Merge "Fix force close of voicemail activity caused by screen rotation"
am: 4c8faa4a0a
Change-Id: I0dcfee81c0cd5a22ca5cafd171471361e9d84b33
diff --git a/Android.mk b/Android.mk
index f3fff79..cbebc44 100644
--- a/Android.mk
+++ b/Android.mk
@@ -11,7 +11,9 @@
LOCAL_JAVA_LIBRARIES := telephony-common voip-common ims-common
LOCAL_STATIC_JAVA_LIBRARIES := \
- guava
+ org.apache.http.legacy \
+ guava \
+ volley
LOCAL_SRC_FILES := $(call all-java-files-under, $(src_dirs))
LOCAL_SRC_FILES += \
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2acf1be..f611706 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -28,6 +28,8 @@
<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" />
<protected-broadcast android:name="android.intent.action.EMERGENCY_CALLBACK_MODE_CHANGED" />
@@ -47,6 +49,7 @@
<protected-broadcast android:name="android.intent.action.DATA_SMS_RECEIVED" />
<protected-broadcast android:name="android.provider.Telephony.SMS_RECEIVED" />
<protected-broadcast android:name="android.provider.Telephony.SMS_DELIVER" />
+ <protected-broadcast android:name="android.provider.Telephony.SMS_REJECTED" />
<protected-broadcast android:name="android.provider.Telephony.WAP_PUSH_DELIVER" />
<protected-broadcast android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
<protected-broadcast android:name="android.provider.Telephony.SMS_CB_RECEIVED" />
@@ -55,9 +58,21 @@
<protected-broadcast android:name= "android.intent.action.stk.session_end" />
<protected-broadcast android:name= "android.intent.action.stk.icc_status_change" />
<protected-broadcast android:name= "android.intent.action.stk.alpha_notify" />
- <protected-broadcast android:name= "android.intent.action.REDIRECTION_DETECTED" />
- <protected-broadcast android:name= "android.intent.action.REQUEST_NETWORK_FAILED" />
+ <protected-broadcast android:name= "android.intent.action.CARRIER_SIGNAL_REDIRECTED" />
+ <protected-broadcast android:name= "android.intent.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED" />
+ <protected-broadcast android:name= "android.intent.action.CARRIER_SIGNAL_PCO_VALUE" />
+ <protected-broadcast android:name= "android.intent.action.VOICEMAIL_SMS_RECEIVED" />
<protected-broadcast android:name= "com.android.intent.isim_refresh" />
+ <protected-broadcast android:name= "com.android.ims.IMS_SERVICE_UP" />
+ <protected-broadcast android:name= "com.android.ims.IMS_SERVICE_DOWN" />
+ <protected-broadcast android:name= "com.android.ims.IMS_INCOMING_CALL" />
+ <protected-broadcast android:name= "com.android.ims.internal.uce.UCE_SERVICE_UP" />
+ <protected-broadcast android:name= "com.android.ims.internal.uce.UCE_SERVICE_DOWN" />
+ <protected-broadcast android:name= "com.android.imsconnection.DISCONNECTED" />
+ <protected-broadcast android:name= "com.android.intent.action.IMS_FEATURE_CHANGED" />
+ <protected-broadcast android:name= "com.android.intent.action.IMS_CONFIG_CHANGED" />
+ <protected-broadcast android:name= "com.android.ims.REGISTRATION_ERROR" />
+ <protected-broadcast android:name= "com.android.phone.vvm.omtp.sms.REQUEST_SENT" />
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
<uses-permission android:name="android.permission.CALL_PHONE" />
@@ -327,7 +342,7 @@
non-voice-capable tablets and regular phone devices. -->
<activity android:name="MobileNetworkSettings"
android:label="@string/settings_label"
- android:theme="@style/SettingsLight">
+ android:theme="@style/NetworkOperatorsSettingsTheme">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.MAIN" />
@@ -354,22 +369,6 @@
</intent-filter>
</activity>
- <activity android:name="GsmUmtsOptions"
- android:label="@string/gsm_umts_options"
- android:theme="@style/DialerSettingsLight">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <activity android:name="CdmaOptions"
- android:label="@string/cdma_options"
- android:theme="@style/DialerSettingsLight">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
<activity android:name="GsmUmtsCallOptions"
android:label="@string/gsm_umts_options"
android:theme="@style/DialerSettingsLight">
@@ -404,14 +403,6 @@
</intent-filter>
</activity>
- <activity android:name="CellBroadcastSms"
- android:label="@string/cell_broadcast_sms"
- android:theme="@android:style/Theme.Holo.DialogWhenLarge">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
<!-- fdn setting -->
<activity android:name="com.android.phone.settings.fdn.FdnSetting"
android:label="@string/fdn"
@@ -456,23 +447,6 @@
android:label="@string/delete_fdn_contact">
</activity>
- <activity android:name="DataRoamingReenable"
- android:label="@string/dialog_alert_title"
- android:theme="@android:style/Theme.Holo.Dialog">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
- <!-- data roaming setting -->
- <activity android:name="RoamingSetting"
- android:label="@string/roaming"
- android:theme="@android:style/Theme.Holo.DialogWhenLarge">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- </intent-filter>
- </activity>
-
<!-- "Call settings" UI, used only on voice-capable phone devices. -->
<activity android:name="CallFeaturesSetting"
android:label="@string/call_settings"
@@ -531,12 +505,6 @@
</activity>
<!-- Start SIP -->
- <service android:name="com.android.services.telephony.sip.SipCallServiceProvider"
- android:singleUser="true" >
- <intent-filter>
- <action android:name="android.telecom.CallServiceProvider" />
- </intent-filter>
- </service>
<service android:name="com.android.services.telephony.sip.SipConnectionService"
android:label="@string/sip_connection_service_label"
android:singleUser="true"
@@ -655,69 +623,86 @@
</intent-filter>
</provider>
<receiver android:name="com.android.phone.vvm.omtp.sms.OmtpMessageReceiver"
- android:exported="true">
+ android:exported="false"
+ androidprv:systemUserOnly="true">
<intent-filter>
- <action android:name="android.intent.action.DATA_SMS_RECEIVED" />
- <data android:scheme="sms" />
+ <action android:name="android.intent.action.VOICEMAIL_SMS_RECEIVED"/>
</intent-filter>
</receiver>
<receiver
android:name="com.android.phone.vvm.omtp.SimChangeReceiver"
- android:exported="true">
+ android:exported="true"
+ androidprv:systemUserOnly="true">
<intent-filter>
<action android:name="android.telephony.action.CARRIER_CONFIG_CHANGED" />
<action android:name="android.intent.action.SIM_STATE_CHANGED" />
</intent-filter>
</receiver>
<receiver
- android:name="com.android.phone.vvm.omtp.OmtpBootCompletedReceiver"
+ android:name="com.android.phone.vvm.omtp.VvmBootCompletedReceiver"
android:exported="true"
- android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
+ android:permission="android.permission.RECEIVE_BOOT_COMPLETED"
+ androidprv:systemUserOnly="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
- <receiver
- android:name="com.android.phone.vvm.omtp.fetch.FetchVoicemailReceiver"
- android:exported="true"
- android:permission="com.android.voicemail.permission.READ_VOICEMAIL">
- <intent-filter>
- <action android:name="android.intent.action.FETCH_VOICEMAIL" />
- <data
- android:scheme="content"
- android:host="com.android.voicemail"
- android:mimeType="vnd.android.cursor.item/voicemail" />
- </intent-filter>
- </receiver>
+ <receiver
+ android:name="com.android.phone.vvm.omtp.fetch.FetchVoicemailReceiver"
+ android:exported="true"
+ android:permission="com.android.voicemail.permission.READ_VOICEMAIL"
+ androidprv:systemUserOnly="true">
+ <intent-filter>
+ <action android:name="android.intent.action.FETCH_VOICEMAIL" />
+ <data
+ android:scheme="content"
+ android:host="com.android.voicemail"
+ android:mimeType="vnd.android.cursor.item/voicemail" />
+ </intent-filter>
+ </receiver>
<receiver
android:name="com.android.phone.vvm.omtp.sync.OmtpVvmSyncReceiver"
android:exported="true"
- android:permission="com.android.voicemail.permission.READ_VOICEMAIL">
+ android:permission="com.android.voicemail.permission.READ_VOICEMAIL"
+ androidprv:systemUserOnly="true">
<intent-filter>
<action android:name="android.provider.action.SYNC_VOICEMAIL"/>
</intent-filter>
</receiver>
- <receiver
- android:name="com.android.phone.vvm.omtp.sync.VoicemailProviderChangeReceiver"
- android:exported="true">
- <intent-filter>
- <action android:name="android.intent.action.PROVIDER_CHANGED" />
- <data
- android:scheme="content"
- android:host="com.android.voicemail"
- android:mimeType="vnd.android.cursor.dir/voicemails"/>
- </intent-filter>
- </receiver>
- <service
- android:name="com.android.phone.vvm.omtp.sync.OmtpVvmSyncService"
- android:exported="false"
- />
- <receiver android:name="com.android.phone.vvm.omtp.VvmPackageInstallReceiver">
- <intent-filter>
- <action android:name="android.intent.action.PACKAGE_INSTALL" />
- <action android:name="android.intent.action.PACKAGE_ADDED" />
- <data android:scheme="package"/>
- </intent-filter>
- </receiver>
+ <receiver
+ android:name="com.android.phone.vvm.omtp.sync.VoicemailProviderChangeReceiver"
+ android:exported="true"
+ androidprv:systemUserOnly="true">
+ <intent-filter>
+ <action android:name="android.intent.action.PROVIDER_CHANGED" />
+ <data
+ android:scheme="content"
+ android:host="com.android.voicemail"
+ android:mimeType="vnd.android.cursor.dir/voicemails"/>
+ </intent-filter>
+ </receiver>
+
+ <service
+ android:name="com.android.phone.vvm.omtp.sms.OmtpProvisioningService"
+ android:exported="false" />
+
+ <service
+ android:name="com.android.phone.vvm.omtp.scheduling.TaskSchedulerService"
+ android:exported="false" />
+
+ <receiver android:name="com.android.phone.vvm.omtp.VvmPackageInstallReceiver"
+ androidprv:systemUserOnly="true">
+ <intent-filter>
+ <action android:name="android.intent.action.PACKAGE_INSTALL" />
+ <action android:name="android.intent.action.PACKAGE_ADDED" />
+ <data android:scheme="package"/>
+ </intent-filter>
+ </receiver>
+
+ <activity android:name=".settings.VoicemailChangePinActivity"
+ android:exported="false"
+ android:theme="@style/DialerSettingsLight"
+ android:windowSoftInputMode="stateVisible|adjustResize">
+ </activity>
</application>
</manifest>
diff --git a/proguard.flags b/proguard.flags
index c4af490..e8646eb 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -1 +1,10 @@
+# Keep classes and methods that have the guava @VisibleForTesting annotation
+-keep @**.VisibleForTesting class *
+-keepclassmembers class * {
+@**.VisibleForTesting *;
+}
+-keep @**.NeededForTesting class *
+-keepclassmembers class * {
+@**.NeededForTesting *;
+}
-verbose
diff --git a/res/layout/voicemail_change_pin.xml b/res/layout/voicemail_change_pin.xml
new file mode 100644
index 0000000..b0db64b
--- /dev/null
+++ b/res/layout/voicemail_change_pin.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2014, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:orientation="vertical">
+ <!-- header text ('Enter Pin') -->
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingTop="48dp"
+ android:paddingStart="48dp"
+ android:paddingEnd="48dp">
+ <TextView
+ android:id="@+id/headerText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:lines="2"
+ android:textAppearance="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle"
+ android:accessibilityLiveRegion="polite"/>
+
+ <!-- hint text ('PIN too short') -->
+ <TextView
+ android:id="@+id/hintText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:lines="2" />
+
+ <!-- error text ('PIN too short') -->
+ <TextView
+ android:id="@+id/errorText"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:lines="2"
+ android:textColor="@android:color/holo_red_dark"/>
+
+ <!-- Password entry field -->
+ <EditText
+ android:id="@+id/pin_entry"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:gravity="center"
+ android:imeOptions="actionNext|flagNoExtractUi"
+ android:inputType="numberPassword"
+ android:textSize="24sp"/>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:gravity="end"
+ android:orientation="horizontal">
+
+ <!-- left : cancel -->
+ <Button
+ android:id="@+id/cancel_button"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:text="@string/change_pin_cancel_label"/>
+
+ <!-- right : continue -->
+ <Button
+ android:id="@+id/next_button"
+ android:layout_width="0dp"
+ android:layout_weight="1"
+ android:layout_height="wrap_content"
+ android:text="@string/change_pin_continue_label"/>
+
+ </LinearLayout>
+</LinearLayout>
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index f0bcc3a..442caa5 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Geen veranderinge is gemaak nie."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Kies stemboodskapdiens"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Jou diensverskaffer"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Ou PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nuwe PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Wag asseblief."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Die nuwe PIN is te kort."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Die nuwe PIN is te lank."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Die nuwe PIN is te swak. \'n Sterk wagwoord moenie daaropvolgend wees of syfers bevat wat herhaal nie."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Die ou PIN pas nie."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Die nuwe PIN bevat ongeldige karakters."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Kan nie PIN verander nie"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Ongesteunde tipe boodskap, bel <xliff:g id="NUMBER">%s</xliff:g> om te luister."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Selnetwerkinstellings"</string>
<string name="label_available" msgid="1181658289009300430">"Beskikbare netwerke"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Soek tans…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA verkies"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Verbeterde 4G LTE-modus"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Gevorderde oproepe"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Gebruik LTE-dienste om stem- en ander kommunikasie te verbeter (aanbeveel)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data geaktiveer"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Laat datagebruik toe"</string>
@@ -440,6 +451,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Sellulêre netwerk is nie beskikbaar nie. Koppel aan \'n draadlose netwerk om \'n oproep te maak."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Voer \'n geldige nommer in om \'n oproep te maak."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Oproep het misluk."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Oproep kan nie op die oomblik bygevoeg word nie."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Begin MMI-volgorde…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Diens word nie gesteun nie"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Kan nie oproepe wissel nie."</string>
@@ -450,6 +462,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Kan nie oproep(e) vrystel nie."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Kan nie oproepe aanhou nie."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Koppel aan \'n draadlose netwerk om \'n oproep te maak."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Aktiveer Wi-Fi-oproepe om \'n oproep te maak."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Noodoproep"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Skakel tans radio aan…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Geen sein nie. Probeer tans weer …"</string>
@@ -544,6 +557,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibreer"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibreer"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visuele stemboodskapdiens"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Stel PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Verander PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Klank"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Luitoon en vibreer"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Ingeboude SIM-kaarte"</string>
@@ -555,10 +570,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Net noodoproepe"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-kaart, gleuf: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Toeganklikheid"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Inkomende Wi-Fi-oproep"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi-oproep vanaf"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi-oproep"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Tik weer om oop te maak"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Kon nie die boodskap dekodeer nie."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"\'n SIM-kaart het jou diens geaktiveer en jou foon se swerwingvermoëns opgedateer."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Daar is te veel aktiewe oproepe. Beëindig of voeg asseblief bestaande oproepe saam voordat jy \'n nuwe een maak."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Verander stemboodskap-PIN"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Gaan voort"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Kanselleer"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Bevestig jou ou PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Voer jou stemboodskap-PIN in om voort te gaan."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Stel \'n nuwe PIN op"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN moet <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> syfers wees."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Bevestig jou PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN\'s stem nie ooreen nie"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Stemboodskap-PIN is opgedateer"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Kan nie PIN stel nie"</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index d7da5f1..556569c 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"ምንም ለውጥ አልተደረገም።"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"የድምፅ መልዕክት አገልግሎት ምረጥ"</string>
<string name="voicemail_default" msgid="2001233554889016880">"የእርስዎ ድምጸ ተያያዥ ሞደም"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"የቀድሞ ፒን"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"አዲስ ፒን"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"እባክዎ ይጠብቁ።"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"አዲሱ ፒን በጣም አጭር ነው።"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"አዲሱ ፒን በጣም ረጅም ነው።"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"አዲሱ ፒን በጣም ደካማ ነው። ጠንካራ የይለፍ ቃል ተከታታይ ቅጥልጥል ወይም ተደጋጋሚ አኃዞች ሊኖሩት አይገባም።"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"የቀድሞ ፒን አልተዛመደም።"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"አዲሱ ፒን ልክ ያልሆኑ ቁምፊዎችን ይዟል።"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"ፒን መቀየር አልተቻለም።"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"የማይደገፍ የመልዕክት አይነት፤ ለማዳመጥ ወደ <xliff:g id="NUMBER">%s</xliff:g> ይደውሉ።"</string>
<string name="mobile_networks" msgid="2843854043339307375">"የተንቀሳቃሽ ስልክ አውታረ መረብ ቅንብሮች"</string>
<string name="label_available" msgid="1181658289009300430">"የሚገኙ አውታረመረቦች"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"በመፈለግ ላይ…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM / WCDMA ተመራጭ"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"የተሻሻለ የ4ጂ LTE ሁነታ"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"የላቀ ጥሪ ማድረግ"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"የድምፅ እና ሌሎች የመልዕክት ልውውጦችን ለማሻሻል LTE አገልግሎቶችን ይጠቀሙ (የሚመከር)"</string>
<string name="data_enabled" msgid="5972538663568715366">"ውሂብ ነቅቷል"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"የውሂብ አጠቃቀም ፍቀድ"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"የተንቀሳቃሽ ስልክ አውታረ መረብ አይገኝም። ጥሪ ለማድረግ ወደ ሽቦ አልባ አውታረ መረብ ያገናኙ።"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"አንድ ጥሪ ለማድረግ የሚሰራ ቁጥር ያስገቡ።"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"ጥሪ አልተሳካም።"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ጥሪ በአሁኑ ጊዜ ሊታከል አይችልም።"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"የMMI sequence…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"አገልግሎት አይደገፍም"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"ጥሪዎችን መቀያየር አልተቻለም።"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"ጥሪ(ዎች)ን መልቀቅ አልተቻለም።"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"ጥሪዎችን መያዝ አልተቻለም።"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ጥሪ ለማድረግ ወደ ሽቦ አልባ አውታረ መረብ ያገናኙ።"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"ጥሪ ለማድረግ Wi-Fi ጥሪን ያንቁ።"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"የአደጋ ጊዜ ጥሪ"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"ሬዲዮ ክፈት"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"ምንም አገልግሎት የለም። ዳግም በመሞከር ላይ…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"ንዘር"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"ንዘር"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"ምስላዊ የድመጽ መልዕከት"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"ፒን ያዘጋጁ"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"ፒን ቀይር"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ድምፅ"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"የደወል ቅላጼ እና ንዘረት"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"አብሮገነብ ሲም ካርዶች"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"የአደጋ ጥሪዎችን ብቻ ለማድረግ"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM ካርድ፣ ማስገቢያ ቀዳዳ፦ <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ተደራሽነት"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"ገቢ የWi-Fi ጥሪ"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"የWi-Fi ጥሪ ከ"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"የWi-Fi ጥሪ"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"ለመክፈት ዳግም ነካ ያድርጉ"</string>
<string name="message_decode_error" msgid="3456481534066924855">"መልዕክቱን በማመሳጠር ላይ ስህተት ነበር።"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"አንድ ሲም ካርድ አገልግሎትዎን ገቢር አድርጎታል፣ እንዲሁም የስልክዎን የማስተላለፍ ችሎታዎችን አዘምኗል።"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"እጅግ በጣም ብዙ ንቁ ጥሪዎች አሉ። እባክዎ አዲስ ከማስቀመጥዎ በፊት ያሉትን ጥሪዎች ይጨርሱ ወይም ያዋህዱ።"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"የድምፅ መልዕክት ፒን ለውጥ"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"ቀጥል"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"ይቅር"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"እሺ"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"የድሮውን ፒን ያረጋግጡ"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"ለመቀጠል የድምፅ መልዕክት ፒንዎን ያስገቡ።"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"አዲስ ፒን ያዘጋጁ"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"ፒን ከ <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="8113764019347322170">"ፒንዎን ያረጋግጡ"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"ፒኖች አይዛመዱም"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"የድምፅ መልዕክት ፒን ዘምኗል"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"ፒን ማዘጋጀት አልተቻለም"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index c5e57b0..607ba3d 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"لم يتم إجراء أية تغييرات."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"اختيار خدمة البريد الصوتي"</string>
<string name="voicemail_default" msgid="2001233554889016880">"مشغل شبكة الجوّال"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"رقم التعريف الشخصي القديم"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"رقم التعريف الشخصي الجديد"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"الرجاء الانتظار."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"رقم التعريف الشخصي الجديد قصير جدًا."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"رقم التعريف الشخصي الجديد طويل جدًا."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"رقم التعريف الشخصي الجديد ضعيف جدًا. لا ينبغي أن تكون كلمة المرور القوية عبارة عن تسلسل متتالٍ أو أرقام متكررة."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"رقم التعريف الشخصي القديم غير مُطابِق."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"رقم التعريف الشخصي الجديد يحتوي على أحرف غير صالحة."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"غير قادر على تغيير رقم التعريف الشخصي"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"نوع الرسالة غير معتمد، اتصل على <xliff:g id="NUMBER">%s</xliff:g> لسماعها."</string>
<string name="mobile_networks" msgid="2843854043339307375">"إعدادات شبكة الجوّال"</string>
<string name="label_available" msgid="1181658289009300430">"الشبكات المتاحة"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"جارِ البحث…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA المفضل"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"وضع 4G LTE المحسّن"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"اتصال متقدم"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"استخدام خدمات LTE لتحسين الصوت والاتصالات الأخرى (مستحسن)"</string>
<string name="data_enabled" msgid="5972538663568715366">"تم تمكين البيانات"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"السماح باستخدام البيانات"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"شبكة الجوّال ليست متوفرة. اتصل بشبكة لاسلكية لإجراء مكالمة."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"لإجراء مكالمة، أدخل رقمًا صالحًا."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"أخفقت المكالمة."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"لا يمكن إضافة مكالمة في الوقت الحالي."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"جارٍ بدء تسلسل MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"الخدمة ليست متوفرة"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"يتعذر تبديل المكالمات."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"يتعذر تحرير المكالمات."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"يتعذر وضع المكالمات قيد الانتظار."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"اتصل بشبكة لاسلكية لإجراء مكالمة."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"يمكنك تمكين اتصال Wi-Fi لإجراء مكالمة."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"مكالمة الطوارئ"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"جارٍ تشغيل اللاسلكي..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"لا تتوفر خدمة. جارٍ إعادة المحاولة…"</string>
@@ -552,6 +565,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"الاهتزاز"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"الاهتزاز"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"بريد صوتي مرئي"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"تعيين رقم التعريف الشخصي"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"تغيير رقم التعريف الشخصي"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"الصوت"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"نغمة الرنين والاهتزاز"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"بطاقات SIM مدمجة"</string>
@@ -563,10 +578,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"مكالمات الطوارئ فقط"</string>
<string name="sim_description_default" msgid="4778679519938775515">"شريحة SIM، المنفذ: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"إمكانية الوصول"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"مكالمة واردة عبر Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"مكالمة Wi-Fi من"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"مكالمة عبر Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"انقر مرة أخرى للفتح."</string>
<string name="message_decode_error" msgid="3456481534066924855">"حدث خطأ أثناء فك ترميز الرسالة."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"نشطت شريحة SIM خدمتك وحدّثت إمكانات التجوال لهاتفك."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"هناك الكثير من المكالمات النشطة. يرجى إنهاء أو دمج المكالمات الموجودة قبل إجراء مكالمة جديدة."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"تغيير رقم التعريف الشخصي للبريد الصوتي"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"متابعة"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"إلغاء"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"موافق"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"تأكيد رقم التعريف الشخصي القديم"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"أدخل رقم التعريف الشخصي لبريدك الصوتي للمتابعة."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"تعيين رقم تعريف شخصي جديد"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"ينبغي لرقم التعريف الشخصي أن يتكون من <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="8113764019347322170">"تأكيد رقم التعريف الشخصي"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"أرقام التعريف الشخصي غير متطابقة"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"تمّ تحديث رقم التعريف الشخصي للبريد الصوتي"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"يتعذر تعيين رقم التعريف الشخصي"</string>
</resources>
diff --git a/res/values-az-rAZ/strings.xml b/res/values-az-rAZ/strings.xml
index a76abfc..d29db42 100644
--- a/res/values-az-rAZ/strings.xml
+++ b/res/values-az-rAZ/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Heç bir dəyişiklik edilmədi."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Səsli poçt xidmətinizi seçin"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operatorunuz"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Köhnə PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Yeni PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Lütfən, gözləyin."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Yeni PIN kod çox qısadır."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Yeni PIN kod çox uzundur."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Yeni PIN kod çox zəifdir. Güclü parol ardıcıllıqdan və ya təkrarlanan rəqəmlərdən ibarət olmamalıdır."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Köhnə PIN kod uyğun gəlmir."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Yeni PIN kod yanlış simvollardan ibarətdir."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN kodu dəyişmək mümkün olmadı"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Dəstəklənməyən mesaj növü, qulaq asmaq üçün <xliff:g id="NUMBER">%s</xliff:g> nömrəsinə zəng edin."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobil şəbəkə ayarları"</string>
<string name="label_available" msgid="1181658289009300430">"Əlçatımlı şəbəkələr"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Axtarılır..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA\'ya üstünlük verilib"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Təkmil 4G LTE Rejimi"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Qabaqcıl Zəng"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Səs və digər kommunikasiyaları təkmilləşdirmək üçün LTE xidmətlərindən istifadə edin (tövsiyə olunur)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data aktivdir"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Data istifadəsinə icazə verin"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobil şəbəkə əlçatmazdır. Zəng etmək üçün Wi-Fi şəbəkəsinə qoşulun."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Zəngi yerləşdirmək üçün düzgün nömrə daxil edin."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Zəng alınmadı."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Hazırda çağrı edilə bilməz."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI başlanma ardıcıllığı…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Xidmət dəstəklənmir"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Zəngləri keçirmək mümkün deyil."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Zəngləri buraxmaq mümkün deyil."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Zənglər saxlanıla bilməz."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Zəng etmək üçün Wi-Fi şəbəkəsinə qoşulun."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Zəng etmək üçün Wi-Fi zəngini dəyişdirin."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Təcili zəng"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Radio yandırılır ..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Xidmət yoxdur. Yenidən cəhd edilir…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrasiya"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrasiya"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vizual Səsli Mesaj"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN kodu ayarlayın"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN kodu dəyişin"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Səs"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Zəng səsi & Vibrasiya"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Daxili SIM kartlar"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Yalnız təcili zəng"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM kart, yuva: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Münasiblik"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Gələn Wi-Fi zəngi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi zəngi"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi zəng"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Açmaq üçün yenidən tıklayın"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Mesaj dekod edilən zaman xəta oldu."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM kart xidmətinizi aktivləşdirdi və telefonunuzun rominq imkanlarını güncəlləşdi."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Burada həddindən çox aktiv zəng var. Yeni birini yerləşdirmək üçün mövcud zəngləri sonlandırın və ya birləşdirin."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Səsli poçtun PIN kodunu dəyişin"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Davam edin"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Ləğv edin"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Ok"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Köhnə PIN kodu təsdiq edin"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Davam etmək üçün səsli poçtun PIN kodunu daxil edin"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Yeni PIN kodu təyin edin"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> rəqəm olmalıdır."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"PİN kodunuzu təsdiq edin"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN kodlar üst-üstə düşmür"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Səsli poçtun PIN kodu yeniləndi"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN kodu ayarlamaq olmur"</string>
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 3829920..946ad38 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Не бяха направени промени."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Избор на услугата за гласова поща"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Вашият оператор"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Стар ПИН"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Нов ПИН"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Моля, изчакайте."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Новият ПИН е твърде къс."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Новият ПИН е твърде дълъг."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Новият ПИН не е достатъчно надежден. Надеждната парола не бива да има последователни или повтарящи се цифри."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Старият ПИН не съответства."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Новият ПИН съдържа невалидни знаци."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Промяната на ПИН не е възможна"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Типът на съобщението не се поддържа. Обадете се на <xliff:g id="NUMBER">%s</xliff:g>, за да го чуете."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Настройки за клетъчна мрежа"</string>
<string name="label_available" msgid="1181658289009300430">"Налични мрежи"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Търси се…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Предпочита се GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Подобрен режим с 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Разширени обаждания"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Ползване на LTE услуги за подобряване на гласовите и др. комуникации (препоръч.)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Данните са активирани"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Разрешаване на преноса на данни"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Не е налице клетъчна мрежа. Свържете се с безжична, за да осъществите обаждане."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"За да извършите обаждане, въведете валиден номер."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Обаждането не бе успешно."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Понастоящем обаждането не може да бъде добавено."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Стартира се последователността MMI…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Услугата не се поддържа"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Обажданията не могат да се превключат."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Обаждането или съответно обажданията не могат да се освободят."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Не може да се извършват обаждания."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Свържете се с безжична мрежа, за да осъществите обаждане."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"За да извършите обаждане, активирайте обажданията през Wi-Fi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Спешно обаждане"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Радиото се включва…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Няма услуга. Извършва се нов опит…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Вибриране"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Вибриране"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Визуална гласова поща"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Задаване на ПИН"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Промяна на ПИН"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Звук"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Мелодия и вибриране"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Вградени SIM карти"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Само спешни обаждания"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM карта, слот: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Достъпност"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Вход. обаждане през Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Обаждане през Wi-Fi от"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Обаждане през Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Докоснете отново, за да отворите"</string>
<string name="message_decode_error" msgid="3456481534066924855">"При декодирането на съобщението възникна грешка."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM картата е активирала клетъчните ви услуги и е актуализирала възможностите за роуминг на телефона ви."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Активните обаждания са твърде много. Моля, завършете или обединете съществуващи обаждания, преди да започнете ново."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Промяна на ПИН за гласовата поща"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Напред"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Отказ"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Потвърдете стария си ПИН"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"За да продължите, въведете ПИН за гласовата си поща."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Задайте нов ПИН"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"ПИН трябва да съдържа между <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="8113764019347322170">"Потвърдете своя ПИН"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"ПИН кодовете не съвпадат"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"ПИН за гласовата поща бе актуализиран"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"ПИН не може да бъде зададен"</string>
</resources>
diff --git a/res/values-bn-rBD/strings.xml b/res/values-bn-rBD/strings.xml
index 3c9411e..eb870ae 100644
--- a/res/values-bn-rBD/strings.xml
+++ b/res/values-bn-rBD/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"কোনো পরিবর্তন করা হয়নি৷"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"ভয়েসমেল পরিষেবা বেছে নিন"</string>
<string name="voicemail_default" msgid="2001233554889016880">"আপনার পরিষেবা প্রদানকারী"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"পুরানো পিন"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"নতুন পিন"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"অনুগ্রহ করে অপেক্ষা করুন৷"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"নতুন পিনটি খুবই ছোট৷"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"নতুন পিনটি খুবই বড়৷"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"নতুন পিনটি খুবই দুর্বল৷ একটি শক্তিশালী পাসওয়ার্ডে ধারাবাহিক ক্রম বা পুনরাবৃত্ত সংখ্যা থাকা উচিৎ নয়৷"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"পুরানো পিন মিলছে না৷"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"নতুন পিনে অবৈধ অক্ষর রয়েছে৷"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"পিন পরিবর্তন করা গেল না"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"এই ধরণের বার্তা সমর্থিত নয় , শুোনার জন্য <xliff:g id="NUMBER">%s</xliff:g> এ কল করুন৷"</string>
<string name="mobile_networks" msgid="2843854043339307375">"সেলুলার নেটওয়ার্ক সেটিংস"</string>
<string name="label_available" msgid="1181658289009300430">"উপলব্ধ নেটওয়ার্কগুলি"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"অনুসন্ধান করছে..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA সুবিধাজনক"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"উন্নত 4G LTE মোড"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"উন্নত কলিং"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"ভয়েস এবং অন্যান্য যোগাযোগব্যবস্থা উন্নত করতে LTE পরিষেবা ব্যবহার করুন (প্রস্তাবিত)"</string>
<string name="data_enabled" msgid="5972538663568715366">"ডেটা সক্ষম করা হয়েছে"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"ডেটা ব্যবহারের অনুমতি দিন"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"মোবাইল নেটওয়ার্ক উপলব্ধ নেই৷ একটি কল করতে কোনো ওয়্যারলেস নেটওয়ার্কে সংযোগ করুন৷"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"কোনো কল স্থাপন করতে, একটি বৈধ নম্বর লিখুন৷"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"কল ব্যর্থ হয়েছে৷"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"এই মুহূর্তে কল যোগ করা যাবে না৷"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI ক্রম চালু হচ্ছে…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"পরিষেবা সমর্থিত নয়"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"কলগুলি স্যুইচ করা যাবে না৷"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"কল(গুলি) কাটা যাবে না৷"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"কলগুলি ধরে রাখা যাবে না।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"একটি কল করতে কোনো ওয়্যারলেস নেটওয়ার্কে সংযোগ করুন৷"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"কোনো কল করতে Wi-Fi কলিং সক্ষম করুন৷"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"জরুরি কল"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"রেডিও চালু করা হচ্ছে…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"কোন পরিষেবা নেই৷ আবার চেষ্টা করা হচ্ছে..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"কম্পন"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"কম্পন"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"ভিজ্যুয়াল ভয়েসমেল"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN সেট করুন"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"পিন পরিবর্তন করুন"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"শব্দ"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"রিংটোন ও কম্পন"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"বিল্ট-ইন সিম কার্ডগুলি"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"শুধুমাত্র জরুরী কলিং"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM কার্ড, স্লট: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"অ্যাক্সেসযোগ্যতা"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"আগত ওয়াই-ফাই কল"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"এর থেকে Wi-Fi কল"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"ওয়াই-ফাই কল"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"খোলার জন্য আবার আলতো চাপুন"</string>
<string name="message_decode_error" msgid="3456481534066924855">"বার্তাটি ডিকোড করার সময় একটি ত্রুটি ঘটেছে৷"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"একটি SIM কার্ড আপনার পরিষেবা সক্রিয় করেছে এবং আপনার ফোনের রোমিং ক্ষমতা আপডেট করা হয়েছে৷"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"অনেকগুলি কল সক্রিয় রয়েছে। অনুগ্রহ করে একটি নতুন কল করার আগে বিদ্যমান কলগুলি কেটে দিন বা এটিকে সেই কলগুলিতে অন্তর্ভুক্ত করুন।"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"ভয়েসমেলের PIN পরিবর্তন করুন"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"চালিয়ে যান"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"বাতিল করুন"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ঠিক আছে"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"আপনার পুরানো PIN নিশ্চিত করুন"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"চালিয়ে যেতে আপনার ভয়েসমেলের PIN লিখুন৷"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"একটি নতুন PIN সেট করুন"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN অবশ্যই <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="8113764019347322170">"আপনার PIN নিশ্চিত করুন"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PINগুলি মিলছে না"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"ভয়েসমেলের PIN আপডেট করা হয়েছে"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN সেট করা গেল না"</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index b3ed481..67d99ae 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -85,7 +85,7 @@
<string name="additional_cdma_call_settings" msgid="8628958775721886909">"Configuració addicional de trucades CDMA"</string>
<string name="sum_cdma_call_settings" msgid="284753265979035549">"Configuració addicional de trucades només CDMA"</string>
<string name="labelNwService" msgid="4699970172021870983">"Configuració del servei de xarxa"</string>
- <string name="labelCallerId" msgid="3888899447379069198">"Identificador de l\'emissor"</string>
+ <string name="labelCallerId" msgid="3888899447379069198">"Identificador de trucada"</string>
<string name="sum_loading_settings" msgid="1826692909391168620">"Carregant la configuració..."</string>
<string name="sum_hide_caller_id" msgid="1071407020290873782">"Número amagat en trucades sortints"</string>
<string name="sum_show_caller_id" msgid="6768534125447290401">"Número mostrat a les trucades de sortida"</string>
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"No s\'ha fet cap canvi."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Trieu un servei de bústia de veu"</string>
<string name="voicemail_default" msgid="2001233554889016880">"EL teu operador"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN antic"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"PIN nou"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Espera un moment."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"El PIN nou és massa curt."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"El PIN nou és massa llarg."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"El PIN nou no és prou segur. Les contrasenyes segures no poden contenir seqüències contínues ni dígits repetits."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"El PIN antic no coincideix."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"El PIN nou conté caràcters que no són vàlids."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"No es pot canviar el PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Aquest tipus de missatge no s\'admet. Truca al <xliff:g id="NUMBER">%s</xliff:g> per escoltar-lo."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Configuració de la xarxa mòbil"</string>
<string name="label_available" msgid="1181658289009300430">"Xarxes disponibles"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"S\'està cercant…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferit"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Mode 4G LTE millorat"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Trucades avançades"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Utilitza els serveis LTE per millorar la veu i la comunicació (opció recomanada)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Dades activades"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Permet l\'ús de dades"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"La xarxa mòbil no està disponible. Per fer una trucada, connecta amb una xarxa sense fil."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Per realitzar una trucada, introdueix un número vàlid."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"No s\'ha pogut fer la trucada."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"En aquest moment no es pot afegir la trucada."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"S\'està iniciant la seqüència MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"El servei no és compatible."</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"No es pot canviar de trucada."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"No es poden alliberar trucades."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"No es poden posar les trucades en espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Per fer una trucada, connecta amb una xarxa sense fil."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Activa les trucades per Wi-Fi per fer una trucada."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Trucada d\'emergència"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"S\'està activant el senyal mòbil..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"No hi ha servei. S\'està tornant a provar..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibra"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibra"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Bústia de veu visual"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Defineix el PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Canvia el PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"So"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"So i vibració"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Targetes SIM integrades"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Només trucades d\'emergència"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Targeta SIM, ranura: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accessibilitat"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Trucada per Wi-Fi entrant"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Trucada per Wi-Fi de"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Trucada per Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Torna a tocar per obrir"</string>
<string name="message_decode_error" msgid="3456481534066924855">"S\'ha produït un error en descodificar el missatge."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Una targeta SIM ha activat el servei, i s\'ha actualitzat la funció d\'itinerància del telèfon."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Hi ha massa trucades actives. Finalitza\'n alguna o combina-les abans de fer-ne una de nova."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Canvia el PIN per a la bústia de veu"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continua"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancel·la"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"D\'acord"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirma el teu PIN antic"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Introdueix el teu PIN per a la bústia de veu per continuar."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Defineix un PIN nou"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"El PIN ha de tenir <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> dígits."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirma el teu PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Els PIN no coincideixen"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"S\'ha actualitzat el PIN per a la bústia de veu"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"No s\'ha pogut definir el PIN"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index d7fe3f3..058fe26 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Nebyly provedeny žádné změny."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Zvolte službu hlasové schránky"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Váš operátor"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Starý kód PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nový kód PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Čekejte prosím."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Nový kód PIN je příliš krátký."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Nový kód PIN je příliš dlouhý."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Nový kód PIN je příliš slabý. Silný kód by neměl obsahovat postupnou řadu čísel ani opakující se čísla."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Starý kód PIN se neshoduje."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Nový kód PIN obsahuje neplatné znaky."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Kód PIN se nepodařilo změnit"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Nepodporovaný typ zprávy, pokud si ji chcete poslechnout zavolejte na číslo <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Nastavení mobilní sítě"</string>
<string name="label_available" msgid="1181658289009300430">"Dostupné sítě"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Vyhledávání..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA – preferováno"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Vylepšený režim 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Rozšířené volání"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Používat ke zlepšení hlasové a další komunikace služby LTE (doporučeno)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Dat. přenosy aktivovány"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Povolit používání dat"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobilní síť není k dispozici. Chcete-li provést hovor, připojte se k bezdrátové síti."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Chcete-li uskutečnit hovor, zadejte platné telefonní číslo."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Volání se nezdařilo."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Hovor teď není možné přidat."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Spouštění sekvence MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Služba není podporována."</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Hovory nelze přepnout."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Hovor nelze ukončit."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Hovory nelze podržet."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Chcete-li provést hovor, připojte se k bezdrátové síti."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Pokud chcete provést hovor, povolte volání přes připojení Wi-Fi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Tísňové volání"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Zapínání rádia..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Služba je nedostupná. Probíhá další pokus…"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrace"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrace"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vizuální hlasová schránka"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Nastavte kód PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Změnit kód PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Zvuk"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Vyzvánění a vibrace"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Vestavěné SIM karty"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Pouze tísňová volání"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM karta, slot: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Přístupnost"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Příchozí hovor přes Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Hovor přes Wi-Fi:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Volání přes Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Akci provedete opětovným klepnutím"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Při dekódování zprávy došlo k chybě."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM karta aktivovala vaši službu a byly aktualizovány roamingové možnosti telefonu."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Máte příliš mnoho aktivních hovorů. Ukončete nebo spojte stávající hovory, než zahájíte nový."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Změňte kód PIN hlasové schránky"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Pokračovat"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Zrušit"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Potvrďte starý kód PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Pokud chcete pokračovat, zadejte kód PIN hlasové schránky."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Nastavte nový kód PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN musí mít <xliff:g id="MIN">%1$d</xliff:g> až <xliff:g id="MAX">%2$d</xliff:g> číslic."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Potvrďte kód PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Kódy PIN nejsou shodné"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Kód PIN hlasové schránky byl změněn"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Kód PIN se nepodařilo nastavit"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 435ca41..f73f491 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Der blev ikke foretaget nogen ændringer."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Vælg telefonsvarertjeneste"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Dit mobilselskab"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Nuværende pinkode"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Ny pinkode"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Vent et øjeblik."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Den nye pinkode er for kort."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Den nye pinkode er for lang."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Denne pinkode er for svag. En stærk adgangskode består ikke af en række tal og har ikke flere af de samme tal efter hinanden."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Den gamle pinkode er forkert."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Den nye pinkode har ugyldige tegn."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Pinkoden kan ikke ændres"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Ikke-understøttet beskedtype. Ring til <xliff:g id="NUMBER">%s</xliff:g> for at aflytte."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Indstillinger for mobilnetværk"</string>
<string name="label_available" msgid="1181658289009300430">"Tilgængelige netværk"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Søger..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA foretrækkes"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Udvidet 4G LTE-tilstand"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Avancerede opkald"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Anvend LTE-tjenester til at forbedre tale og anden kommunikation (anbefalet)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data aktiveret"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Tillad dataforbrug"</string>
@@ -442,6 +453,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobilnetværk er ikke tilgængeligt. Opret forbindelse til et trådløst netværk for at foretage et opkald."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Indtast et gyldigt nummer for at foretage et opkald."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Opkald mislykkedes."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Opkaldet kan ikke tilføjes på nuværende tidspunkt."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Starter MMI-sekvens ..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Tjenesten er ikke understøttet"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Kan ikke skifte opkald."</string>
@@ -452,6 +464,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Kan ikke frigive et eller flere opkald."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Opkald kan ikke sættes i venteposition."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Opret forbindelse til et trådløst netværk for at foretage et opkald."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Aktivér Wi-Fi-opkald for at foretage et opkald."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Nødopkald"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Tænder for radio ..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ingen tjeneste. Prøver igen..."</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibration"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibration"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visuel telefonsvarer"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Angiv pinkode"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Skift pinkode"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Lyd"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ringetone og vibration"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Indbyggede SIM-kort"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Kun nødopkald"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-kortrille: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Hjælpefunktioner"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Indgående Wi-Fi-opkald"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi-opkald fra"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi-opkald"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Tryk igen for at åbne"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Der opstod en fejl under afkodning af beskeden."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Et SIM-kort har aktiveret din tjeneste og opdateret telefonens roamingmuligheder."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Der er for mange aktive opkald. Afslut et opkald, eller flet eksisterende opkald, inden du foretager et nyt."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Skift pinkode til din telefonsvarer"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Fortsæt"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Annuller"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Bekræft din gamle pinkode"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Angiv din pinkode til din telefonsvarer for at fortsætte."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Angiv en ny pinkode"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Pinkoden skal være på <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> cifre."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Bekræft din pinkode"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Pinkoderne er ikke ens"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Pinkode til din telefonsvarer blev opdateret"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Pinkoden kan ikke angives"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 5dad837..7486439 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Es wurden keine Änderungen vorgenommen."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Mailbox-Dienst auswählen"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Mobilfunkanbieter"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Alte PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Neue PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Bitte warten."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Die neue PIN ist zu kurz."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Die neue PIN ist zu lang."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Die neue PIN ist zu unsicher. Ein sicheres Passwort sollte keine aufeinanderfolgenden oder wiederholten Zeichen enthalten."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Die alte PIN stimmt nicht überein."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Die neue PIN enthält ungültige Zeichen."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN kann nicht geändert werden"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Nicht unterstützter Nachrichtentyp, zum Abhören <xliff:g id="NUMBER">%s</xliff:g> anrufen."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Einstellungen für Mobilfunknetze"</string>
<string name="label_available" msgid="1181658289009300430">"Verfügbare Netzwerke"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Suche läuft..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA bevorzugt"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Erweiterter 4G LTE-Modus"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Erweiterte Anruffunktionen"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Zur Verbesserung von Sprache und Kommunikation LTE-Dienste verwenden (empfohlen)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Daten aktiviert"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Datennutzung zulassen"</string>
@@ -440,6 +451,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Es ist kein Mobilfunknetz verfügbar. Stelle zum Telefonieren eine WLAN-Verbindung her."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Gib eine gültige Nummer ein."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Fehler beim Anruf."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Der Anruf kann momentan nicht hinzugefügt werden."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI-Sequenz wird gestartet..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Dienst wird nicht unterstützt"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Anruf kann nicht gewechselt werden."</string>
@@ -450,6 +462,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Anrufe können nicht freigegeben werden."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Anrufe können nicht gehalten werden."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Stelle zum Telefonieren eine WLAN-Verbindung her."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Aktiviere Anrufe über WLAN, um anzurufen."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Notruf"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Mobilfunkverbindung wird aktiviert..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Kein Service. Erneuter Versuch..."</string>
@@ -544,6 +557,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibration"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibration"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visuelle Mailbox"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN festlegen"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN ändern"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Töne"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Klingelton & Vibration"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Integrierte SIM-Karten"</string>
@@ -555,10 +570,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Nur Notrufe"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-Karte, Schacht: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Bedienungshilfen"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Eingehender WLAN-Anruf"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"WLAN-Anruf von"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"WLAN-Anruf"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Zum Öffnen erneut tippen"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Beim Entschlüsseln der Nachricht ist ein Fehler aufgetreten."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Eine SIM-Karte hat deinen Dienst aktiviert und die Roamingfunktionen deines Smartphones aktualisiert."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Zu viele aktive Anrufe. Beende aktive Anrufe oder führe sie zusammen, bevor du einen neuen Anruf tätigst."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Mailbox-PIN ändern"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Weiter"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Abbrechen"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Alte PIN bestätigen"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Gib zum Fortfahren deine Mailbox-PIN ein."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Neue PIN festlegen"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN muss <xliff:g id="MIN">%1$d</xliff:g> - <xliff:g id="MAX">%2$d</xliff:g> Zeichen umfassen."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"PIN bestätigen"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Die PINs stimmen nicht überein"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Mailbox-PIN aktualisiert"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Festlegen der PIN nicht möglich"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index d791f02..d7a02e9 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Δεν έγιναν αλλαγές."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Επιλογή υπηρεσίας αυτόματου τηλεφωνητή"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Ο πάροχος κινητής τηλεφωνίας"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Παλιό PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Νέο PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Περιμένετε."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Το νέο PIN είναι πολύ μικρό."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Το νέο PIN είναι πολύ μεγάλo."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Το νέο PIN είναι πολύ αδύναμο. Ένας ισχυρός κωδικός πρόσβασης δεν θα πρέπει να αποτελείται από ακολουθίες χαρακτήρων ή επαναλαμβανόμενα ψηφία."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Το παλιό PIN δεν αντιστοιχεί."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Το νέο PIN περιέχει μη έγκυρους χαρακτήρες."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Δεν είναι δυνατή η αλλαγή του PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Μη υποστηριζόμενος τύπος μηνύματος: καλέστε στο <xliff:g id="NUMBER">%s</xliff:g> για να το ακούσετε."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Ρυθμίσεις δικτ. κιν. τηλ."</string>
<string name="label_available" msgid="1181658289009300430">"Διαθέσιμα δίκτυα"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Αναζήτηση..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Προτιμώνται GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Βελτιωμένη λειτουργία 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Προηγμένες λειτουργίες κλήσης"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Χρήση υπηρεσιών LTE για τη βελτίωση της φωνητικής επικοινωνίας και άλλου είδους επικοινωνιών (συνιστάται)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Ενεργοποίηση δεδομένων"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Επιτρέπεται η χρήση δεδομένων"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Το δίκτυο κινητής τηλεφωνίας δεν είναι διαθέσιμο. Συνδεθείτε σε ένα ασύρματο δίκτυο για να πραγματοποιήσετε μια κλήση."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Για να πραγματοποιήσετε κλήση, εισαγάγετε έναν έγκυρο αριθμό."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Η κλήση απέτυχε."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Δεν είναι δυνατή η προσθήκη κλήσης αυτήν τη στιγμή."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Έναρξη ακολουθίας MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Η υπηρεσία δεν υποστηρίζεται"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Δεν είναι δυνατή η εναλλαγή κλήσεων."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Δεν είναι δυνατή η πραγματοποίηση κλήσεων."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Δεν είναι δυνατή η αναμονή κλήσεων."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Συνδεθείτε σε ασύρματο δίκτυο για να πραγματοποιήσετε μια κλήση."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Ενεργοποιήστε τη δυνατότητα κλήσεων μέσω Wi-Fi για να πραγματοποιήσετε μια κλήση."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Κλήσεις επείγουσας ανάγκης"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Ενεργοποίηση πομπού..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Δεν υπάρχει υπηρεσία. Νέα προσπάθεια…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Δόνηση"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Δόνηση"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Οπτικός αυτόματος τηλεφ."</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Ορισμός PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Αλλαγή PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Ήχος"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ήχος κλήσης & δόνηση"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Ενσωματωμένες κάρτες SIM"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Μόνο κλήσεις έκτακτης ανάγκης"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Κάρτα SIM, υποδοχή: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Προσβασιμότητα"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Εισερχ. κλήση μέσω Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Κλήση Wi-Fi από"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Κλήση μέσω Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Πατήστε ξανά για άνοιγμα"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Παρουσιάστηκε κάποιο σφάλμα κατά την αποκωδικοποίηση του μηνύματος."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Μια κάρτα SIM ενεργοποίησε την υπηρεσία σας και ενημέρωσε τις δυνατότητες περιαγωγής του τηλεφώνου σας."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Υπάρχουν πάρα πολλές ενεργές κλήσεις. Τερματίστε ή να συγχωνεύστε τις υπάρχουσες κλήσεις πριν πραγματοποιήσετε νέα."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Αλλαγή PIN αυτόματου τηλεφωνητή"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Συνέχεια"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Ακύρωση"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ΟΚ"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Επιβεβαιώστε το παλιό σας PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Εισαγάγετε το PIN του αυτόματου τηλεφωνητή σας για να συνεχίσετε."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Ορίστε ένα νέο PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Το PIN πρέπει να αποτελείται από <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="8113764019347322170">"Επιβεβαιώστε το PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Τα PIN δεν ταιριάζουν"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Το PIN αυτόματου τηλεφωνητή ενημερώθηκε"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Δεν είναι δυνατή η ρύθμιση του PIN"</string>
</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index b06fe88..f0fbd11 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"No changes were made."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Choose voicemail service"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Your operator"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Old PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"New PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Please wait."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"The new PIN is too short."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"The new PIN is too long."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"The new PIN is too weak. A strong password should not have a continuous sequence or repeated digits."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"The old PIN doesn\'t match."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"The new PIN contains invalid characters."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Unable to change PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Unsupported message type. Call <xliff:g id="NUMBER">%s</xliff:g> to listen."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobile network settings"</string>
<string name="label_available" msgid="1181658289009300430">"Available networks"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Searching…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferred"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Enhanced 4G LTE Mode"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Advanced calling"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Use LTE services to improve voice and other communications (recommended)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data enabled"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Allow data usage"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobile network is not available. Connect to a wireless network to make a call."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"To place a call, enter a valid number."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Call failed."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Call cannot be added at the moment."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Starting MMI sequence…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Service not supported"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Can\'t switch calls."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Can\'t release call(s)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Can\'t hold calls."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Connect to a wireless network to make a call."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Enable Wi-Fi calling to make a call."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Emergency call"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Turning on radio…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"No service. Trying again…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrate"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrate"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visual Voicemail"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Set PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Change PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Sound"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ringtone & Vibrate"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Built-in SIM cards"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Emergency calling only"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM card, slot: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accessibility"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Incoming Wi-Fi call"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi call from"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi call"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Tap again to open"</string>
<string name="message_decode_error" msgid="3456481534066924855">"There was an error while decoding the message."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"A SIM card has activated your service and updated your phone\'s roaming capabilities."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"There are too many active calls. Please end or merge existing calls before placing a new one."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Change Voicemail PIN"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continue"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancel"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirm your old PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Enter your voicemail PIN to continue."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Set a new PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN must be <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> digits long."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirm your PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PINs don\'t match"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Voicemail PIN updated"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Unable to set PIN"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index b06fe88..f0fbd11 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"No changes were made."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Choose voicemail service"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Your operator"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Old PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"New PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Please wait."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"The new PIN is too short."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"The new PIN is too long."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"The new PIN is too weak. A strong password should not have a continuous sequence or repeated digits."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"The old PIN doesn\'t match."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"The new PIN contains invalid characters."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Unable to change PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Unsupported message type. Call <xliff:g id="NUMBER">%s</xliff:g> to listen."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobile network settings"</string>
<string name="label_available" msgid="1181658289009300430">"Available networks"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Searching…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferred"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Enhanced 4G LTE Mode"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Advanced calling"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Use LTE services to improve voice and other communications (recommended)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data enabled"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Allow data usage"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobile network is not available. Connect to a wireless network to make a call."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"To place a call, enter a valid number."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Call failed."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Call cannot be added at the moment."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Starting MMI sequence…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Service not supported"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Can\'t switch calls."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Can\'t release call(s)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Can\'t hold calls."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Connect to a wireless network to make a call."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Enable Wi-Fi calling to make a call."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Emergency call"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Turning on radio…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"No service. Trying again…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrate"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrate"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visual Voicemail"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Set PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Change PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Sound"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ringtone & Vibrate"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Built-in SIM cards"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Emergency calling only"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM card, slot: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accessibility"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Incoming Wi-Fi call"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi call from"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi call"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Tap again to open"</string>
<string name="message_decode_error" msgid="3456481534066924855">"There was an error while decoding the message."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"A SIM card has activated your service and updated your phone\'s roaming capabilities."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"There are too many active calls. Please end or merge existing calls before placing a new one."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Change Voicemail PIN"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continue"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancel"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirm your old PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Enter your voicemail PIN to continue."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Set a new PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN must be <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> digits long."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirm your PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PINs don\'t match"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Voicemail PIN updated"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Unable to set PIN"</string>
</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index b06fe88..f0fbd11 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"No changes were made."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Choose voicemail service"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Your operator"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Old PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"New PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Please wait."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"The new PIN is too short."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"The new PIN is too long."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"The new PIN is too weak. A strong password should not have a continuous sequence or repeated digits."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"The old PIN doesn\'t match."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"The new PIN contains invalid characters."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Unable to change PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Unsupported message type. Call <xliff:g id="NUMBER">%s</xliff:g> to listen."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobile network settings"</string>
<string name="label_available" msgid="1181658289009300430">"Available networks"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Searching…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferred"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Enhanced 4G LTE Mode"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Advanced calling"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Use LTE services to improve voice and other communications (recommended)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data enabled"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Allow data usage"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobile network is not available. Connect to a wireless network to make a call."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"To place a call, enter a valid number."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Call failed."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Call cannot be added at the moment."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Starting MMI sequence…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Service not supported"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Can\'t switch calls."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Can\'t release call(s)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Can\'t hold calls."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Connect to a wireless network to make a call."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Enable Wi-Fi calling to make a call."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Emergency call"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Turning on radio…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"No service. Trying again…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrate"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrate"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visual Voicemail"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Set PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Change PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Sound"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ringtone & Vibrate"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Built-in SIM cards"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Emergency calling only"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM card, slot: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accessibility"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Incoming Wi-Fi call"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi call from"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi call"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Tap again to open"</string>
<string name="message_decode_error" msgid="3456481534066924855">"There was an error while decoding the message."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"A SIM card has activated your service and updated your phone\'s roaming capabilities."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"There are too many active calls. Please end or merge existing calls before placing a new one."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Change Voicemail PIN"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continue"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancel"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirm your old PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Enter your voicemail PIN to continue."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Set a new PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN must be <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> digits long."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirm your PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PINs don\'t match"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Voicemail PIN updated"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Unable to set PIN"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 0a7c4d3..e8bae71 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"No se realizaron cambios."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Elegir servicio de buzón de voz"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Tu proveedor"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN anterior"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nuevo PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Un momento."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"El nuevo PIN es demasiado corto."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"El nuevo PIN es demasiado largo."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"El nuevo PIN no es muy seguro. Una contraseña segura no debería tener secuencias continuas ni dígitos repetidos."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"El PIN anterior no coincide."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"El nuevo PIN contiene caracteres no válidos."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"No se puede cambiar el PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Tipo de mensaje no compatible. Llama al <xliff:g id="NUMBER">%s</xliff:g> para escucharlo."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Configuración de la red móvil"</string>
<string name="label_available" msgid="1181658289009300430">"Redes disponibles"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Buscando..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferido"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Modo 4G LTE mejorado"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Llamadas avanzadas"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Usa servicios de LTE para mejorar comunicaciones de voz y otras (recomendado)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Usar paquete de datos"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Permitir el uso de datos"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"La red móvil no está disponible. Conéctate a una red inalámbrica para realizar una llamada."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Para realizar una llamada, ingresa un número válido."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Error en la llamada"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"No se puede agregar la llamada en este momento."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Iniciar la secuencia de MMI"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Servicio no compatible"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"No se puede cambiar llamadas."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"No se puede liberar llamadas."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"No es posible poner las llamadas en espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Conectarse a una red inalámbrica para hacer una llamada"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Habilita las llamadas con Wi-Fi para hacer una llamada."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Llamada de emergencia"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Encendiendo radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"No hay servicio. Vuelve a intentarlo."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrar"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrar"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Buzón de voz visual"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Establecer PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Cambiar PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Sonido"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Tono y vibración"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Tarjetas SIM integradas"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Solo llamada de emergencia"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Tarjeta SIM, ranura: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accesibilidad"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Llamada Wi-Fi entrante"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Llamada con Wi-Fi de"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Llamada por Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Presionar de nuevo para abrir"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Se produjo un error al decodificar el mensaje."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Una tarjeta SIM activó tu servicio y actualizó las capacidades de roaming del teléfono."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Hay demasiadas llamadas activas. Finaliza o combina las llamadas existentes antes de realizar una llamada nueva."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Cambiar el PIN del buzón de voz"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continuar"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancelar"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Aceptar"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirmar el PIN antiguo"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Ingresa el PIN del buzón de voz para continuar."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Establecer un PIN nuevo"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"El PIN debe tener entre <xliff:g id="MIN">%1$d</xliff:g> y <xliff:g id="MAX">%2$d</xliff:g> dígitos."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirmar el PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Los PIN no coinciden"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN del buzón de voz actualizado"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"No se puede establecer el PIN"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 44944eb..bed4c3a 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"No se ha realizado ningún cambio."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Seleccionar servicio de buzón de voz"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Tu operador"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN antiguo"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"PIN nuevo"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Espera…"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"El PIN nuevo es muy corto."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"El PIN nuevo es muy largo."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"El PIN nuevo no es lo bastante seguro. Una contraseña segura no debería contener secuencias continuas ni dígitos repetidos."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"El PIN antiguo no coincide."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"El PIN nuevo contiene caracteres no válidos."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"No se puede cambiar el PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Este tipo de mensaje no se admite. Llama al <xliff:g id="NUMBER">%s</xliff:g> para escucharlo."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Ajustes de red móvil"</string>
<string name="label_available" msgid="1181658289009300430">"Redes disponibles"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Buscando..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Preferencia de GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Modo 4G LTE mejorado"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Llamadas avanzadas"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Usar servicios LTE para mejorar la voz y otras comunicaciones (recomendado)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Habilitar datos"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Permitir uso de datos"</string>
@@ -440,6 +451,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"La red móvil no está disponible. Conéctate a una red inalámbrica para hacer llamadas."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Para realizar una llamada, introduce un número válido."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"No se ha podido llamar."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"No se puede añadir la llamada en este momento."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Iniciando secuencia MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Servicio no admitido"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"No se pueden intercambiar llamadas."</string>
@@ -450,6 +462,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"No se pueden hacer llamadas."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"No se pueden retener llamadas."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Conéctate a una red inalámbrica para hacer llamadas."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Para llamar, tienes que habilitar las llamadas por Wi-Fi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Llamada de emergencia"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Activando señal móvil…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Sin servicio. Reintentado…"</string>
@@ -544,6 +557,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrar"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrar"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Buzón de voz visual"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Configurar el PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Cambiar PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Sonido"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Tono y vibración"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Tarjetas SIM integradas"</string>
@@ -555,10 +570,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Solo llamadas de emergencia"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Tarjeta SIM, ranura: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accesibilidad"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Llamada Wi-Fi entrante"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Llamada por Wi-Fi de"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Llamada Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Toca de nuevo para abrir"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Se ha producido un error al decodificar el mensaje."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Una tarjeta SIM ha activado tu servicio y actualizado la función de itinerancia del teléfono."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Hay demasiadas llamadas activas. Finaliza o combina las llamadas que tienes antes de iniciar otra."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Cambiar el PIN del buzón de voz"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continuar"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancelar"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Aceptar"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirma tu antiguo PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Para continuar, escribe tu PIN del buzón de voz."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Configura un PIN nuevo"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"El PIN debe tener entre <xliff:g id="MIN">%1$d</xliff:g> y <xliff:g id="MAX">%2$d</xliff:g> dígitos."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirma tu PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Los PIN no coinciden"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Se ha cambiado el PIN del buzón de voz"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"No se ha podido configurar el PIN"</string>
</resources>
diff --git a/res/values-et-rEE/strings.xml b/res/values-et-rEE/strings.xml
index bbf0274..65a4fe0 100644
--- a/res/values-et-rEE/strings.xml
+++ b/res/values-et-rEE/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Muudatusi ei tehtud."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Valige kõnepostiteenus"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Teie operaator"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Vana PIN-kood"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Uus PIN-kood"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Oodake."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Uus PIN-kood on liiga lühike."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Uus PIN-kood on liiga pikk."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Uus PIN-kood on liiga nõrk. Tugevas paroolis ei tohi olla mitut järjestikust samasugust tähemärki ega korduvaid numbreid."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Vana PIN-kood ei sobi."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Uus PIN-kood sisaldab sobimatuid tähemärke."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN-koodi ei õnnestu muuta"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Toetamata sõnumi tüüp, kuulamiseks helistage numbrile <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobiilsidevõrgu seaded"</string>
<string name="label_available" msgid="1181658289009300430">"Saadaolevad võrgud"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Otsimine ..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Eelistatud GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Tõhustatud 4G LTE režiim"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Täpsem helistamine"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Kasutage hääl- ja muu suhtluse täiustamiseks LTE-teenuseid (soovitatav)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Andmeside lubatud"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Luba andmekasutus"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobiilivõrk pole saadaval. Helistamiseks looge ühendus traadita võrguga."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Helistamiseks sisestage kehtiv number."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Kõne ebaõnnestus."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Kõnet ei saa praegu lisada."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI-jada alustamine ..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Teenust ei toetata"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Kõnesid ei saa vahetada."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Kõnet (kõnesid) ei saa vabastada."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Kõnesid ei saa ootele panna."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Helistamiseks looge ühendus traadita võrguga."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Lubage helistamiseks WiFi-kõned."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Hädaabikõne"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Raadioside sisselülitamine ..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Teenus puudub. Uuesti proovimine ..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibreerimine"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibreerimine"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visuaalne kõnepost"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN-koodi määramine"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN-koodi muutmine"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Heli"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Helin ja vibratsioon"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Sisseehitatud SIM-kaardid"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Ainult hädaabikõned"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-kaart, pilu: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Juurdepääsetavus"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Sissetulev WiFi-kõne"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"WiFi-kõne:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"WiFi-kõne"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Avamiseks puudutage uuesti"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Sõnumi dekodeerimisel ilmnes viga."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM-kaart aktiveeris teenuse ja värskendas telefoni rändlusvõimeid."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Liiga palju aktiivseid kõnesid. Enne uue kõne tegemist lõpetage mõni olemasolev kõne või ühendage mitu kõnet omavahel."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Muutke kõneposti PIN-koodi"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Jätka"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Tühista"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Kinnitage vana PIN-kood"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Jätkamiseks sisestage kõneposti PIN-kood."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Määrake uus PIN-kood"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN-kood peab olema vahemikus <xliff:g id="MIN">%1$d</xliff:g>–<xliff:g id="MAX">%2$d</xliff:g> numbrit."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Kinnitage PIN-kood"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-koodid ei ühti"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Kõneposti PIN-koodi värskendati"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN-koodi ei saa määrata"</string>
</resources>
diff --git a/res/values-eu-rES/strings.xml b/res/values-eu-rES/strings.xml
index aef9587..0f22662 100644
--- a/res/values-eu-rES/strings.xml
+++ b/res/values-eu-rES/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Ez da aldaketarik egin."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Aukeratu erantzungailu-zerbitzua"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operadorea"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN kode zaharra"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"PIN kode berria"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Itxaron, mesedez."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Laburregia da PIN kode berria."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Luzeegia da PIN kode berria."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Ahulegia da PIN kode berria. Pasahitza sendoa izan dadin, ez du izan behar zenbaki-segidarik edo errepikatutako zenbakirik."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"PIN kode zaharra ez dator bat."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Balio ez duten karaktereak ditu PIN kode berriak."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Ezin da aldatu PIN kodea"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Ez dira onartzen mota honetako mezuak. Entzuteko, deitu <xliff:g id="NUMBER">%s</xliff:g> zenbakira."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Sare mugikorraren ezarpenak"</string>
<string name="label_available" msgid="1181658289009300430">"Sare erabilgarriak"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Bilatzen…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA hobetsita"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"4G LTE modu hobetua"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Deitzeko aukera aurreratuak"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Erabili LTE zerbitzuak ahotsa eta bestelako komunikazioak hobetzeko (gomendatua)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Datuak gaituta"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Onartu datuak erabiltzea"</string>
@@ -442,6 +453,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Sare mugikorra ez dago erabilgarri. Deia egiteko, konektatu haririk gabeko sare batera."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Deitzeko, idatzi balio duen zenbaki bat."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Ezin izan da deitu."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Une honetan ezin da gehitu deirik."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI sekuentzia hasten…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Ez da zerbitzua onartzen"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Ezin da deiz aldatu."</string>
@@ -452,6 +464,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Ezin dira deiak bereizi."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Ezin dira zain utzi deiak."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Deia egiteko, konektatu haririk gabeko sare batera."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Deia egiteko, gaitu Wi-Fi bidezko deiak."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Larrialdi-deia"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Irratia pizten…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ez dago zerbitzurik. Berriro saiatzen…"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Egin dar-dar"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Egin dar-dar"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Erantzungailu bisuala"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Ezarri PIN kodea"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Aldatu PIN kodea"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Soinua"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Tonua eta dardara"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"SIM txartel integratuak"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Larrialdi-deiak soilik"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM txartela, <xliff:g id="SLOT_ID">%s</xliff:g> erretena"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Erabilerraztasuna"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Sarrerako Wi-Fi deia"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi bidezko deia:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi deia"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Irekitzeko, sakatu berriro"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Errore bat gertatu mezua deskodetzean."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM txartel batek zerbitzua aktibatu du eta telefonoaren ibiltaritza-gaitasunak aldatu ditu."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Dei gehiegi daude aktibo. Amaitu edo bateratu abian diren deiak beste bat egin aurretik."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Aldatu erantzungailuaren PIN kodea"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Jarraitu"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Utzi"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Ados"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Berretsi PIN kode zaharra"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Idatzi erantzungailuaren PIN kodea jarraitzeko."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Ezarri PIN kode berria"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"<xliff:g id="MIN">%1$d</xliff:g> eta <xliff:g id="MAX">%2$d</xliff:g> digituren artean izan behar ditu PIN kodeak."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Berretsi PIN kodea"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Ez datoz bat PIN kodeak"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Eguneratu da erantzungailuaren PIN kodea"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Ezin da ezarri PIN kodea"</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index c7f8430..fe87ee6 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"تغییری انجام نشده است."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"انتخاب سرویس پست صوتی"</string>
<string name="voicemail_default" msgid="2001233554889016880">"شرکت مخابراتی شما"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"پین قدیمی"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"پین جدید"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"لطفاً منتظر بمانید."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"پین جدید خیلی کوتاه است."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"پین جدید خیلی طولانی است."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"پین جدید خیلی ضعیف است. گذرواژه قوی نباید توالی از اعداد باشد یا عدد تکراری داشته باشد."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"پین قدیمی مطابقت ندارد."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"پین جدید نویسههای نامعتبری دارد."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"پین تغییر نکرد"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"نوع پیام پشتیبانی نمیشود، برای گوش کردن با <xliff:g id="NUMBER">%s</xliff:g> تماس بگیرید."</string>
<string name="mobile_networks" msgid="2843854043339307375">"تنظیمات شبکه تلفن همراه"</string>
<string name="label_available" msgid="1181658289009300430">"شبکههای موجود"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"در حال جستجو…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA برگزیده"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"حالت پیشرفته 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"تماس پیشرفته"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"استفاده از سرویسهای LTE جهت بهبود ارتباطات صوتی و سایر ارتباطات (توصیه میشود)"</string>
<string name="data_enabled" msgid="5972538663568715366">"دادهها فعال شدند"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"استفاده از داده مجاز است"</string>
@@ -353,7 +364,7 @@
<string name="tty_mode_option_summary" msgid="1073835131534808732">"تنظیم حالت TTY"</string>
<string name="auto_retry_mode_title" msgid="4073265511427813322">"سعی مجدد خودکار"</string>
<string name="auto_retry_mode_summary" msgid="4973886004067532288">"فعال کردن حالت سعی مجدد خودکار"</string>
- <string name="tty_mode_not_allowed_video_call" msgid="3795846787901909176">"تغییر حالت TTY در طول تماس ویدیویی مجاز نیست"</string>
+ <string name="tty_mode_not_allowed_video_call" msgid="3795846787901909176">"تغییر حالت TTY در طول تماس ویدئویی مجاز نیست"</string>
<string name="menu_add" msgid="1882023737425114762">"افزودن مخاطب"</string>
<string name="menu_edit" msgid="7143003705504672374">"ویرایش مخاطب"</string>
<string name="menu_delete" msgid="3977150783449642851">"حذف مخاطب"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"شبکه همراه در دسترس نیست. برای برقراری تماس به یک شبکه بیسیم وصل شوید."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"برای برقراری تماس، یک شماره معتبر وارد کنید."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"تماس ناموفق بود."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"فعلاً نمیتوانید تماس اضافه کنید."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"شروع ترتیب MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"سرویس پشتیبانی نمیشود"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"نمیتوانید بین تماسها جابجا شوید."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"نمیتوانید تماس(ها) را آزاد کنید."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"نگهداشتن تماسها ممکن نیست."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"برای برقراری تماس، به یک شبکه بیسیم وصل شوید"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"برای برقراری تماس، تماس Wi-Fi را فعال کنید."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"تماس اضطراری"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"در حال روشن کردن رادیو..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"سرویسی در دسترس نیست. دوباره امتحان کنید..."</string>
@@ -463,7 +476,7 @@
<string name="onscreenManageCallsText" msgid="5473231160123254154">"مدیریت تماسها"</string>
<string name="onscreenManageConferenceText" msgid="6485935856534311346">"مدیریت کنفرانس"</string>
<string name="onscreenAudioText" msgid="1710087112800041743">"صوتی"</string>
- <string name="onscreenVideoCallText" msgid="4800924186056115442">"تماس ویدیویی"</string>
+ <string name="onscreenVideoCallText" msgid="4800924186056115442">"تماس ویدئویی"</string>
<string name="importSimEntry" msgid="6614358325359736031">"وارد کردن"</string>
<string name="importAllSimEntries" msgid="1503181169636198673">"وارد کردن همه"</string>
<string name="importingSimContacts" msgid="7374056215462575769">"وارد کردن مخاطبین سیم"</string>
@@ -540,21 +553,35 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"لرزش"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"لرزش"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"پست صوتی تصویری"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"تنظیم پین"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"تغییر پین"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"صدا"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"آهنگ زنگ و لرزش"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"سیمکارتهای داخلی"</string>
- <string name="enable_video_calling_title" msgid="7237253660669000899">"روشن کردن تماس ویدیویی"</string>
- <string name="enable_video_calling_dialog_msg" msgid="8948186136957417948">"برای روشن کردن تماس ویدیویی، باید حالت پیشرفته 4G LTE را در تنظیمات شبکه فعال کنید."</string>
+ <string name="enable_video_calling_title" msgid="7237253660669000899">"روشن کردن تماس ویدئویی"</string>
+ <string name="enable_video_calling_dialog_msg" msgid="8948186136957417948">"برای روشن کردن تماس ویدئویی، باید حالت پیشرفته 4G LTE را در تنظیمات شبکه فعال کنید."</string>
<string name="enable_video_calling_dialog_settings" msgid="576528473599603249">"تنظیمات شبکه"</string>
<string name="enable_video_calling_dialog_close" msgid="7411471282167927991">"بستن"</string>
<string name="sim_label_emergency_calls" msgid="4847699229529306397">"تماسهای اضطراری"</string>
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"فقط تماسهای اضطراری"</string>
<string name="sim_description_default" msgid="4778679519938775515">"سیمکارت، شکاف: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"دسترسپذیری"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"تماس Wi-Fi ورودی"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"تماس Wi-Fi از"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"تماس Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"دوباره ضربه بزنید تا باز شود"</string>
<string name="message_decode_error" msgid="3456481534066924855">"هنگام رمزگشایی پیام، خطایی روی داد."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"یک سیمکارت سرویس شما را فعال کرده است و قابلیتهای رومینگ تلفنتان را بهروز کرده است."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"تعداد زیادی تماس فعال وجود دارد. قبل از برقراری تماس جدید، لطفاً به تماسهای موجود پایان دهید یا آنها را ادغام کنید."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"تغییر پین پست صوتی"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"ادامه"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"لغو"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"تأیید"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"تأیید پین قدیمی"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"پین پست صوتی را برای ادامه وارد کنید."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"تنظیم پین جدید"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"پین باید <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="8113764019347322170">"تأیید پین"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"پینها با یکدیگر مطابقت ندارند"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"پین پست صوتی بهروزرسانی شد"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"پین تنظیم نشد"</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index 98ff6a2..5f0f8a3 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Muutoksia ei tehty."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Valitse puhelinvastaajapalvelu"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operaattorisi"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Vanha PIN-koodi"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Uusi PIN-koodi"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Odota."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Uusi PIN-koodi on liian lyhyt."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Uusi PIN-koodi on liian pitkä."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Uusi PIN-koodi on liian heikko. Vahvassa salasanassa ei saa olla peräkkäisiä tai toistuvia numeroita."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Vanha PIN-koodi ei täsmää."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Uusi PIN-koodi sisältää virheellisiä merkkejä."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN-koodin vaihtaminen epäonnistui."</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Viestin tyyppiä ei tueta. Kuuntele soittamalla numeroon <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Matkapuhelinverkon asetukset"</string>
<string name="label_available" msgid="1181658289009300430">"Käytettävissä olevat verkot"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Haetaan…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Ensisijaisesti GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Enhanced 4G LTE -tila"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Puhelujen lisävaihtoehdot"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Käytä LTE-palveluita puheviestinnän ja muiden viestintätapojen parantamiseen (suositeltu)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Datayhteys käytössä"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Salli tiedonsiirto"</string>
@@ -440,6 +451,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Matkapuhelinverkko ei ole käytettävissä. Yhdistä langattomaan verkkoon, jos haluat soittaa puhelun."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Soita antamalla kelvollinen numero."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Puhelu epäonnistui."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Puhelua ei voi lisätä juuri nyt."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Aloitetaan MMI-koodisekvenssiä..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Palvelua ei tueta"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Puhelua ei voi vaihtaa."</string>
@@ -450,6 +462,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Puheluja ei voi vapauttaa."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Puhelujen pito ei onnistu."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Yhdistä langattomaan verkkoon, jos haluat soittaa puhelun."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Ota Wi-Fi-puhelut käyttöön soittaaksesi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Hätäpuhelu"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Käynnistetään radiota…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ei yhteyttä. Yritetään uudelleen…"</string>
@@ -544,6 +557,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Värinä"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Värinä"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visuaalinen puhelinvastaaja"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Aseta PIN-koodi."</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Vaihda PIN-koodi"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Ääni"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Soittoääni ja värinä"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Sisäiset SIM-kortit"</string>
@@ -555,10 +570,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Vain hätäpuhelut"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-kortti, paikka: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Esteettömyys"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Saapuva Wi-Fi-puhelu"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi-puhelu henkilöltä"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi-puhelu"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Avaa koskettamalla uudelleen."</string>
<string name="message_decode_error" msgid="3456481534066924855">"Virhe purettaessa viestiä."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM-kortti on aktivoinut palvelusi ja päivittänyt puhelimesi roaming-toiminnot."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Aktiivisia puheluja on liian monta. Lopeta puheluita tai yhdistä niitä ennen uuden puhelun aloittamista."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Vaihda vastaajan PIN-koodi."</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Jatka"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Peruuta"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Vahvista vanha PIN-koodi."</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Jatka antamalla vastaajasi PIN-koodi."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Määritä uusi PIN-koodi."</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN-koodin pitää olla <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> merkkiä pitkä."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Vahvista PIN-koodi."</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-koodit eivät täsmää."</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Vastaajan PIN-koodi on päivitetty."</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN-koodin määrittäminen epäonnistui."</string>
</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index a7d8a21..85443a9 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Aucune modification n\'a été apportée."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Choisissez un service de messagerie vocale."</string>
<string name="voicemail_default" msgid="2001233554889016880">"Votre fournisseur de services"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Ancien NIP"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nouveau NIP"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Veuillez patienter."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Le nouveau NIP est trop court."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Le nouveau NIP est trop long."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Le nouveau NIP n\'est pas assez robuste. Il ne devrait pas contenir de séquences continues ni de chiffres répétés."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Le NIP saisi ne correspond pas à l\'ancien NIP."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Le nouveau NIP contient des caractères incorrects."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Impossible de modifier le NIP"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Type de message non pris en charge. Composez le <xliff:g id="NUMBER">%s</xliff:g> pour l\'écouter."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Paramètres réseaux cellulaires"</string>
<string name="label_available" msgid="1181658289009300430">"Réseaux disponibles"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Recherche en cours…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA de préférence"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Mode LTE 4G avancé"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Appel avancé"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Utiliser services LTE pour améliorer communications vocales et autres (recommandé)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Données activées"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Autoriser l\'utilisation des données"</string>
@@ -440,6 +451,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Le réseau cellulaire n\'est pas accessible. Connectez-vous à un réseau Wi-Fi pour faire un appel."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Pour faire un appel, entrez un numéro valide."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Échec de l\'appel."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Impossible d\'ajouter l\'appel pour le moment."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Lancement de la séquence IHM..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Service non pris en charge"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Impossible de faire des appels."</string>
@@ -450,6 +462,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Impossible de libérer l\'appel ou les appels."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Impossible de mettre les appels en attente."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Connectez-vous à un réseau Wi-Fi pour faire un appel."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Activez les appels Wi-Fi pour faire un appel."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Appel d\'urgence"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Activation du signal radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Aucun service. Nouvel essai en cours..."</string>
@@ -544,6 +557,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibreur"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibreur"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Messagerie vocale visuelle"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Définir le NIP"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Modifier le NIP"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Son"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Sonnerie et vibreur"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Cartes SIM intégrées"</string>
@@ -555,10 +570,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Appels d\'urgence seulement"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Carte SIM, fente : <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accessibilité"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Appel Wi-Fi entrant"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Appel Wi-Fi de"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Appel Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Touchez à nouveau pour ouvrir"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Une erreur s\'est produite lors du décodage du message."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Une carte SIM a activé votre service et mis à jour les fonctionnalités d\'itinérance de votre téléphone."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Il y a trop d\'appels actifs. Veuillez mettre fin aux appels existants ou les fusionner avant d\'en passer un nouveau."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Modifier le NIP de la messagerie vocale"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continuer"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Annuler"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirmez votre ancien NIP"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Entrez votre NIP de messagerie vocale pour continuer."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Choisissez un nouveau NIP"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Le NIP doit comporter de <xliff:g id="MIN">%1$d</xliff:g> à <xliff:g id="MAX">%2$d</xliff:g> chiffres."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirmez votre NIP"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Les NIP ne correspondent pas"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"NIP de messagerie vocale mis à jour"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Impossible de définir le NIP"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index f94c9e8..5ac4194 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Aucune modification n\'a été apportée."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Choisissez un service de messagerie vocale."</string>
<string name="voicemail_default" msgid="2001233554889016880">"Votre opérateur"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Ancien code"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nouveau code"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Veuillez patienter."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Le nouveau code est trop court."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Le nouveau code est trop long."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Le nouveau code n\'est pas suffisamment sécurisé. Pour qu\'un mot de passe soit sûr, il ne doit pas contenir de chiffres qui se suivent ou qui se répètent."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"L\'ancien code est erroné."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Le nouveau code contient des caractères incorrects."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Impossible de modifier le code"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Type de message incompatible, composez le <xliff:g id="NUMBER">%s</xliff:g> pour l\'écouter."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Paramètres réseau mobile"</string>
<string name="label_available" msgid="1181658289009300430">"Réseaux disponibles"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Recherche..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA de préférence"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Mode LTE 4G avancé"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Appel avancé"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Utiliser services LTE pour améliorer communications vocales et autres (recommandé)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Données activées"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Autoriser la consommation des données"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Le réseau mobile n\'est pas disponible. Connectez-vous à un réseau sans fil pour passer un appel."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Pour émettre un appel, veuillez saisir un numéro valide."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Échec de l\'appel."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Impossible d\'ajouter un appel pour le moment."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Lancement de la séquence IHM..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Service incompatible"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Impossible de changer d\'appel."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Impossible de lancer les appels."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Impossible de mettre les appels en attente."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Connectez-vous à un réseau sans fil pour passer un appel."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Pour passer un appel, veuillez activer les appels Wi-Fi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Appel d\'urgence"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Activation du signal radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Aucun service disponible. Nouvelle tentative en cours…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibreur"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibreur"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Messagerie vocale visuelle"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Définir un code"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Modifier le code"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Sonnerie"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Sonnerie et vibreur"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Cartes SIM intégrées"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Appels d\'urgence seulement"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Carte SIM, emplacement : <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accessibilité"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Appel Wi-Fi entrant"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Appel Wi-Fi de"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Appel Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Appuyez à nouveau pour ouvrir."</string>
<string name="message_decode_error" msgid="3456481534066924855">"Une erreur s\'est produite lors du décodage du message."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Votre service a été activé et les fonctionnalités d\'itinérance de votre téléphone ont été mises à jour via une carte SIM."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Il y a trop d\'appels actifs. Pour passer un autre appel, vous devez mettre fin aux appels existants ou fusionner ces derniers."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Modifier le code de la boîte vocale"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continuer"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Annuler"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirmer votre ancien code"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Pour continuer, saisissez le code de votre boîte vocale."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Définir un nouveau code"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Le code ne peut être composé que de chiffres de <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="8113764019347322170">"Confirmer votre code"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Les codes ne correspondent pas."</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Le code de votre boîte vocale a été mis à jour."</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Impossible de définir le code"</string>
</resources>
diff --git a/res/values-gl-rES/strings.xml b/res/values-gl-rES/strings.xml
index f12d9ee..55ff12c 100644
--- a/res/values-gl-rES/strings.xml
+++ b/res/values-gl-rES/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Non se fixeron cambios."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Escolle o servizo de correo de voz"</string>
<string name="voicemail_default" msgid="2001233554889016880">"O teu operador"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN antigo"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"PIN novo"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Agarda."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"O PIN novo é demasiado curto."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"O PIN novo é demasiado longo."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"O novo PIN é pouco seguro. Para que sexa seguro, non debe conter secuencias continuas nin díxitos repetidos."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"O PIN antigo non coincide."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"O novo PIN contén caracteres non válidos."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Non se puido cambiar o PIN."</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Tipo de mensaxe non compatible. Chama ao <xliff:g id="NUMBER">%s</xliff:g> para escoitala."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Configuración da rede móbil"</string>
<string name="label_available" msgid="1181658289009300430">"Redes dispoñibles"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Buscando..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferido"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Modo LTE 4G mellorado"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Chamadas avanzadas"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Usa os servizos LTE para mellorar a comunicación por voz e outras (recomendado)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Datos activados"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Permitir o uso de datos"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"A rede móbil non está dispoñible. Conéctate a unha rede sen fíos para facer unha chamada."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Para realizar unha chamada, introduce un número válido."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Produciuse un erro na chamada."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Non se pode engadir a chamada neste momento."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Iniciando secuencia MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Servizo non compatible"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Non se poden cambiar as chamadas."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Non se poden desconectar as chamadas."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Non se poden poñer as chamadas en espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Conéctate a unha rede sen fíos para facer unha chamada."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Activa as chamadas por wifi para facer unha chamada."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Chamada de emerxencia"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Activando radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Sen servizo. Tentando de novo…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrar"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrar"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Correo de voz visual"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Establecer PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Cambiar PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Son"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ton de chamada e vibración"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Tarxetas SIM integradas"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Só chamadas de emerxencia"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Tarxeta SIM, rañura: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accesibilidade"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Chamada wifi entrante"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Chamada por wifi de"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Chamada wifi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Toca de novo para abrir"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Produciuse un erro durante a descodificación da mensaxe."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"A tarxeta SIM activou o teu servizo e actualizou as funcións de itinerancia do teléfono."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Hai moitas chamadas activas. Finaliza as chamadas existentes ou combínaas antes de facer unha nova."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Cambiar PIN do correo de voz"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continuar"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancelar"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Aceptar"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirma o teu PIN anterior"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Escribe o PIN do teu correo de voz para continuar."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Establece un PIN novo"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"O PIN debe conter entre <xliff:g id="MIN">%1$d</xliff:g> e <xliff:g id="MAX">%2$d</xliff:g> díxitos."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirma o teu PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Os PIN non coinciden"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Actualizouse o PIN do correo de voz"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Non se puido establecer o PIN"</string>
</resources>
diff --git a/res/values-gu-rIN/strings.xml b/res/values-gu-rIN/strings.xml
index b3006f9..057b2ca 100644
--- a/res/values-gu-rIN/strings.xml
+++ b/res/values-gu-rIN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"કોઇ બદલાવો થયાં ન હતાં."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"વૉઇસમેઇલ સેવા પસંદ કરો"</string>
<string name="voicemail_default" msgid="2001233554889016880">"તમારો કેરિઅર"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"જૂનો PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"નવો PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"કૃપા કરીને રાહ જુઓ."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"નવો PIN ખૂબ ટૂંકો છે."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"નવો PIN ખૂબ લાંબો છે."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"નવો PIN ખૂબ નબળો છે. સશક્ત પાસવર્ડ સતત ક્રમ અથવા પુનરાવર્તિત અંકો ધરાવતો હોવો જોઇએ નહીં."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"જૂનો PIN મેળ ખાતો નથી."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"નવો PIN અમાન્ય અક્ષરો ધરાવે છે."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN બદલવામાં અસમર્થ"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"અસમર્થિત સંદેશ પ્રકાર, સાંભળવા માટે <xliff:g id="NUMBER">%s</xliff:g> પર કૉલ કરો."</string>
<string name="mobile_networks" msgid="2843854043339307375">"સેલ્યુલર નેટવર્ક સેટિંગ્સ"</string>
<string name="label_available" msgid="1181658289009300430">"ઉપલબ્ધ નેટવર્ક્સ"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"શોધી રહ્યું છે..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA પસંદ કરેલ છે"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"વિસ્તૃત 4G LTE મોડ"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"વિગતવાર કૉલિંગ"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"વૉઇસ અને અન્ય સંચારોને બહેતર બનાવવા માટે LTE સેવાઓનો ઉપયોગ કરો (ભલામણ કરેલ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"ડેટા સક્ષમ કરેલ છે"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"ડેટા વપરાશની મંજૂરી આપો"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"સેલ્યુલર નેટવર્ક ઉપલબ્ધ નથી. કૉલ કરવા માટે વાયરલેસ નેટવર્કથી કનેક્ટ કરો."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"કૉલ કરવા માટે, માન્ય નંબર દાખલ કરો."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"કૉલ નિષ્ફળ થયો."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"આ સમયે કૉલ ઉમેરી શકાતો નથી."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI અનુક્રમ પ્રારંભ કરી રહ્યાં છે…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"સેવા સમર્થિત નથી"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"કૉલ્સ સ્વિચ કરી શકાતા નથી."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"કૉલ(લ્સ) રિલીઝ કરી શકતા નથી."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"કૉલ્સને હોલ્ડ કરી શકતાં નથી."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"કૉલ કરવા માટે વાયરલેસ નેટવર્કથી કનેક્ટ કરો."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"કૉલ કરવા માટે Wi-Fi કૉલિંગ સક્ષમ કરો."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"કટોકટીનો કૉલ"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"રેડિઓ ચાલુ કરી રહ્યાં છે…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"કોઈ સેવા નથી. ફરી પ્રયાસ કરી રહ્યાં છે…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"વાઇબ્રેટ"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"વાઇબ્રેટ"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"વિઝ્યુઅલ વૉઇસમેઇલ"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN સેટ કરો"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN બદલો"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ધ્વનિ"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"રિંગટોન અને વાઇબ્રેટ"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"બિલ્ટ-ઇન SIM કાર્ડ્સ"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"ફક્ત કટોકટીની કૉલિંગ"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM કાર્ડ, સ્લોટ: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ઍક્સેસિબિલિટી"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"આવનાર Wi-Fi કૉલ"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"આમના તરફથી Wi-Fi કૉલ"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi કૉલ"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"ખોલવા માટે ફરીથી ટૅપ કરો"</string>
<string name="message_decode_error" msgid="3456481534066924855">"સંદેશ ડીકોડિંગ કરતી વખતે ભૂલ આવી હતી."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"એક SIM કાર્ડ એ તમારી સેવા સક્રિય કરી છે અને તમારા ફોનની રોમિંગ ક્ષમતાઓને અપડેટ કરી છે."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"અહીં ઘણા બધા સક્રિય કૉલ્સ છે. કૃપા કરીને એક નવો કૉલ કરવા પહેલાં અસ્તિત્વમાંના કૉલ્સને સમાપ્ત કરો અથવા મર્જ કરો."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"વૉઇસમેઇલ PIN બદલો"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"ચાલુ રાખો"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"રદ કરો"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ઓકે"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"તમારા જૂના PIN ની પુષ્ટિ કરો"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"ચાલુ રાખવા માટે તમારો વૉઇસમેઇલ PIN દાખલ કરો."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"એક નવો PIN સેટ કરો"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN <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="8113764019347322170">"તમારા PIN ની પુષ્ટિ કરો"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN મેળ ખાતા નથી"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"વૉઇસમેઇલ PIN અપડેટ કર્યો"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN સેટ કરવામાં અસમર્થ"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 92bffd1..02f38a4 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"कोई परिवर्तन नहीं किए गए."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"वॉयस मेल सेवा चुनें"</string>
<string name="voicemail_default" msgid="2001233554889016880">"आपका वाहक"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"पुराना पिन"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"नया पिन"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"कृपया प्रतीक्षा करें."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"नया पिन बहुत छोटा है."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"नया पिन बहुत बड़ा है."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"नया पिन बहुत कमज़ोर है. किसी सशक्त पासवर्ड में निरंतर क्रम या अंकों का दोहराव नहीं होना चाहिए."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"पुराने पिन का मिलान नहीं हो रहा है."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"नए पिन में अमान्य वर्ण शामिल हैं."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"पिन बदलने में असमर्थ"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"असमर्थित संदेश प्रकार, सुनने के लिए <xliff:g id="NUMBER">%s</xliff:g> पर कॉल करें."</string>
<string name="mobile_networks" msgid="2843854043339307375">"सेल्युलर नेटवर्क सेटिंग"</string>
<string name="label_available" msgid="1181658289009300430">"उपलब्ध नेटवर्क"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"खोज रहा है..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA पसंदीदा"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"उन्नत 4G LTE मोड"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"उन्नत कॉलिंग"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"ध्वनि और अन्य संचारों को बेहतर बनाने हेतु LTE सेवाओं का उपयोग करें (अनुशंसित)"</string>
<string name="data_enabled" msgid="5972538663568715366">"डेटा सक्षम किया गया"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"डेटा उपयोग करने दें"</string>
@@ -347,8 +358,8 @@
<string name="sum_fdn" msgid="1959399454900272878">"फ़िक्स्ड डायलिंग नंबर प्रबंधित करें"</string>
<string name="sum_fdn_change_pin" msgid="6666549734792827932">"FDN पहुंच के लिए पिन बदलें"</string>
<string name="sum_fdn_manage_list" msgid="8431088265332628316">"फ़ोन नंबर सूची प्रबंधित करें"</string>
- <string name="voice_privacy" msgid="3776841382844614716">"ध्वनि गोपनीयता"</string>
- <string name="voice_privacy_summary" msgid="3159383389833516214">"उन्नत गोपनीयता मोड सक्षम करें"</string>
+ <string name="voice_privacy" msgid="3776841382844614716">"ध्वनि निजता"</string>
+ <string name="voice_privacy_summary" msgid="3159383389833516214">"उन्नत निजता मोड सक्षम करें"</string>
<string name="tty_mode_option_title" msgid="9033098925144434669">"TTY मोड"</string>
<string name="tty_mode_option_summary" msgid="1073835131534808732">"TTY मोड सेट करें"</string>
<string name="auto_retry_mode_title" msgid="4073265511427813322">"स्वतः पुन: प्रयास"</string>
@@ -414,7 +425,7 @@
<string name="pin2_error_exception" msgid="1088689322248996699">"नेटवर्क या SIM कार्ड त्रुटि"</string>
<string name="doneButton" msgid="2859593360997984240">"पूर्ण"</string>
<string name="voicemail_settings_number_label" msgid="8524164258691887790">"ध्वनिमेल नबंर"</string>
- <string name="card_title_dialing" msgid="5769417478498348054">"डायल कर रहा है"</string>
+ <string name="card_title_dialing" msgid="5769417478498348054">"डायल हो रहा है"</string>
<string name="card_title_redialing" msgid="8253487008234167266">"पुन: डायल हो रहा है"</string>
<string name="card_title_conf_call" msgid="1162980346189744501">"कॉन्फ़्रेंस कॉल"</string>
<string name="card_title_incoming_call" msgid="7364539451234646909">"इनकमिंग कॉल"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"सेल्युलर नेटवर्क उपलब्ध नहीं है. कॉल करने के लिए किसी वायरलेस नेटवर्क से कनेक्ट करें."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"कॉल करने के लिए, मान्य नंबर डालें."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"कॉल विफल."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"इस समय कॉल नहीं जोड़ा जा सकता."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI अनुक्रम प्रारंभ हो रहा है…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"सेवा समर्थित नहीं है"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"कॉल स्विच नहीं किए जा सकते."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"कॉल रिलीज़ नहीं किया जा सकता (किए जा सकते)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"कॉल होल्ड नहीं किए जा सकते."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"कॉल करने के लिए किसी वायरलेस नेटवर्क से कनेक्ट करें."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"कॉल करने के लिए वाई-फ़ाई कॉलिंग सक्षम करें."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"आपातकालीन कॉल"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"रेडियो चालू कर रहा है..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"कोई सेवा नहीं. पुन: प्रयास किया जा रहा है…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"कंपन करें"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"कंपन करें"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"विज़ुअल वॉइसमेल"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"पिन सेट करें"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"पिन बदलें"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ध्वनि"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"रिंगटोन और कंपन"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"अंतर्निहित सिम कार्ड"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"केवल आपातकालीन कॉल"</string>
<string name="sim_description_default" msgid="4778679519938775515">"सिम कार्ड, स्लॉट: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"सरल उपयोग"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"इनकमिंग वाई-फ़ाई कॉल"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"इससे वाई-फ़ाई कॉल"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"वाई-फ़ाई कॉल"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"खोलने के लिए पुन: टैप करें"</string>
<string name="message_decode_error" msgid="3456481534066924855">"संदेश डीकोड करते समय कोई त्रुटि हुई थी."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"सिम कार्ड द्वारा आपकी सेवा को सक्रिय किया गया है और आपके फ़ोन की रोमिंग क्षमताओं को अपडेट किया गया है."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"बहुत अधिक कॉल सक्रिय हैं. नया कॉल करने से पहले कृपया मौजूदा कॉल समाप्त करें या उन्हें मिला दें."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"वॉइसमेल पिन बदलें"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"जारी रखें"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"अभी नहीं"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ठीक है"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"अपने पुराने पिन की पुष्टि करें"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"जारी रखने के लिए अपना वॉइसमेल पिन डालें."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"एक नया पिन सेट करें"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"पिन में <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="8113764019347322170">"अपने पिन की पुष्टि करें"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"पिन का मिलान नहीं हो रहा"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"वॉइसमेल पिन अपडेट किया गया"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"पिन सेट कर पाने में असमर्थ"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 2cd1fe5..d5a833c 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Nisu izvršene nikakve promjene."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Odaberite uslugu govorne pošte"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Vaš mobilni operater"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Stari PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Novi PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Pričekajte."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Novi PIN je prekratak."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Novi PIN je predugačak."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Novi je PIN preslab. Jaka zaporka ne smije sadržavati kontinuirani niz ili ponovljene znamenke."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Stari se PIN ne podudara."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Novi PIN sadrži nevažeće znakove."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN se ne može promijeniti"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Vrsta poruke nije podržana, nazovite <xliff:g id="NUMBER">%s</xliff:g> da biste je poslušali."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Postavke mobilne mreže"</string>
<string name="label_available" msgid="1181658289009300430">"Dostupne mreže"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Pretraživanje…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Preferirano GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Poboljšan 4G LTE način"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Napredno pozivanje"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Upotreba LTE usluga za poboljšanje glasovne i drugih komunikacija (preporučeno)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Podaci su omogućeni"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Dopusti upotrebu podataka"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobilna mreža nije dostupna. Povežite se s bežičnom mrežom da biste uputili poziv."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Unesite važeći broj da biste uspostavili poziv."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Poziv nije uspio."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Poziv trenutačno nije moguć."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Pokretanje MMI sekvence…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Usluga nije podržana"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Prebacivanje poziva nije moguće."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Prekidanje poziva nije moguće."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Pozivi se ne mogu stavljati na čekanje."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Povežite se s bežičnom mrežom da biste uputili poziv."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Omogućite pozivanje putem Wi-Fi veze da biste uspostavili poziv."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Hitan poziv"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Uključivanje radija…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Nema usluge. Pokušavamo ponovo…"</string>
@@ -543,6 +556,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibracija"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibracija"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vizualna govorna pošta"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Postavljanje PIN-a"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Promjena PIN-a"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Zvuk"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Melodija zvona i vibracija"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Ugrađene SIM kartice"</string>
@@ -554,10 +569,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Samo hitni pozivi"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM kartica, utor: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Pristupačnost"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Dolazni Wi-Fi poziv"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi poziv s broja"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi poziv"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Dodirnite opet za otvaranje"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Došlo je do pogreške prilikom dekodiranja poruke."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM kartica aktivirala je vašu uslugu i ažurirala mogućnosti telefona za roaming."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Postoji previše aktivnih poziva. Prekinite ili spojite postojeće pozive prije uspostavljanja novog poziva."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Promjena PIN-a govorne pošte"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Nastavi"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Odustani"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"U redu"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Potvrda starog PIN-a"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Da biste nastavili, unesite PIN za govornu poštu."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Postavljanje novog PIN-a"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN mora sadržavati od <xliff:g id="MIN">%1$d</xliff:g> do <xliff:g id="MAX">%2$d</xliff:g> znamenki."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Potvrda PIN-a"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-ovi se ne podudaraju"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Ažuriran je PIN govorne pošte"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN se ne može postaviti"</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index d0bcb6f..d3371d8 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Nem történt változtatás."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Válassza ki a hangposta-szolgáltatást"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Saját mobilszolgáltató"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Régi PIN-kód"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Új PIN-kód"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Kérjük, várjon."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Az új PIN-kód túl rövid."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Az új PIN-kód túl hosszú."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Az új PIN-kód túl gyenge. Az erős jelszavak nem tartalmaznak egymás után következő számokat vagy ismétlődő számjegyeket."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"A régi PIN-kód nem egyezik a tárolttal."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Az új PIN-kód érvénytelen karaktereket tartalmaz."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Nem sikerült módosítani a PIN-kódot"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Nem támogatott üzenettípus. Hívja a következő telefonszámot az üzenet meghallgatásához: <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobilhálózati beállítások"</string>
<string name="label_available" msgid="1181658289009300430">"Elérhető hálózatok"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Keresés…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA a preferált"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Javított 4G LTE mód"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Továbbfejlesztett telefonhívás"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"LTE-szolgáltatások használata hang- és egyéb kommunikáció javításához (ajánlott)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Adatok engedélyezése"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Adatforgalom engedélyezése"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"A mobilhálózat nem érhető el. Hívás indításához csatlakozzon egy vezeték nélküli hálózathoz."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Hívásindításhoz adjon meg egy érvényes számot."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Sikertelen hívás."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Jelenleg nem lehet hívást indítani."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI-sorozat indítása..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"A szolgáltatás nem támogatott"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"A hívások közötti váltás sikertelen."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"A tartásban lévő hívás(ok) folytatása sikertelen."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"A hívások nem tarthatók."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Hívás indításához csatlakozzon egy vezeték nélküli hálózathoz."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Engedélyezze a Wi-Fi-hívást a hívásindításhoz."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Segélyhívás"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Rádió bekapcsolása..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Nincs szolgáltatás. Újrapróbálkozás folyamatban…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Rezgés"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Rezgés"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vizuális hangpostaüzenet"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN-kód beállítása"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN-kód módosítása"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Hang"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Csengőhang és rezgés"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Beépített SIM kártyák"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Csak segélyhívás"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM kártya, bővítőhely: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Kisegítő lehetőségek"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Beérkező Wi-Fi-hívás"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi-hívás tőle:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi-hívás"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Koppintson rá ismét a megnyitáshoz"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Hiba történt az üzenet dekódolása közben."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Egy SIM kártya aktiválta a szolgáltatást, valamint frissítette a telefon barangolási képességeit."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Túl sok aktív hívás van. Új hívás indítása előtt fejezzen be vagy vonjon össze meglévő hívásokat."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"A hangposta PIN-kódjának módosítása"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Folytatás"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Mégse"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"A régi PIN-kód megerősítése"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Írja be a hangpostához használt PIN-kódját a folytatáshoz."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Állíts be új PIN-kódot"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"A PIN-kódnak <xliff:g id="MIN">%1$d</xliff:g>–<xliff:g id="MAX">%2$d</xliff:g> számjegyből kell állnia."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"PIN-kód megerősítése"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"A PIN-kódok nem egyeznek"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"A hangpostához használt PIN-kód frissítve"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Nem sikerült beállítani a PIN-kódot"</string>
</resources>
diff --git a/res/values-hy-rAM/strings.xml b/res/values-hy-rAM/strings.xml
index 3613912..2d03c25 100644
--- a/res/values-hy-rAM/strings.xml
+++ b/res/values-hy-rAM/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Ոչ մի փոփոխություն կատարված չէ:"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Ընտրել ձայնային փոստի ծառայությունը"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Ձեր օպերատորը"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Հին PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Նոր PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Խնդրում ենք սպասել:"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Նոր PIN-ը չափազանց կարճ է:"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Նոր PIN-ը չափազանց երկար է:"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Նոր PIN-ը բավականաչափ հուսալի չէ: Հուսալի գաղտնաբառը չպետք է ունենա շարունակական հաջորդականություն կամ կրկնվող թվեր:"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Հին PIN-ը չի համընկնում:"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Նոր PIN-ը պարունակում է անվավեր գրանշաններ:"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Չհաջողվեց փոխել PIN-ը"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Հաղորդագրության չաջակցվող տեսակ, զանգեք <xliff:g id="NUMBER">%s</xliff:g> համարին՝ լսելու համար:"</string>
<string name="mobile_networks" msgid="2843854043339307375">"Բջջային ցանցի կարգավորումները"</string>
<string name="label_available" msgid="1181658289009300430">"Հասանելի ցանցեր"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Որոնում..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA նախընտրելի"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Ընդլայնված 4G LTE ռեժիմ"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Ընդլայնված զանգ"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Ձայնի և կապի որակը բարելավելու համար օգտվեք LTE ծառայություններից (հանձնարարելի)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Տվյալները միացված են"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Թույլատրել տվյալների օգտագործումը"</string>
@@ -418,9 +429,9 @@
<string name="pin2_attempts" msgid="720736232885011507">\n"Ձեզ մնացել է <xliff:g id="NUMBER">%d</xliff:g> փորձ:"</string>
<string name="pin2_unblocked" msgid="7791600368153469078">"PIN2 կոդն այլևս արգելափակված չէ"</string>
<string name="pin2_error_exception" msgid="1088689322248996699">"Ցանցի կամ SIM քարտի սխալ"</string>
- <string name="doneButton" msgid="2859593360997984240">"Կատարված է"</string>
+ <string name="doneButton" msgid="2859593360997984240">"Պատրաստ է"</string>
<string name="voicemail_settings_number_label" msgid="8524164258691887790">"Ձայնային փոստի համարը"</string>
- <string name="card_title_dialing" msgid="5769417478498348054">"Համարարկվում է"</string>
+ <string name="card_title_dialing" msgid="5769417478498348054">"Համարը հավաքվում է"</string>
<string name="card_title_redialing" msgid="8253487008234167266">"Վերահամարարկում"</string>
<string name="card_title_conf_call" msgid="1162980346189744501">"Կոնֆերանս զանգ"</string>
<string name="card_title_incoming_call" msgid="7364539451234646909">"Մուտքային զանգ"</string>
@@ -436,12 +447,13 @@
<string name="notification_network_selection_text" msgid="2607085729661923269">"Ընտրված ցանցը (<xliff:g id="OPERATOR_NAME">%s</xliff:g>) անհասանելի է"</string>
<string name="incall_error_power_off" msgid="2947938060513306698">"Զանգ կատարելու համար անջատեք Ինքնաթիռի ռեժիմը:"</string>
<string name="incall_error_power_off_wfc" msgid="8711428920632416575">"Զանգ կատարելու համար անջատեք Ինքնաթիռի ռեժիմը կամ միացեք անլար ցանցին:"</string>
- <string name="incall_error_ecm_emergency_only" msgid="738708660612388692">"Սովորական զանգ կատարելու համար դուրս եկեք արտակարգ իրավիճակների հետզանգի ռեժիմից:"</string>
+ <string name="incall_error_ecm_emergency_only" msgid="738708660612388692">"Սովորական զանգ կատարելու համար դուրս եկեք շտապ կանչի ռեժիմից։"</string>
<string name="incall_error_emergency_only" msgid="4678640422710818317">"Ցանցում գրանցված չէ:"</string>
<string name="incall_error_out_of_service" msgid="4100065333878929223">"Բջջային ցանցն անհասանելի է:"</string>
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Բջջային ցանցն անհասանելի է: Զանգ կատարելու համար միացեք անլար ցանցին:"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Զանգ կատարելու համար մուտքագրեք ճիշտ համար:"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Զանգը ձախողվեց:"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Այս պահին հնարավոր չէ զանգել:"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Մեկնարկում է MMI հաջորդականությունը..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Ծառայությունը չի աջակցվում"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Հնարավոր չէ փոխանջատել զանգը:"</string>
@@ -452,10 +464,11 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Հնարավոր չէ անջատել զանգ(եր)ը:"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Հնարավոր չէ հետաձգել զանգերը:"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Զանգ կատարելու համար միացեք անլար ցանցին:"</string>
- <string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Արտակարգ իրավիճակների զանգ"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Զանգ կատարելու համար միացրեք «Զանգեր Wi-Fi ցանցի միջոցով» գործառույթը:"</string>
+ <string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Շտապ կանչ"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Ռադիոն միացվում է..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ծառայությունը մատչելի չէ: Նորից փորձեք…"</string>
- <string name="radio_off_during_emergency_call" msgid="2535800034010306830">"Արտակարգ իրավիճակների զանգի ժամանակ հնարավոր չէ մտնել ինքնաթիռի ռեժիմ:"</string>
+ <string name="radio_off_during_emergency_call" msgid="2535800034010306830">"Շտապ կանչի ժամանակ հնարավոր չէ մտնել ինքնաթիռի ռեժիմ:"</string>
<string name="dial_emergency_error" msgid="1509085166367420355">"Հնարավոր չէ զանգել: <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> համարը արտակարգ իրավիճակի համար չէ:"</string>
<string name="dial_emergency_empty_error" msgid="9130194953830414638">"Հնարավոր չէ զանգել: Հավաքեք արտակարգ իրավիճակի որևէ համար:"</string>
<string name="dialerKeyboardHintText" msgid="9192914825413747792">"Օգտագործեք ստեղնաշարը՝ համարհավաքման համար"</string>
@@ -476,8 +489,8 @@
<string name="importToFDNfromContacts" msgid="2130620207013368580">"Ներմուծել կոնտակտներից"</string>
<string name="singleContactImportedMsg" msgid="6868483416182599206">"Ներմուծված կոնտակտ"</string>
<string name="failedToImportSingleContactMsg" msgid="415399285420353917">"Չհաջողվեց ներմուծել կոնտակտը"</string>
- <string name="hac_mode_title" msgid="8740268574688743289">"Լսողական օգնական"</string>
- <string name="hac_mode_summary" msgid="6833851160514929341">"Միացնել լսողական օգնականի համատեղելիությունը"</string>
+ <string name="hac_mode_title" msgid="8740268574688743289">"Լսողական ապարատ"</string>
+ <string name="hac_mode_summary" msgid="6833851160514929341">"Միացնել լսողական ապարատի աջակցումը"</string>
<string-array name="tty_mode_entries">
<item msgid="512950011423868021">"TTY-ն անջատված է"</item>
<item msgid="3971695875449640648">"TTY Full"</item>
@@ -528,7 +541,7 @@
<item quantity="one">Նշված գործողությունն Արտակարգ իրավիճակների հետզանգի ռեժիմում հասանելի չէ: Հեռախոսը գտնվելու է այս ռեժիմում <xliff:g id="COUNT_1">%s</xliff:g> րոպե: Ցանկանո՞ւմ եք դուրս գալ հիմա:</item>
<item quantity="other">Նշված գործողությունն Արտակարգ իրավիճակների հետզանգի ռեժիմում հասանելի չէ: Հեռախոսը գտնվելու է այս ռեժիմում <xliff:g id="COUNT_1">%s</xliff:g> րոպե: Ցանկանո՞ւմ եք դուրս գալ հիմա:</item>
</plurals>
- <string name="alert_dialog_in_ecm_call" msgid="1886723687211887104">"Ընտրված գործողությունը մատչելի չէ արտակարգ հետզանգի ռեժիմում գտնվելիս:"</string>
+ <string name="alert_dialog_in_ecm_call" msgid="1886723687211887104">"Ընտրված գործողությունը հասանելի չէ շտապ կանչի ժամանակ:"</string>
<string name="progress_dialog_exiting_ecm" msgid="4835734101617817074">"Դուրս է գալիս արտակարգ իրավիճակների հետզանգի ռեժիմից"</string>
<string name="alert_dialog_yes" msgid="6674268047820703974">"Այո"</string>
<string name="alert_dialog_no" msgid="1476091437797628703">"Ոչ"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Թրթռալ"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Թրթռալ"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Տեսանելի ձայնային փոստ"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Սահմանել PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Փոխել PIN-ը"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Ձայն"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ձայներանգ & Թրթռոց"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Ներկառուցված SIM քարտեր"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Միայն արտակարգ իրավիճակների զանգեր"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM քարտ, բնիկը՝ <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Մատչելիություն"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Մուտքային Wi-Fi զանգ"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi զանգ այս օգտվողից՝"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Զանգ Wi-Fi-ի միջոցով"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Կրկին հպեք՝ բացելու համար"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Հաղորդագրությունն ապակոդավորելիս սխալ առաջացավ:"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM քարտն ակտիվացրել է ծառայությունը և թարմացրել ձեր հեռախոսի ռոումինգի հնարավորությունները:"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Չափազանց շատ ընթացիկ զանգեր կան: Ավարտեք կամ միավորեք առկա զանգերը՝ նախքան նորն զանգ կատարելը:"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Փոխել ձայնային փոստի PIN-ը"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Շարունակել"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Չեղարկել"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Լավ"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Հաստատեք ձեր հին PIN-ը"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Շարունակելու համար մուտքագրեք ձայնային փոստի PIN-ը:"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Սահմանեք նոր PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN-ը պետք է բաղկացած լինի <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="8113764019347322170">"Հաստատեք ձեր PIN-ը"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-երը չեն համընկնում"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Ձայնային փոստի PIN-ը թարմացվեց"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Չհաջողվեց սահմանել PIN"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 56711b7..444bc42 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Tidak ada perubahan yang dilakukan."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Pilih layanan kotak pesan"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operator Anda"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN Lama"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"PIN Baru"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Mohon tunggu."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"PIN baru terlalu pendek."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"PIN baru terlalu panjang."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"PIN baru terlalu lemah. Sandi yang kuat tidak boleh memiliki urutan karakter kontinu atau digit berulang."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"PIN lama tidak cocok."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"PIN baru berisi karakter yang tidak valid."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Tidak dapat mengubah PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Tipe pesan tidak didukung, telepon <xliff:g id="NUMBER">%s</xliff:g> untuk mendengarkan."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Setelan jaringan seluler"</string>
<string name="label_available" msgid="1181658289009300430">"Jaringan yang tersedia"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Menelusuri…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA lebih disukai"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Mode LTE 4G yang Ditingkatkan"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Panggilan Telepon Lanjutan"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Gunakan layanan LTE untuk menyempurnakan suara dan komunikasi lainnya (disarankan)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data diaktifkan"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Izinkan penggunaan data"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Jaringan selular tidak tersedia. Sambungkan ke jaringan nirkabel untuk melakukan panggilan."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Untuk melakukan panggilan telepon, masukkan nomor yang valid."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Telepon gagal."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Panggilan tidak dapat ditambahkan untuk saat ini."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Memulai urutan MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Layanan tidak didukung"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Tidak dapat berganti panggilan telepon."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Tidak dapat melepas panggilan telepon."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Tidak dapat menahan panggilan."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Sambungkan ke jaringan nirkabel untuk melakukan panggilan"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Aktifkan panggilan Wi-Fi untuk melakukan panggilan."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Panggilan darurat"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Menghidupkan radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Tidak ada layanan. Mencoba lagi…"</string>
@@ -473,7 +486,7 @@
<string name="hac_mode_title" msgid="8740268574688743289">"Alat bantu dengar"</string>
<string name="hac_mode_summary" msgid="6833851160514929341">"Hidupkan kompatibilitas alat bantu dengar"</string>
<string-array name="tty_mode_entries">
- <item msgid="512950011423868021">"TTY Mati"</item>
+ <item msgid="512950011423868021">"TTY Nonaktif"</item>
<item msgid="3971695875449640648">"TTY Penuh"</item>
<item msgid="1937509904407445684">"TTY HCO"</item>
<item msgid="5644925873488772224">"TTY VCO"</item>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Getar"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Getar"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Kotak Pesan Visual"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Setel PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Ubah PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Suara"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Nada dering & Getar"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Kartu SIM internal"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Hanya untuk panggilan darurat"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Aksesibilitas"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Panggilan Wi-Fi masuk"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Panggilan Wi-Fi dari"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Panggilan Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Ketuk lagi untuk membuka"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Terjadi kesalahan saat mendekode pesan."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Kartu SIM telah mengaktifkan layanan dan memperbarui kemampuan roaming ponsel."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Ada terlalu banyak panggilan aktif. Akhiri atau gabungkan panggilan yang ada sebelum melakukan panggilan baru."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Ubah PIN Pesan Suara"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Lanjutkan"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Batal"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Oke"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Konfirmasi PIN lama Anda"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Masukkan PIN pesan suara Anda untuk melanjutkan."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Setel PIN baru"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN harus <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> digit."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Konfirmasi PIN Anda"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN tidak cocok"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN pesan suara diperbarui"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Tidak dapat menyetel PIN"</string>
</resources>
diff --git a/res/values-is-rIS/strings.xml b/res/values-is-rIS/strings.xml
index 8bf57ea..1bc1bf0 100644
--- a/res/values-is-rIS/strings.xml
+++ b/res/values-is-rIS/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Engu var breytt."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Velja talhólfsþjónustu"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Símafyrirtækið þitt"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Gamla PIN-númerið"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nýtt PIN-númer"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Augnablik."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Nýja PIN-númerið er of stutt."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Nýja PIN-númerið er of langt."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Nýja PIN-númerið er ekki nógu sterkt. Sterk aðgangsorð mega ekki vera með tölustafi í beinni röð eða endurtekna tölustafi."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Gamla PIN-númerið passar ekki."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Nýja PIN-númerið inniheldur ógilda stafi."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Ekki var hægt að breyta PIN-númerinu"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Óstudd skilaboðagerð, hringdu í <xliff:g id="NUMBER">%s</xliff:g> til að hlusta."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Farsímakerfisstillingar"</string>
<string name="label_available" msgid="1181658289009300430">"Símkerfi í boði"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Leitar…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA fyrsta val"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"endurbætt 4G LTE-stilling"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Betri símtöl"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Nota LTE-þjónustu til að bæta talsamband og önnur samskipti (ráðlagt)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Kveikt á gagnaaðgangi"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Leyfa gagnanotkun"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Farsímakerfi er ekki í boði. Tengstu þráðlausu neti til að hringja."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Sláðu inn gilt númer til að hringja símtal."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Tókst ekki að hringja."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Ekki er hægt að bæta símtali við sem stendur."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Ræsir MMI-runu…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Þjónusta ekki studd"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Ekki hægt að skipta milli símtala."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Ekki hægt að leggja á."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Getur ekki sett símtöl í bið."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Tengstu þráðlausu neti til að hringja."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Virkjaðu Wi-Fi símtöl til að hringja."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Neyðarsímtal"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Kveikir á loftneti…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ekkert samband. Reynir aftur…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Titringur"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Titringur"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Myndrænt talhólf"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Stilla PIN-númer"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Breyta PIN-númeri"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Hljóð"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Hringitónn og titringur"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Innbyggð SIM-kort"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Eingöngu neyðarsímtöl"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-kort, rauf: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Aðgengi"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Wi-Fi símtal berst"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi símtal frá"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi símtal"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Ýttu aftur til að opna"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Villa kom upp við að afkóða skeytið."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM-kort hefur virkjað þjónustuna þína og uppfært reikigetu símans."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Of mörg símtöl eru virk. Ljúktu eða sameinaðu fyrirliggjandi símtöl áður en þú hringir nýtt."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Breyta PIN-númeri talhólfs"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Halda áfram"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Hætta við"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Í lagi"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Staðfestu gamla PIN-númerið"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Sláðu inn PIN-númerið fyrir talhólf til að halda áfram."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Veldu nýtt PIN-númer"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN-númerið verður að vera <xliff:g id="MIN">%1$d</xliff:g>–<xliff:g id="MAX">%2$d</xliff:g> tölustafir."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Staðfestu PIN-númerið"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-númerin stemma ekki"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN-númer fyrir talhólf uppfært"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Ekki hægt að stilla PIN-númer"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 7c26677..8bf4340 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Nessuna modifica effettuata."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Scegli il servizio di segreteria"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operatore"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Vecchio PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nuovo PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Attendi."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Il nuovo PIN è troppo corto."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Il nuovo PIN è troppo lungo."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Il nuovo PIN è troppo semplice. Una password efficace non deve contenere sequenze continue o cifre ripetute."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Il vecchio PIN non corrisponde."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Il nuovo PIN contiene caratteri non validi."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Impossibile cambiare il PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Tipo di messaggio non supportato, chiama <xliff:g id="NUMBER">%s</xliff:g> per ascoltare."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Impostazioni rete cellulare"</string>
<string name="label_available" msgid="1181658289009300430">"Reti disponibili"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Ricerca..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferito"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Modalità 4G LTE avanzata"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Chiamata avanzata"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Usa i servizi LTE per migliorare la voce e le altre comunicazioni (consigliato)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Dati attivati"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Consenti l\'utilizzo dei dati"</string>
@@ -440,6 +451,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"La rete cellulare non è disponibile. Connettiti a una rete wireless per effettuare una chiamata."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Per effettuare una chiamata, inserisci un numero valido."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Chiamata non riuscita."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Al momento non è possibile aggiungere la chiamata."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Inizio sequenza MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Servizio non supportato"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Impossibile cambiare chiamata."</string>
@@ -450,6 +462,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Impossibile riagganciare."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Impossibile mettere in attesa le chiamate."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Connettiti a una rete wireless per effettuare una chiamata."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Attiva le chiamate tramite Wi-Fi per effettuare una chiamata."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Chiamata di emergenza"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Attivazione segnale cellulare..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Nessun servizio. Nuovo tentativo…"</string>
@@ -544,6 +557,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrazione"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrazione"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Leggi la segreteria"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Imposta PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Cambia PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Suono"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Suoneria e vibrazione"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Schede SIM integrate"</string>
@@ -555,10 +570,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Solo chiamate di emergenza"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Scheda SIM, slot: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accessibilità"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Chiamata Wi-Fi in arrivo"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Chiamata Wi-Fi da"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Chiamata Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Tocca di nuovo per aprire"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Si è verificato un errore durante la decodifica del messaggio."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Una scheda SIM ha attivato il tuo servizio e ha aggiornato le funzionalità di roaming del telefono."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Ci sono troppe chiamate attive. Termina o unisci le chiamate esistenti prima di effettuarne una nuova."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Cambia PIN segreteria"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continua"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Annulla"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Conferma il PIN precedente"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Inserisci il PIN della segreteria per continuare."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Imposta un nuovo PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Il PIN deve contenere da <xliff:g id="MIN">%1$d</xliff:g> a <xliff:g id="MAX">%2$d</xliff:g> cifre."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Conferma il tuo PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"I PIN non corrispondono"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN segreteria aggiornato"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Impossibile impostare il PIN"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 1ee7865..6e4ea22 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"לא בוצעו שינויים."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"בחר שירות של דואר קולי"</string>
<string name="voicemail_default" msgid="2001233554889016880">"הספק שלך"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"קוד גישה ישן"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"קוד גישה חדש"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"אנא המתן."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"קוד הגישה החדש קצר מדי."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"קוד הגישה החדש ארוך מדי."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"קוד הגישה החדש חלש מדי. בסיסמה חזקה אסור שיהיו ספרות ברצף מספרי או ספרות שחוזרות על עצמן."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"קוד הגישה הישן אינו תואם."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"קוד הגישה החדש מכיל תווים לא חוקיים."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"לא ניתן לשנות את קוד הגישה"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"סוג ההודעה לא נתמך. התקשר למספר <xliff:g id="NUMBER">%s</xliff:g> כדי להאזין לה."</string>
<string name="mobile_networks" msgid="2843854043339307375">"הגדרות רשת סלולרית"</string>
<string name="label_available" msgid="1181658289009300430">"רשתות זמינות"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"מחפש..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA מועדף"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"מצב 4G LTE משופר"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"שיחה משופרת"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"השתמש בשירותי LTE כדי לשפר את הקול ודרכי תקשורת אחרות (מומלץ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"נתונים מופעלים"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"התר שימוש בנתונים"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"רשת סלולרית אינה זמינה. התחבר לרשת אלחוטית כדי לבצע שיחה."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"כדי להתקשר, הזן מספר טלפון חוקי."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"השיחה נכשלה."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"לא ניתן להוסיף את השיחה כרגע."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"מתחיל רצף MMI…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"שירות לא נתמך"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"לא ניתן לעבור בין שיחות."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"לא ניתן לשחרר שיחות."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"לא ניתן להחזיק שיחות."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"התחבר לרשת אלחוטית כדי לבצע שיחה."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"הפעל את \'שיחות Wi-Fi\' כדי להתקשר."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"שיחת חירום"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"מפעיל את הרדיו…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"אין שירות. מנסה שוב..."</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"רטט"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"רטט"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"דואר קולי ויזואלי"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"הגדרת קוד גישה"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"שינוי קוד הגישה"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"צליל"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"רינגטון ורטט"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"כרטיסי SIM מובנים"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"שיחות חירום בלבד"</string>
<string name="sim_description_default" msgid="4778679519938775515">"כרטיס SIM, חריץ: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"נגישות"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"שיחת Wi-Fi נכנסת"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"שיחת Wi-Fi מאת"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"שיחת Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"הקש שוב כדי לפתוח"</string>
<string name="message_decode_error" msgid="3456481534066924855">"אירעה שגיאה בעת פענוח ההודעה."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"כרטיס SIM הפעיל את השירות שלך ועדכן את יכולות הנדידה של הטלפון."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"יש יותר מדי שיחות פעילות. כדי להתחיל שיחה חדשה עליך לסיים או למזג חלק מהשיחות הפעילות."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"שינוי של קוד הגישה לדואר הקולי"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"המשך"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"ביטול"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"אישור"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"אשר את קוד הגישה הישן"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"הזן את קוד הגישה לדואר הקולי כדי להמשיך."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"הגדר קוד גישה חדש"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"האורך של קוד הגישה חייב להיות <xliff:g id="MAX">%2$d</xliff:g>-<xliff:g id="MIN">%1$d</xliff:g> ספרות."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"אשר את קוד הגישה"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"קודי הגישה אינם תואמים"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"קוד הגישה לדואר הקולי עודכן"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"לא ניתן להגדיר את קוד הגישה"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index d3de4fd..480bfab 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"変更されていません。"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"ボイスメールサービスを選択"</string>
<string name="voicemail_default" msgid="2001233554889016880">"携帯通信会社"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"古い PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"新しい PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"お待ちください。"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"新しい PIN が短すぎます。"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"新しい PIN が長すぎます。"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"新しい PIN の強度が弱すぎます。パスワードには連続する文字や、数字の繰り返しは使用しないでください。"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"古い PIN が一致しません。"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"新しい PIN に無効な文字が含まれています。"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN を変更できませんでした"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"サポートされていないメッセージ タイプです。<xliff:g id="NUMBER">%s</xliff:g> 宛に電話をかけてメッセージをお聞きください。"</string>
<string name="mobile_networks" msgid="2843854043339307375">"モバイルネットワーク設定"</string>
<string name="label_available" msgid="1181658289009300430">"利用可能なネットワーク"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"検索中..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMAを優先"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"4G LTE拡張モード"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"高度な通話機能"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"LTEサービスを使用して音声などの通信を改善する(推奨)"</string>
<string name="data_enabled" msgid="5972538663568715366">"データ通信を有効にする"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"データ使用を許可"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"モバイルネットワークが利用できません。電話をかけるには無線ネットワークに接続してください。"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"発信するには、有効な番号を入力してください。"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"発信できませんでした。"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"現在、通話を追加できません。"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMIシーケンスを開始中..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"サービスはサポートされていません"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"通話を切り替えられません。"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"通話を解放できません。"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"通話を保留にできません。"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"電話をかけるには無線ネットワークに接続してください。"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"電話をかけるには Wi-Fi 通話を有効にしてください。"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"緊急通報"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"無線通信をONにしています..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"通信サービスはありません。もう一度お試しください…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"バイブレーション"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"バイブレーション"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"ビジュアルボイスメール"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN の設定"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN の変更"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"通知音"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"着信音とバイブレーション"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"内蔵のSIMカード"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"緊急通報のみ"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIMカード、スロット: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ユーザー補助機能"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Wi-Fi通話が着信中"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi 通話の着信"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi通話"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"開くにはもう一度タップしてください"</string>
<string name="message_decode_error" msgid="3456481534066924855">"メッセージのデコード中にエラーが発生しました。"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIMカードでサービスが有効になり、スマートフォンのローミング機能が更新されています。"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"通話中の電話の数が多すぎます。新しく通話を発信するには、まず既存の通話を終了するか、統合してグループ通話にしてください。"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"ボイスメール PIN の変更"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"続行"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"キャンセル"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"古い PIN の確認"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"続行するにはボイスメール PIN を入力してください。"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"新しい PIN の設定"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN は <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="8113764019347322170">"PIN の確認"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN が一致しません"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"ボイスメール PIN を更新しました"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN を設定できません"</string>
</resources>
diff --git a/res/values-ka-rGE/strings.xml b/res/values-ka-rGE/strings.xml
index 924dc17..bdd6411 100644
--- a/res/values-ka-rGE/strings.xml
+++ b/res/values-ka-rGE/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"ცვლილებები არ განხორციელებულა."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"ხმოვანი ფოსტის სერვისის არჩევა"</string>
<string name="voicemail_default" msgid="2001233554889016880">"თქვენი ოპერატორი"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"ძველი PIN-კოდი"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"ახალი PIN-კოდი"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"გთხოვთ, დაელოდოთ."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"ახალი PIN-კოდი ძალიან მოკლეა."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"ახალი PIN-კოდი ძალიან გრძელია."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"ახალი PIN-კოდი ძალიან სუსტია. ძლიერი პაროლი არ უნდა შეიცავდეს გამეორებული ციფრების გრძელ თანმიმდევრობას."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"ძველი PIN-კოდი არ თანხვდება."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"ახალი PIN-კოდი არასწორ სიმბოლოებს შეიცავს."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN-კოდის შეცვლა შეუძლებელია"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"შეტყობინების ტიპი მხარდაუჭერელია. მოსასმენად დარეკეთ <xliff:g id="NUMBER">%s</xliff:g>-ზე."</string>
<string name="mobile_networks" msgid="2843854043339307375">"ფიჭური ქსელის პარამეტრებიჶ"</string>
<string name="label_available" msgid="1181658289009300430">"ხელმისაწვდომი ქსელები"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"ძიება..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA უპირატესობით"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"გაუმჯობესებული 4G LTE რეჟიმი"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"გაუმჯობესებული დარეკვა"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"ხმოვანი და სხვა სახის კომუნიკაციებიგამოიყენეთ LTE მომსახურება გაუმჯობესება ხმა და სხვა კომუნიკაციები (რეკომენდირებულია)"</string>
<string name="data_enabled" msgid="5972538663568715366">"მონაცემთა გადაცემა ჩართულია჻"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"მონაცემების გამოყენება"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"ფიჭური ქსელი მიუწვდომელია. ზარის განსახორციელებლად, დაუკავშირდით უსადენო ქსელს."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"ზარის განხორციელებისათვის, შეიყვანეთ მოქმედი ნომერი."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"ზარი ვერ განხორციელდა."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ამჯერად ზარის დამატება ვერ ხერხდება."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI თანმიმდევრობის დაწყება…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"მომსახურება არ არის მხარდაჭერილი"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"ვერ ხორციელდება ზარების გადართვა."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"ვერ ხერხდება ზარ(ებ)ის გაშვება."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"ზარების დაყოვნება ვერ ხერხდება."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ზარის განსახორციელებლად, დაუკავშირდით უსადენო ქსელს."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"ზარის განსახორციელებლად ჩართეთ Wi-Fi დარეკვა."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"გადაუდებელი ზარი"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"გადამცემის ჩართვა…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"მომხსახურება არ არის. სცადეთ ხელხლა..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"ვიბრაცია"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"ვიბრაცია"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"ვიზუალური ხმოვანი ფოსტა"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"დააყენეთ PIN-კოდი"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN-კოდის შეცვლა"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ხმა"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"ზარის მელოდია & ვიბრაცია"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"ჩაშენებული SIM ბარათები"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"მხოლოდ საგანგებო ნომრებზე დარეკვა"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM ბარათი, სლოტი: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"მარტივი წვდომა"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"შემომავალი Wi-Fi ზარი"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi ზარი აბონენტისგან"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi ზარი"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"გასახსნელად, შეეხეთ ხელახლა"</string>
<string name="message_decode_error" msgid="3456481534066924855">"შეტყობინების გაშიფრვისას წარმოიშვა შეცდომა."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM ბარათმა გაააქტიურა თქვენი სერვისი და თქვენი ტელეფონის როუმინგის შესაძლებლობები განაახლა."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"ძალიან ბევრი აქტიური ზარია. გთხოვთ, დაასრულოთ ან გააერთიანოთ არსებული ზარები ახალი ზარის განხორციელებამდე."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"ხმოვანი ფოსტის PIN-კოდის შეცვლა"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"გაგრძელება"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"გაუქმება"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"კარგი"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"დაადასტურეთ თქვენი ძველი PIN-კოდი"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"გასაგრძელებლად შეიყვანეთ თქვენი ხმოვანი ფოსტის PIN-კოდი."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"დააყენეთ ახალი PIN-კოდი"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN-კოდი უნდა იყოს <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="8113764019347322170">"დაადასტურეთ PIN-კოდი"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-კოდები არ ემთხვევა"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"ხმოვანი ფოსტის PIN-კოდი განახლდა"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN-კოდის დაყენება შეუძლებელია"</string>
</resources>
diff --git a/res/values-kk-rKZ/strings.xml b/res/values-kk-rKZ/strings.xml
index b810ec3..877ecbb 100644
--- a/res/values-kk-rKZ/strings.xml
+++ b/res/values-kk-rKZ/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Еш өзгеріс жасалмаған."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Дауыс хабары қызметін таңдау"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Операторыңыз"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Ескі PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Жаңа PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Күте тұрыңыз."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Жаңа PIN код тым қысқа."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Жаңа PIN код тым ұзын."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Жаңа PIN код тым әлсіз. Күшті құпия сөзде үздіксіз реттік немесе қайталанатын таңбалар болмауы тиіс."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Ескі PIN код сәйкес келмейді."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Жаңа PIN кодта жарамсыз таңбалар бар."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN кодты өзгерту мүмкін емес"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Қолдау көрсетілмейтін хабар түрі, тыңдау үшін <xliff:g id="NUMBER">%s</xliff:g> нөміріне қоңырау шалыңыз."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Ұялы желі параметрлері"</string>
<string name="label_available" msgid="1181658289009300430">"Қол жетімді желілер"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Іздеуде…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA қалаулы"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Жақсартылған 4G LTE режимі"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Кеңейтілген қоңырау шалу мүмкіндіктері"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Дауыстық және басқа байланыстарды жақсарту үшін LTE қызметтерін пайдалану (ұсынылады)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Дерекқор қосылған"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Деректерді пайдалануға рұқсат ету"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Ұялы желі қол жетімді емес. Қоңырау шалу үшін сымсыз желіге қосылыңыз."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Қоңырау шалу үшін жарамды нөмірді енгізіңіз."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Қоңырау шалынбады."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Қоңырауды қазіргі уақытта қосу мүмкін емес."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI қатарын бастау…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Қызметке қолдау көрсетілмейді"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Қоңырауларды ауыстыру мүмкін емес."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Қоңырау(лар)ды босату мүмкін емес."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Қоңырауларды ұстау мүмкін емес."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Қоңырау шалу үшін сымсыз желіге қосылыңыз."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Қоңырау шалу үшін, Wi-Fi желісін қосыңыз."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Төтенше қоңырау"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Радионы қосуда…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Қызмет жоқ. Әрекет қайталануда…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Діріл"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Діріл"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Визуалды дауыс поштасы"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN кодын орнату"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN кодты өзгерту"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Дыбыс"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Рингтон& Діріл"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Кірістірілген SIM карталары"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Тек жедел қоңыраулар"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM картасы, ұяшық: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Арнайы мүмкіндіктер"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Кіріс Wi-Fi қоңырауы"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi қоңырауын шалушы:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi қоңырауы"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Ашу үшін қайта түртіңіз"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Хабарды кодтан шығару кезінде қате пайда болды."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM карта қызметті белсендіріп, телефонның роуминг мүмкіндіктерін жаңартты."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Белсенді қоңыраулар тым көп. Жаңа қоңырау шалудан бұрын бар қоңырауларды аяқтаңыз немесе біріктіріңіз."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Дауыстық пошта PIN кодын өзгерту"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Жалғастыру"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Тоқтату"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Жарайды"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Ескі PIN кодыңызды растаңыз"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Жалғастыру үшін, дауыстық поштаңыздың PIN кодын енгізіңіз."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Жаңа PIN кодын орнатыңыз"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN коды <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="8113764019347322170">"PIN кодын растаңыз"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN кодтары сәйкес келмейді"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Дауыстық пошта PIN коды жаңартылды"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN кодын орнату мүмкін болмады"</string>
</resources>
diff --git a/res/values-km-rKH/strings.xml b/res/values-km-rKH/strings.xml
index 6e5aaca..a41b1ab 100644
--- a/res/values-km-rKH/strings.xml
+++ b/res/values-km-rKH/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"មិនបានប្ដូរ។"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"ជ្រើសសេវាសារជាសំឡេង"</string>
<string name="voicemail_default" msgid="2001233554889016880">"អ្នកផ្តល់សេវាទូរស័ព្ទរបស់អ្នក"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"លេខកូដ PIN ថ្មី"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"លេខកូដ PIN ថ្មី"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"សូមរង់ចាំ។"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"លេខកូដ PIN ថ្មីខ្លីពេក។"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"លេខកូដ PIN ថ្មីវែងពេក។"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"លេខកូដ PIN ថ្មីខ្សោយពេក។ ពាក្យសម្ងាត់ដែលខ្លាំងមិនគួរមានលេខរៀងតគ្នា ឬស្ទួនគ្នាទេ។"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"លេខកូដ PIN ចាស់មិនត្រូវគ្នា។"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"លេខកូដ PIN ថ្មីមានតួអក្សរមិនត្រឹមត្រូវ។"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"មិនអាចប្ដូរលេខកូដ PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"មិនស្គាល់ប្រភេទសារ សូមហៅទូរស័ព្ទទៅ <xliff:g id="NUMBER">%s</xliff:g> ដើម្បីស្ដាប់។"</string>
<string name="mobile_networks" msgid="2843854043339307375">"ការកំណត់បណ្ដាញចល័ត"</string>
<string name="label_available" msgid="1181658289009300430">"បណ្ដាញដែលមាន"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"កំពុងស្វែងរក..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA ដែលចូលចិត្ត"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"របៀប 4G LTE ធ្វើឲ្យប្រសើរឡើង"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"ការហៅទូរសព្ទកម្រិតខ្ពស់"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"ប្រើសេវាកម្ម LTE ដើម្បីធ្វើឲ្យសម្លេង និងការទំនាក់ទំនងផ្សេងទៀតប្រសើរឡើង (បានណែនាំ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"បានបើកទិន្នន័យ"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"អនុញ្ញាតឲ្យប្រើប្រាស់ទិន្នន័យ"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"មិនមានបណ្តាញទូរស័ព្ទទេ។ ភ្ជាប់ទៅបណ្តាញឥតខ្សែដើម្បីធ្វើការហៅ។"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"ដើម្បីធ្វើការហៅ បញ្ចូលលេខដែលមានសុពលភាព។"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"បានបរាជ័យការហៅ។"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"មិនអាចបន្ថែមការហៅទូរសព្ទនៅពេលនេះបានទេ។"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"កំពុងចាប់ផ្ដើមលំដាប់ MMI ..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"សេវាកម្មមិនត្រូវបានគាំទ្រទេ។"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"មិនអាចឆ្លាស់ការហៅបានទេ។"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"មិនអាចបញ្ចេញការហៅបានទេ។"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"មិនអាចរង់ចាំការហៅទេ"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ភ្ជាប់ទៅបណ្តាញឥតខ្សែដើម្បីធ្វើការហៅ។"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"បើកការហៅតាមវ៉ាយហ្វាយដើម្បីធ្វើការហៅ។"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"ការហៅនៅពេលមានអាសន្ន"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"កំពុងបើកវិទ្យុ…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"គ្មានសេវាទេ។ ព្យាយាមម្តង…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"ញ័រ"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"ញ័រ"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"សារជាសំឡេងអាចមើលឃើញ"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"កំណត់លេខកូដ PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"ប្ដូរលេខកូដ PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"សំឡេង"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"សំឡេងរោទ៍ & ញ័រ"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"ស៊ីមកាតជាប់ជាមួយ"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"សម្រាប់ការហៅពេលអាសន្នប៉ុណ្ណោះ"</string>
<string name="sim_description_default" msgid="4778679519938775515">"ស៊ីមកាត រន្ធ៖ <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ភាពងាយស្រួល"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"មានការហៅចូលមកតាម Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"ការហៅតាម Wi-Fi ពី"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"ហៅតាម Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"ប៉ះម្ដងទៀតដើម្បីបើក"</string>
<string name="message_decode_error" msgid="3456481534066924855">"មានកំហុសខណៈពេលឌិកូដសារ។"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"ស៊ីមកាតបានធ្វើឲ្យសេវាកម្មរបស់អ្នកសកម្ម និងបានធ្វើបច្ចុប្បន្នភាពសមត្ថភាពរ៉ូមីងសម្រាប់ទូរស័ព្ទរបស់អ្នក។"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"មានការហៅដែលសកម្មច្រើនពេក។ សូមបញ្ចប់ ឬដាក់បញ្ចូលគ្នាការហៅដែលមានស្រាប់មុនពេលដាក់ការហៅថ្មី។"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"ប្ដូរលេខកូដ PIN ជាសារសំឡេង"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"បន្ត"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"បោះបង់"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"យល់ព្រម"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"បញ្ជាក់លេខកូដ PIN ចាស់របស់អ្នក"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"បញ្ចូលលេខកូដ PIN ជាសារសំឡេងរបស់អ្នកដើម្បីបន្ត។"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"កំណត់លេខកូដ PIN ថ្មី"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN ត្រូវតែមាន <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="8113764019347322170">"បញ្ជាក់លេខកូដ PIN របស់អ្នក"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"លេខកូដ PIN មិនត្រូវគ្នា"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"បានធ្វើបច្ចុប្បន្នភាពលេខកូដ PIN ជាសារសំលេង"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"មិនអាចកំណត់លេខកូដ PIN"</string>
</resources>
diff --git a/res/values-kn-rIN/strings.xml b/res/values-kn-rIN/strings.xml
index 8c036e6..6c04a99 100644
--- a/res/values-kn-rIN/strings.xml
+++ b/res/values-kn-rIN/strings.xml
@@ -21,14 +21,14 @@
<string name="emergencyDialerIconLabel" msgid="7812140032168171053">"ತುರ್ತು ಡಯಲರ್"</string>
<string name="phoneIconLabel" msgid="2331230813161304895">"ಫೋನ್"</string>
<string name="fdnListLabel" msgid="8630418672279521003">"FDN ಪಟ್ಟಿ"</string>
- <string name="unknown" msgid="6878797917991465859">"ಅಜ್ಞಾತ"</string>
+ <string name="unknown" msgid="6878797917991465859">"ಅಪರಿಚಿತ"</string>
<string name="private_num" msgid="6713286113000232309">"ಖಾಸಗಿ ಸಂಖ್ಯೆ"</string>
<string name="payphone" msgid="4793877574636445118">"ಪೇಫೋನ್"</string>
<string name="onHold" msgid="9035493194749959955">"ತಡೆಹಿಡಿಯಲಾಗಿದೆ"</string>
<string name="mmiStarted" msgid="6347869857061147003">"MMI ಕೋಡ್ ಪ್ರಾರಂಭಿಸಲಾಗಿದೆ"</string>
<string name="ussdRunning" msgid="485588686340541690">"USSD ಕೋಡ್ ಚಾಲನೆಯಲ್ಲಿದೆ…"</string>
<string name="mmiCancelled" msgid="2771923949751842276">"MMI ಕೋಡ್ ರದ್ದು ಮಾಡಲಾಗಿದೆ"</string>
- <string name="cancel" msgid="5044513931633602634">"ರದ್ದುಮಾಡು"</string>
+ <string name="cancel" msgid="5044513931633602634">"ರದ್ದುಮಾಡಿ"</string>
<string name="enter_input" msgid="1810529547726803893">"USSD ಸಂದೇಶದ ಅಕ್ಷರಗಳು <xliff:g id="MIN_LEN">%d</xliff:g> ಮತ್ತು <xliff:g id="MAX_LEN">%d</xliff:g> ನಡುವೆ ಇರಬೇಕು. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="manageConferenceLabel" msgid="4691922394301969053">"ಕಾನ್ಫರೆನ್ಸ್ ಕರೆಯನ್ನು ನಿರ್ವಹಿಸಿ"</string>
<string name="ok" msgid="3811371167865772377">"ಸರಿ"</string>
@@ -147,18 +147,28 @@
<string name="no_change" msgid="3186040086622435212">"ಯಾವುದೇ ಬದಲಾವಣೆಗಳನ್ನು ಮಾಡಲಿಲ್ಲ."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"ಧ್ವನಿಮೇಲ್ ಸೇವೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
<string name="voicemail_default" msgid="2001233554889016880">"ನನ್ನ ವಾಹಕ"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"ಹಳೆಯ ಪಿನ್"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"ಹೊಸ ಪಿನ್"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"ದಯವಿಟ್ಟು ನಿರೀಕ್ಷಿಸಿ."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"ಹೊಸ ಪಿನ್ ತುಂಬಾ ಚಿಕ್ಕದಾಗಿದೆ."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"ಹೊಸ ಪಿನ್ ತುಂಬಾ ಉದ್ದವಾಗಿದೆ."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"ಹೊಸ ಪಿನ್ ತುಂಬಾ ದುರ್ಬಲವಾಗಿದೆ. ಪ್ರಬಲ ಪಾಸ್ವರ್ಡ್ ನಿರಂತರ ಅನುಕ್ರಮ ಅಥವಾ ಪುನರಾವರ್ತಿತ ಅಂಕಿಗಳನ್ನು ಹೊಂದುವಂತಿಲ್ಲ."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"ಹಳೆಯ ಪಿನ್ ಹೊಂದಾಣಿಕೆಯಾಗುತ್ತಿಲ್ಲ."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"ಹೊಸ ಪಿನ್ ಅಮಾನ್ಯವಾದ ಅಕ್ಷರಗಳನ್ನು ಒಳಗೊಂಡಿದೆ."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"ಪಿನ್ ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"ಬೆಂಬಲಿತವಲ್ಲದ ಸಂದೇಶ ಮಾದರಿ, ಆಲಿಸಲು <xliff:g id="NUMBER">%s</xliff:g> ಗೆ ಕರೆ ಮಾಡಿ."</string>
<string name="mobile_networks" msgid="2843854043339307375">"ಸೆಲ್ಯುಲಾರ್ ನೆಟ್ವರ್ಕ್ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="label_available" msgid="1181658289009300430">"ಲಭ್ಯವಿರುವ ನೆಟ್ವರ್ಕ್ಗಳು"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
<string name="empty_networks_list" msgid="4249426905018815316">"ಯಾವುದೇ ನೆಟ್ವರ್ಕ್ಗಳು ಕಂಡುಬಂದಿಲ್ಲ."</string>
- <string name="search_networks" msgid="1601136049300882441">"ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ಹುಡುಕು"</string>
+ <string name="search_networks" msgid="1601136049300882441">"ನೆಟ್ವರ್ಕ್ಗಳನ್ನು ಹುಡುಕಿ"</string>
<string name="network_query_error" msgid="6828516148953325006">"ನೆಟ್ವರ್ಕ್ಗಳಿಗಾಗಿ ಹುಡುಕುತ್ತಿರುವಾಗ ದೋಷ."</string>
<string name="register_on_network" msgid="9055203954040805084">"<xliff:g id="NETWORK">%s</xliff:g> ನಲ್ಲಿ ನೋಂದಾಯಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="not_allowed" msgid="5613353860205691579">"ಈ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕವನ್ನು ನಿಮ್ಮ ಸಿಮ್ ಕಾರ್ಡ್ ಅನುಮತಿಸುವುದಿಲ್ಲ."</string>
<string name="connect_later" msgid="2308119155752343975">"ಇದೀಗ ಈ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಪಡಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="registration_done" msgid="495135664535876612">"ನೆಟ್ವರ್ಕ್ನಲ್ಲಿ ನೋಂದಾಯಿಸಲಾಗಿದೆ."</string>
<string name="sum_carrier_select" msgid="3494252551249882718">"ನೆಟ್ವರ್ಕ್ ಆಪರೇಟರ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
- <string name="sum_search_networks" msgid="2921092249873272715">"ಎಲ್ಲ ಲಭ್ಯವಿರುವ ನೆಟ್ವರ್ಕ್ಗಳಿಗಾಗಿ ಹುಡುಕು"</string>
+ <string name="sum_search_networks" msgid="2921092249873272715">"ಎಲ್ಲ ಲಭ್ಯವಿರುವ ನೆಟ್ವರ್ಕ್ಗಳಿಗಾಗಿ ಹುಡುಕಿ"</string>
<string name="select_automatically" msgid="5628402124471810174">"ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆಯ್ಕೆಮಾಡು"</string>
<string name="sum_select_automatically" msgid="5614890115123292400">"ಪ್ರಾಶಸ್ತ್ಯ ನೀಡಲಾದ ನೆಟ್ವರ್ಕ್ ಅನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಆಯ್ಕೆಮಾಡು"</string>
<string name="register_automatically" msgid="6017849844573519637">"ಸ್ವಯಂಚಾಲಿತ ನೋಂದಣಿ…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA ಗೆ ಪ್ರಾಶಸ್ತ್ಯ ನೀಡಲಾಗಿದೆ"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"ವರ್ಧಿಸಲಾದ 4G LTE ಮೋಡ್"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"ಸುಧಾರಿತ ಕರೆ"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"ಧ್ವನಿ ಮತ್ತು ಇತರ ಸಂವಹನಗಳನ್ನು ಸುಧಾರಿಸಲು LTE ಸೇವೆಗಳನ್ನು ಬಳಸಿ (ಶಿಫಾರಸು ಮಾಡಲಾಗಿದೆ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"ಡೇಟಾ ಸಕ್ರಿಯಗೊಂಡಿದೆ"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"ಡೇಟಾ ಬಳಕೆಯನ್ನು ಅನುಮತಿಸಿ"</string>
@@ -205,7 +216,7 @@
<string name="roaming" msgid="8871412572928323707">"ಡೇಟಾ ರೋಮಿಂಗ್"</string>
<string name="roaming_enable" msgid="7331106985174381987">"ರೋಮಿಂಗ್ನಲ್ಲಿರುವಾಗ ಡೇಟಾ ಸೇವೆಗಳಿಗೆ ಸಂಪರ್ಕಿಸು"</string>
<string name="roaming_disable" msgid="1843417228755568110">"ರೋಮಿಂಗ್ನಲ್ಲಿರುವಾಗ ಡೇಟಾ ಸೇವೆಗಳಿಗೆ ಸಂಪರ್ಕಿಸು"</string>
- <string name="roaming_reenable_message" msgid="8913735676127858115">"ಡೇಟಾ ರೋಮಿಂಗ್ ಅನ್ನು ಆಫ್ ಮಾಡಿರುವ ಸ್ಥಿತಿಯಲ್ಲಿ ನಿಮ್ಮ ಹೋಮ್ ನೆಟ್ವರ್ಕ್ ಅನ್ನು ನೀವು ಇರಿಸಿರುವ ಕಾರಣ ನೀವು ಡೇಟಾ ಸಂಪರ್ಕವನ್ನು ಕಳೆದುಕೊಂಡಿರುವಿರಿ."</string>
+ <string name="roaming_reenable_message" msgid="8913735676127858115">"ಡೇಟಾ ರೋಮಿಂಗ್ ಅನ್ನು ಆಫ್ ಮಾಡಿರುವ ಸ್ಥಿತಿಯಲ್ಲಿ ನಿಮ್ಮ ಮುಖಪುಟ ನೆಟ್ವರ್ಕ್ ಅನ್ನು ನೀವು ಇರಿಸಿರುವ ಕಾರಣ ನೀವು ಡೇಟಾ ಸಂಪರ್ಕವನ್ನು ಕಳೆದುಕೊಂಡಿರುವಿರಿ."</string>
<string name="roaming_warning" msgid="1603164667540144353">"ನೀವು ಗಣನೀಯವಾಗಿ ಶುಲ್ಕಗಳನ್ನು ತೆರಬೇಕಾಗಬಹುದು."</string>
<string name="roaming_alert_title" msgid="3654815360303826008">"ಡೇಟಾ ರೋಮಿಂಗ್ ಅನುಮತಿಸುವುದೇ?"</string>
<string name="gsm_umts_options" msgid="6538311689850981686">"GSM/UMTS ಆಯ್ಕೆಗಳು"</string>
@@ -355,7 +366,7 @@
<string name="auto_retry_mode_summary" msgid="4973886004067532288">"ಸ್ವಯಂ ಮರುಪ್ರಯತ್ನಿಸುವಿಕೆ ಮೋಡ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="tty_mode_not_allowed_video_call" msgid="3795846787901909176">"TTY ಮೋಡ್ ವೀಡಿಯೊ ಕರೆಯ ಸಂದರ್ಭದಲ್ಲಿ ಅನುಮತಿಸಲಾಗುವುದಿಲ್ಲ"</string>
<string name="menu_add" msgid="1882023737425114762">"ಸಂಪರ್ಕ ಸೇರಿಸಿ"</string>
- <string name="menu_edit" msgid="7143003705504672374">"ಸಂಪರ್ಕವನ್ನು ಸಂಪಾದಿಸಿ"</string>
+ <string name="menu_edit" msgid="7143003705504672374">"ಸಂಪರ್ಕವನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="menu_delete" msgid="3977150783449642851">"ಸಂಪರ್ಕವನ್ನು ಅಳಿಸಿ"</string>
<string name="get_pin2" msgid="8204677063922225311">"PIN2 ಅನ್ನು ಟೈಪ್ ಮಾಡಿ"</string>
<string name="name" msgid="7329028332786872378">"ಹೆಸರು"</string>
@@ -364,7 +375,7 @@
<string name="add_fdn_contact" msgid="2481915899633353976">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಿ"</string>
<string name="adding_fdn_contact" msgid="7627379633721940991">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="fdn_contact_added" msgid="7458335758501736665">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಯನ್ನು ಸೇರಿಸಲಾಗಿದೆ."</string>
- <string name="edit_fdn_contact" msgid="7976936035587081480">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಯನ್ನು ಸಂಪಾದಿಸಿ"</string>
+ <string name="edit_fdn_contact" msgid="7976936035587081480">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಯನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
<string name="updating_fdn_contact" msgid="8370929876849803600">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಯನ್ನು ನವೀಕರಿಸಲಾಗುತ್ತಿದೆ…"</string>
<string name="fdn_contact_updated" msgid="5497828782609005017">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಯನ್ನು ನವೀಕರಿಸಲಾಗಿದೆ."</string>
<string name="delete_fdn_contact" msgid="6668958073074151717">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಯನ್ನು ಅಳಿಸು"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"ಸೆಲ್ಯುಲಾರ್ ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿಲ್ಲ. ಕರೆ ಮಾಡಲು ವೈರ್ಲೆಸ್ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಪಡಿಸಿ."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"ಕರೆಯನ್ನು ಮಾಡಲು, ಮಾನ್ಯವಾದ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"ಕರೆ ವಿಫಲವಾಗಿದೆ."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ಕರೆಯನ್ನು ಈ ಸಮಯದಲ್ಲಿ ಸೇರಿಸಲಾಗುವುದಿಲ್ಲ."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI ಅನುಕ್ರಮ ಪ್ರಾರಂಭವಾಗುತ್ತಿದೆ…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"ಸೇವೆಯು ಬೆಂಬಲಿತವಾಗಿಲ್ಲ"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"ಕರೆಗಳನ್ನು ಬದಲಾಯಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"ಕರೆ(ಗಳು) ಬಿಡುಗಡೆ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"ಕರೆಗಳನ್ನು ಹೋಲ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ಕರೆ ಮಾಡಲು ವೈರ್ಲೆಸ್ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಪಡಿಸಿ."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"ಕರೆ ಮಾಡಲು ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"ತುರ್ತು ಕರೆಗಳು"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"ರೇಡಿಯೋ ಆನ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"ಯಾವುದೇ ಸೇವೆ ಇಲ್ಲ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಲಾಗುತ್ತಿದೆ..."</string>
@@ -456,7 +469,7 @@
<string name="onscreenHoldText" msgid="2285258239691145872">"ಹೋಲ್ಡ್ ಮಾಡು"</string>
<string name="onscreenEndCallText" msgid="4403855834875398585">"ಮುಕ್ತಾಯ"</string>
<string name="onscreenShowDialpadText" msgid="8561805492659639893">"ಡಯಲ್ಪ್ಯಾಡ್"</string>
- <string name="onscreenMuteText" msgid="5011369181754261374">"ಮ್ಯೂಟ್ ಮಾಡು"</string>
+ <string name="onscreenMuteText" msgid="5011369181754261374">"ಮ್ಯೂಟ್ ಮಾಡಿ"</string>
<string name="onscreenAddCallText" msgid="5140385634712287403">"ಕರೆಯನ್ನು ಸೇರಿಸು"</string>
<string name="onscreenMergeCallsText" msgid="6640195098064538950">"ಕರೆಗಳನ್ನು ವಿಲೀನಗೊಳಿಸು"</string>
<string name="onscreenSwapCallsText" msgid="1602990689244030047">"ಸ್ವ್ಯಾಪ್ ಮಾಡು"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"ವೈಬ್ರೇಟ್"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"ವೈಬ್ರೇಟ್"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"ದೃಶ್ಯ ಧ್ವನಿಮೇಲ್"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"ಪಿನ್ ಹೊಂದಿಸಿ"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"ಪಿನ್ ಬದಲಾಯಿಸಿ"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ಧ್ವನಿ"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"ರಿಂಗ್ಟೋನ್ & ವೈಬ್ರೇಟ್"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"ಅಂತರ್-ರಚಿತ ಸಿಮ್ ಕಾರ್ಡ್ಗಳು"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"ತುರ್ತು ಕರೆ ಮಾಡುವಿಕೆ ಮಾತ್ರ"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM ಕಾರ್ಡ್, ಸ್ಲಾಟ್: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ಪ್ರವೇಶಿಸುವಿಕೆ"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"ಒಳಬರುವ ವೈ-ಫೈ ಕರೆ"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"ಅವರಿಂದ ವೈ-ಫೈ ಕರೆ"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"ವೈ-ಫೈ ಕರೆ"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"ತೆರೆಯಲು ಮತ್ತೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
<string name="message_decode_error" msgid="3456481534066924855">"ಸಂದೇಶವನ್ನು ಡೀಕೋಡ್ ಮಾಡುವಾಗ ದೋಷವುಂಟಾಗಿದೆ."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"ನಿಮ್ಮ ಸೇವೆಯನ್ನು ಸಿಮ್ ಕಾರ್ಡ್ ಸಕ್ರಿಯಗೊಳಿಸಿದೆ ಮತ್ತು ನಿಮ್ಮ ಫೋನ್ನ ರೋಮಿಂಗ್ ಸಾಮರ್ಥ್ಯವನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡಲಾಗಿದೆ."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"ಹಲವಾರು ಸಕ್ರಿಯ ಕರೆಗಳು. ಹೊಸ ಕರೆ ಮಾಡುವ ಮೊದಲು ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಕರೆಗಳನ್ನು ಅಂತ್ಯಗೊಳಿಸಿ ಅಥವಾ ವಿಲೀನಗೊಳಿಸಿ."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"ಧ್ವನಿಮೇಲ್ ಪಿನ್ ಬದಲಾಯಿಸಿ"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"ಮುಂದುವರಿಸು"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"ರದ್ದುಮಾಡಿ"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ಸರಿ"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"ನಿಮ್ಮ ಹಳೆಯ ಪಿನ್ ಅನ್ನು ದೃಢೀಕರಿಸಿ"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"ಮುಂದುವರಿಸಲು ನಿಮ್ಮ ಧ್ವನಿಮೇಲ್ ಪಿನ್ ಅನ್ನು ನಮೂದಿಸಿ."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"ಹೊಸ ಪಿನ್ ಹೊಂದಿಸಿ"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"ಪಿನ್ <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="8113764019347322170">"ನಿಮ್ಮ ಪಿನ್ ಅನ್ನು ದೃಢೀಕರಿಸಿ"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"ಪಿನ್ಗಳು ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"ಧ್ವನಿಮೇಲ್ ಪಿನ್ ಅಪ್ಡೇಟ್ ಮಾಡಲಾಗಿದೆ"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"ಪಿನ್ ಹೊಂದಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 7c49406..95c05e3 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"변경사항이 없습니다."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"음성사서함 서비스 선택"</string>
<string name="voicemail_default" msgid="2001233554889016880">"이동통신사"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"이전 PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"새 PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"잠시 기다려 주세요."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"새 PIN이 너무 짧습니다."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"새 PIN이 너무 깁니다."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"새 PIN의 안정성이 낮습니다. 안전한 비밀번호에는 연속되는 숫자 또는 반복되는 숫자를 사용하지 말아야 합니다."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"이전 PIN이 일치하지 않습니다."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"새 PIN에 잘못된 문자가 있습니다."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN을 변경할 수 없습니다."</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"지원되지 않는 메시지 유형입니다. 들으려면 <xliff:g id="NUMBER">%s</xliff:g>번으로 전화하세요."</string>
<string name="mobile_networks" msgid="2843854043339307375">"이동통신망 설정"</string>
<string name="label_available" msgid="1181658289009300430">"사용 가능한 네트워크"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"검색 중..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA로 기본 설정"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"향상된 4G LTE 모드"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"고급 통화"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"LTE 서비스를 사용하여 음성 및 기타 통신을 개선할 수 있습니다(권장)."</string>
<string name="data_enabled" msgid="5972538663568715366">"데이터 사용"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"데이터 사용 허용"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"모바일 네트워크를 사용할 수 없습니다. 전화를 걸려면 무선 네트워크에 연결하세요."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"전화를 걸려면 올바른 번호를 입력하세요."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"전화 연결 실패"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"현재 통화를 추가할 수 없습니다."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI 시퀀스 시작 중..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"지원되지 않는 서비스입니다."</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"통화를 전환할 수 없습니다."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"통화를 끊을 수 없습니다."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"통화를 보류할 수 없습니다."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"전화를 걸려면 무선 네트워크에 연결하세요."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"전화를 걸려면 Wi-Fi 통화를 사용 설정하세요."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"긴급 전화"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"무선을 켜는 중..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"서비스를 사용할 수 없습니다. 다시 시도 중..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"진동"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"진동"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"시각적 음성사서함"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN 설정"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN 변경"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"알림음"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"벨소리 및 진동"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"내장된 SIM 카드"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"긴급 전화 전용"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM 카드, 슬롯: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"접근성"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Wi-Fi 수신 전화"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi 수신 전화:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi 통화"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"다시 탭하여 열기"</string>
<string name="message_decode_error" msgid="3456481534066924855">"메시지를 디코딩하는 중에 오류가 발생했습니다."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM 카드로 서비스가 활성화되었으며 휴대전화 로밍 기능이 업데이트되었습니다."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"활성화된 통화가 너무 많습니다. 새로운 전화를 걸기 전에 기존의 통화를 끝내거나 합치세요."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"음성사서함 PIN 변경"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"계속"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"취소"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"확인"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"이전 PIN 확인"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"계속하려면 음성사서함 PIN을 입력하세요."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"새 PIN 설정"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN은 <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="8113764019347322170">"PIN 확인"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN이 일치하지 않음"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"음성사서함 PIN이 업데이트되었습니다."</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN을 설정할 수 없습니다."</string>
</resources>
diff --git a/res/values-ky-rKG/strings.xml b/res/values-ky-rKG/strings.xml
index 9730d53..0cee197 100644
--- a/res/values-ky-rKG/strings.xml
+++ b/res/values-ky-rKG/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Эч өзгөртүү киргизилген жок."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Үн почтасынын кызматын тандаңыз"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Операторуңуз"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Эски PIN код"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Жаңы PIN код"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Күтө туруңуз."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Жаңы PIN код өтө эле кыска."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Жаңы PIN код өтө эле узун."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Жаңы PIN код өтө эле жөнөкөй. Сырсөз күчтүү болушу үчүн анда сандар үзгүлтүксүз катардан турбашы же сандар кайталанбашы керек."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Эски PIN код дал келген жок."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Жаңы PIN коддо жараксыз белгилер бар."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN код өзгөртүлгөн жок"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Колдоого алынбаган билдирүү, угуу үчүн <xliff:g id="NUMBER">%s</xliff:g> чалыңыз."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Мобилдик тармактын жөндөөлөрү"</string>
<string name="label_available" msgid="1181658289009300430">"Жеткиликтүү тармактар"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Изделүүдө…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA артыкчылыктуу"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Жакшыртылган 4G LTE режими"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Өркүндөтүлгөн чалуу"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Үн жана башка байлнштрд жакшыртуу үчүн LTE кызматтарын пайдаланыңыз (сунушталат)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Дайындар иштетилсин"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Дайындарды пайдаланууга уруксат берүү"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Уюлдук тармак жеткиликтүү эмес. Чалуу үчүн зымсыз тармакка туташыңыз."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Чалуу үчүн, жарактуу номер киргизиңиз."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Чалынбай калды."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Бул жолу чалууну кошуу мүмкүн эмес."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI кезеги башталууда…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Кызмат колдоого алынбайт"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Чалуулар которуштурулбай жатат."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Чалуу(лар) бошотулбай жатат."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Чалууну кармап туруу мүмкүн эмес."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Чалуу үчүн зымсыз тармакка туташыңыз."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Wi-Fi аркылуу чалыңыз."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Шашылыш чалуу"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Радио күйгүзүлүүдө…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Кызмат жок. Кайра аракет кылууда…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Дирилдөө"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Дирилдөө"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Визуалдык үн почтасы"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN код коюу"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN кодду өзгөртүү"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Үнү"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Рингтон жана Титирөө"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Кыналган SIM карталар"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Шашылыш чалуу гана"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-карта, оюкча: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Жеткиликтүүлүк"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Кирүүчү Wi-Fi чалуу"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi аркылуу чалуу:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi чалуу"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Ачуу үчүн кайра таптап коюңуз"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Билдирүү дешифрленип жатканда ката кеткен."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM-карта кызматыңызды жандырып, телефонуңуздун роуминг мүмкүнчүлүктөрүн жаңыртты."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Учурда жигердүү чалуулар өтө көп. Чалуу үчүн учурдагы чалууларды бүтүрүңүз же бириктириңиз."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Үн почтасынын PIN кодун өзгөртүү"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Улантуу"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Жокко чыгаруу"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Жарайт"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Эски PIN кодуңузду ырастаңыз"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Улантуу үчүн үн почтаңыздын PIN кодун киргизиңиз."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Жаңы PIN коюңуз"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN <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="8113764019347322170">"PIN кодуңузду ырастаңыз"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN коддор дал келген жок"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Үн почтасынын PIN коду жаңыртылды"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN код коюлбайт"</string>
</resources>
diff --git a/res/values-lo-rLA/strings.xml b/res/values-lo-rLA/strings.xml
index 9b9a6db..2074754 100644
--- a/res/values-lo-rLA/strings.xml
+++ b/res/values-lo-rLA/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"ບໍ່ມີການປ່ຽນແປງເກີດຂຶ້ນ."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"ເລືອກບໍລິການຂໍ້ຄວາມສຽງ"</string>
<string name="voicemail_default" msgid="2001233554889016880">"ຜູ້ໃຫ້ບໍລິການຂອງທ່ານ"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"ລະຫັດ PIN ເກົ່າ"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"ລະຫັດ PIN ໃໝ່"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"ກະລຸນາລໍຖ້າ."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"ລະຫັດ PIN ໃໝ່ສັ້ນເກີນໄປ."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"ລະຫັດ PIN ໃໝ່ຍາວເກີນໄປ."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"ລະຫັດ PIN ໃໝ່ງ່າຍເກີນໄປ. ລະຫັດຜ່ານທີ່ຍາກບໍ່ຄວນຈະມີຕົວເລກຕໍ່ເນື່ອງ ຫຼື ຕົວເລກຊໍ້າໆກັນ."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"ລະຫັດ PIN ເກົ່າບໍ່ກົງກັນ."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"ລະຫັດ PIN ໃໝ່ມີຕົວອັກສອນທີ່ບໍ່ຖືກຕ້ອງ."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"ບໍ່ສາມາດປ່ຽນລະຫັດ PIN ໄດ້"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"ປະເພດຂໍ້ຄວາມທີ່ບໍ່ຮອງຮັບ, ໂທ <xliff:g id="NUMBER">%s</xliff:g> ເພື່ອຟັງ."</string>
<string name="mobile_networks" msgid="2843854043339307375">"ການຕັ້ງຄ່າເຄືອຂ່າຍມືຖື"</string>
<string name="label_available" msgid="1181658289009300430">"ເຄືອຂ່າຍທີ່ມີ"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"ກຳລັງຊອກຫາ..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"ຕ້ອງການ GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"ໂໝດ Enhanced 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"ການໂທຂັ້ນສູງ"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"ໃຊ້ການບໍລິການ LTE ເພື່ອປັບປຸງສຽງ ແລະການບໍລິການອື່ນໆ (ແນະນຳ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"ເປີດໃຊ້ເດຕາ"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"ອະນຸຍາດໃຫ້ໃຊ້ຂໍ້ມູນ"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"ເຄືອຂ່າຍເຊລລູລາບໍ່ພ້ອມໃຊ້ງານ. ໃຫ້ເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍໄຮ້ສາຍເພື່ອເຮັດການໂທ."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"ເພື່ອທີ່ຈະໂທ, ປ້ອນເບີໂທທີ່ໃຊ້ໄດ້ເຂົ້າໄປ."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"ໂທບໍ່ສຳເລັດ."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ບໍ່ສາມາດເພີ່ມການໂທໄດ້ໃນເວລານີ້."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"ກຳລັງເລີ່ມຕົ້ນລຳດັບ MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"ການບໍລິການບໍ່ຮອງຮັບ"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"ບໍ່ສາມາດສະຫຼັບສາຍໂທໄດ້."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"ບໍ່ສາມາດປ່ອຍສາຍໂທໄດ້."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"ບໍ່ສາມາດພັກສາຍໄດ້."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍໄຮ້ສາຍເພື່ອເຮັດການໂທ."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"ກະລຸນາເປີດໃຊ້ການໂທ Wi-Fi ເພື່ອໂທ."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"ໂທສຸກເສີນ"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"ກຳລັງເປີດໃຊ້ວິທະຍຸ..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"ບໍ່ມີການບໍລິການ. ກຳລັງລອງໃໝ່ອີກ…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"ສັ່ນເຕືອນ"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"ສັ່ນເຕືອນ"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"ຂໍ້ຄວາມສຽງປະກອບພາບ"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"ຕັ້ງລະຫັດ PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"ປ່ຽນລະຫັດ PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ສຽງ"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"ຣິງໂທນ & ການສັ່ນເຕືອນ"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"SIM ກາດທີ່ມາກັບເຄື່ອງ"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"ການໂທສຸກເສີນເທົ່ານັ້ນ"</string>
<string name="sim_description_default" msgid="4778679519938775515">"ແຜ່ນ SIM, ຊ່ອງ: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ການຊ່ວຍເຂົ້າເຖິງ"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"ສາຍໂທເຂົ້າ Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"ການໂທ Wi-Fi ຈາກ"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"ການໂທ Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"ແຕະອີກຄັ້ງເພື່ອເປີດ"</string>
<string name="message_decode_error" msgid="3456481534066924855">"ມີຂໍ້ຜິດພາດໃນລະຫວ່າງຖອດລະຫັດຂໍ້ຄວາມດັ່ງກ່າວ."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"ແຜ່ນ SIM ໄດ້ເປີດໃຊ້ງານການບໍລິການຂອງທ່ານ ແລະອັບເດດຄວາມສາມາດໃຊ້ງານຂ້າມເຂດຂອງໂທລະສັບຂອງທ່ານແລ້ວ."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"ມີສາຍຫຼາຍເກີນໄປ. ກະລຸນາວາງສາຍ ຫຼື ຮວມສາຍທີ່ກຳລັງໂທກ່ອນໂທສາຍໃໝ່."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"ປ່ຽນລະຫັດ PIN ຂໍ້ຄວາມສຽງ"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"ດຳເນີນການຕໍ່"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"ຍົກເລີກ"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ຕົກລົງ"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"ຢືນຢັນລະຫັດ PIN ເກົ່າຂອງທ່ານ"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"ໃສ່ລະຫັດ PIN ຂໍ້ຄວາມສຽງຂອງທ່ານເພື່ອດຳເນີນການຕໍ່."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"ຕັ້ງເປັນ PIN ໃຫມ່"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"ລະຫັດ PIN ຈະຕ້ອງມີ <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="8113764019347322170">"ຢືນຢັນລະຫັດ PIN ຂອງທ່ານ"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"ລະຫັດ PIN ບໍ່ກົງກັນ"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"ອັບເດດລະຫັດ PIN ຂໍ້ຄວາມສຽງແລ້ວ"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"ບໍ່ສາມາດຕັ້ງລະຫັດ PIN ໄດ້"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index c92a8cc..51bf40e 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Neatlikta jokių pakeitimų."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Pasirinkti balso pašto paslaugą"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Jūsų operatorius"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Senas PIN kodas"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Naujas PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Palaukite."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Naujas PIN kodas per trumpas."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Naujas PIN kodas per ilgas."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Naujas PIN kodas nepakankamai patikimas. Patikimame slaptažodyje neturėtų būti kelių vienodų simbolių iš eilės ar pasikartojančių skaitmenų."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Senas PIN kodas nesutampa."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Naujame PIN kode yra netinkamų simbolių."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Nepavyko pakeisti PIN kodo"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Nepalaikomas pranešimo tipas, paskambinkite numeriu <xliff:g id="NUMBER">%s</xliff:g> ir išklausykite."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Korinio tinklo nustatymai"</string>
<string name="label_available" msgid="1181658289009300430">"Galimi tinklai"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Ieškoma…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Pageidaujama GSM / WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Patobulintas 4G LTE režimas"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Išplėstinės skambinimo parinktys"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Naudoti LTE paslaugas „Voice“ ir kitiems ryšiams patobulinti (rekomenduojama)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Duomenys įgalinti"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Leisti naudoti duomenis"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobiliojo ryšio tinklas nepasiekiamas. Prisijunkite prie belaidžio ryšio tinklo, kad galėtumėte skambinti."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Kad galėtumėte paskambinti, įveskite tinkamą numerį."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Paskambinti nepavyko."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Šiuo metu skambučio atlikti negalima."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Paleidžiama MMI seka..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Paslauga nepalaikoma"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Nepavyko perjungti skambučių."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Nepavyko atjungti skamb."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Negalima sulaikyti skambučių."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Prisijunkite prie belaidžio ryšio tinklo, kad galėtumėte skambinti."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Įgalinkite „Wi-Fi“ skambinimą, kad galėtumėte skambinti."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Skambutis pagalbos numeriu"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Įjungiamas radijas…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Nėra ryšio. Bandoma dar kartą…"</string>
@@ -493,7 +506,7 @@
<string name="ota_skip_activation_dialog_title" msgid="2943366608272261306">"Praleisti aktyvinimą?"</string>
<string name="ota_skip_activation_dialog_message" msgid="2440770373498870550">"Jei praleisite aktyvinimą, negalėsite skambinti ar prisijungti prie mobilių duomenų tinklų (nors ir galite prisijungti prie „Wi-Fi“ tinklų). Iki tol, kol suaktyvinsite telefoną, aktyvinkite jį kaskart jį įjungdami."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="3458532775091563208">"Praleisti"</string>
- <string name="ota_activate" msgid="1368528132525626264">"Aktyvinti"</string>
+ <string name="ota_activate" msgid="1368528132525626264">"Suaktyvinti"</string>
<string name="ota_title_activate_success" msgid="6570240212263372046">"Telefonas suaktyvintas."</string>
<string name="ota_title_problem_with_activation" msgid="7095824491970084367">"Aktyvinimo problema"</string>
<string name="ota_listen" msgid="162923839877584937">"Vadovaukitės girdimomis instrukcijomis, kol išgirsite, kad aktyvinimas baigtas."</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibruoti"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibruoti"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vaizdinis balso paštas"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN kodo nustatymas"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Keisti PIN kodą"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Garsas"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Skambėjimo tonas ir vibracija"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Įtaisytosios SIM kortelės"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Tik skambučiai pagalbos numeriu"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM kortelė, lizdas: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Pritaikymas neįgaliesiems"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Gaunamasis „Wi-Fi“ skamb."</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"„Wi-Fi“ skambutis nuo"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"„Wi-Fi“ skambutis"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Palieskite dar kartą, kad atidarytumėte"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Iškoduojant pranešimą įvyko klaida."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM kortelė suaktyvino paslaugą ir atnaujino telefono tarptinklinio duomenų ryšio funkcijas."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Yra per daug aktyvių skambučių. Prieš skambindami kitu numeriu, užbaikite ar sujunkite esamus skambučius."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Balso pašto PIN kodo keitimas"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Tęsti"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Atšaukti"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Gerai"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Seno PIN kodo patvirtinimas"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Jei norite tęsti, įveskite balso pašto PIN kodą."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Naujo PIN kodo nustatymas"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN kodas turi būti <xliff:g id="MIN">%1$d</xliff:g>–<xliff:g id="MAX">%2$d</xliff:g> skaitmenų."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"PIN kodo patvirtinimas"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN kodai neatitinka"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Balso pašto PIN kodas atnaujintas"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Nepavyksta nustatyti PIN kodo"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index b7f2902..807dbfc 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Izmaiņas netika veiktas."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Izvēlieties balss pasta pakalpojumu"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Jūsu operators"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Iepriekšējais PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Jaunais PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Lūdzu, uzgaidiet!"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Jaunais PIN ir pārāk īss."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Jaunais PIN ir pārāk garš."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Jaunais PIN nav pietiekami drošs. Droša parole nedrīkst ietvert secīgus vai atkārtotus ciparus."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Vecais PIN neatbilst."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Jaunajā PIN ir ietvertas nederīgas rakstzīmes."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Neizdevās mainīt PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Neatbalstīts ziņojuma veids. Lai noklausītos, zvaniet uz numuru <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobilā tīkla iestatījumi"</string>
<string name="label_available" msgid="1181658289009300430">"Pieejamie tīkli"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Notiek meklēšana…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Ieteicams GSM/WCDMA režīms"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Uzlabota 4G LTE režīms"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Paplašināta zvanīšana"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Lietojiet LTE pakalpojumus, lai uzlabotu balss un cita veida saziņu (ieteicams)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Dati ir iespējoti."</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Atļaut datu izmantošanu"</string>
@@ -438,6 +449,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobilais tīkls nav pieejams. Lai veiktu zvanu, izveidojiet savienojumu ar bezvadu tīklu."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Lai veiktu zvanu, ievadiet derīgu numuru."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Zvans neizdevās."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Pašlaik nevar pievienot zvanu."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Notiek MMI secības startēšana…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Pakalpojums netiek atbalstīts"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Nevar pārslēgt zvanus."</string>
@@ -448,6 +460,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Nevar pārtraukt zvanu(-us)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Nevar aizturēt zvanus."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Lai veiktu zvanu, izveidojiet savienojumu ar bezvadu tīklu."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Lai veiktu zvanu, iespējojiet Wi-Fi zvanus."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Ārkārtas zvans"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Notiek radio ieslēgšana..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Nav pakalpojuma. Notiek atkārtots mēģinājums…"</string>
@@ -545,6 +558,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrozvans"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrozvans"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vizuālais balss pasts"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN koda iestatīšana"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Mainīt PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Signāls"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Zvana signāls un vibrācija"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Iebūvētās SIM kartes"</string>
@@ -556,10 +571,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Tikai ārkārtas izsaukumi"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM karte, slots: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Pieejamība"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Ienākošs Wi-Fi zvans"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi zvans no:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi zvans"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Pieskarieties vēlreiz, lai atvērtu."</string>
<string name="message_decode_error" msgid="3456481534066924855">"Atšifrējot ziņojumu, radās kļūda."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM kartē ir aktivizēts jūsu pakalpojums un atjauninātas tālruņa viesabonēšanas iespējas."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Ir pārāk daudz aktīvu zvanu. Pirms jauna zvana veikšanas pabeidziet vai apvienojiet esošos zvanus."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Balss pasta PIN koda mainīšana"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Turpināt"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Atcelt"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Labi"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Vecā PIN koda apstiprināšana"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Lai turpinātu, ievadiet sava balss pasta PIN kodu."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Jauna PIN koda iestatīšana"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN kodā ir jābūt <xliff:g id="MIN">%1$d</xliff:g>–<xliff:g id="MAX">%2$d</xliff:g> cipariem."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"PIN koda apstiprināšana"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN kodi neatbilst."</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Balss pasta PIN kods atjaunināts"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Nevar iestatīt PIN kodu."</string>
</resources>
diff --git a/res/values-mk-rMK/strings.xml b/res/values-mk-rMK/strings.xml
index 5af6a34..c6f8494 100644
--- a/res/values-mk-rMK/strings.xml
+++ b/res/values-mk-rMK/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Не беа направени промени."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Избери услуга на говорна пошта"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Вашиот оператор"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Стар PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Нов PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Почекајте."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Новиот PIN е премногу кус."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Новиот PIN е премногу долг."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Новиот PIN е премногу слаб. Силна лозинка не треба да содржи непрекината серија или цифри што се повторуваат."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Стариот PIN не се совпаѓа."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Новиот PIN содржи погрешни знаци."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN-кодот не може да се промени"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Неподдржан тип порака. Повикајте <xliff:g id="NUMBER">%s</xliff:g> за да слушате."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Поставки за мобилна мрежа"</string>
<string name="label_available" msgid="1181658289009300430">"Достапни мрежи"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Се пребарува..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA претпочитана"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Режим на подобрени 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Напредно повикување"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Користете ги услугите на LTE за да ја подобрите гласовната и другите видови комуникација (препорачано)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Податоците се овозможени"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Дозволи користење интернет"</string>
@@ -442,6 +453,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Не е достапна мобилна мрежа. Поврзете се на безжична мрежа за да повикате."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"За да повикате, внесете важечки број."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Повикот не успеа."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Повикот не може да се додаде во моментов."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Започнува MMI низа..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Услугата не е поддржана"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Не може да префрли повици."</string>
@@ -452,6 +464,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Не може да реализира повик(ци)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Не може да се задржат повици."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Поврзете се на безжична мрежа за да повикате."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Овозможете повикување преку Wi-Fi за воспоставување повик."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Повик за итни случаи"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Вклучување радио..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Нема услуга. Се обидува повторно…"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Вибрирање"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Вибрирање"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Визуелна говорна пошта"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Поставете PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Променете PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Звук"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Мелодија и вибрации"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Вградени СИМ-картички"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Само итни повикувања"</string>
<string name="sim_description_default" msgid="4778679519938775515">"СИМ-картичка, отвор: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Пристапност"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Дојдовен повик преку Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Повик преку Wi-Fi од"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Повик преку Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Допрете повторно за да се отвори"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Настана грешка при дешифрирање на пораката."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Вашата СИМ-картичка ја активираше услугата и ги ажурираше способностите за роаминг на вашиот телефон."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Има премногу активни повици. Завршете или спојте ги постоечките повици пред да започнете нов."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Променете PIN на говорната пошта"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Продолжи"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Откажи"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Во ред"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Потврдете го стариот PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Внесете го PIN-кодот на говорната пошта за да продолжите."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Поставете нов PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN мора да содржи најмалку <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="8113764019347322170">"Потврдете PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-кодовите не се совпаѓаат"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN-кодот на говорната пошта е ажуриран"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN не може да се постави"</string>
</resources>
diff --git a/res/values-ml-rIN/strings.xml b/res/values-ml-rIN/strings.xml
index 957b3b3..b5e915c 100644
--- a/res/values-ml-rIN/strings.xml
+++ b/res/values-ml-rIN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"മാറ്റങ്ങളൊന്നും വരുത്തിയിട്ടില്ല."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"വോയ്സ്മെയിൽ സേവനങ്ങൾ തിരഞ്ഞെടുക്കുക"</string>
<string name="voicemail_default" msgid="2001233554889016880">"നിങ്ങളുടെ കാരിയർ"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"പഴയ പിൻ"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"പുതിയ പിൻ"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"ദയവായി കാത്തിരിക്കുക."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"പുതിയ പിൻ വളരെ ചെറുതാണ്."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"പുതിയ പിൻ വളരെ ദൈർഘ്യമേറിയതാണ്."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"പുതിയ പിൻ വളരെ ദുർബലമാണ്. ഒരു ദൃഢമായ പാസ്വേഡിൽ തുടർച്ചയായി വരുന്നതോ ആവർത്തിച്ച് വരുന്നതോ ആയ അക്കങ്ങൾ ഉണ്ടാവരുത്."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"പഴയ പിന്നുമായി യോജിക്കുന്നില്ല."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"പുതിയ പിന്നിൽ അസാധുവായ പ്രതീകങ്ങൾ അടങ്ങിയിരിക്കുന്നു."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"പിൻ മാറ്റാനായില്ല"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"സന്ദേശ തരം പിന്തുണയ്ക്കുന്നില്ല, കേൾക്കാൻ <xliff:g id="NUMBER">%s</xliff:g> നമ്പറിൽ വിളിക്കുക."</string>
<string name="mobile_networks" msgid="2843854043339307375">"സെല്ലുലാർ നെറ്റ്വർക്ക് ക്രമീകരണങ്ങൾ"</string>
<string name="label_available" msgid="1181658289009300430">"ലഭ്യമായ നെറ്റ്വർക്കുകൾ"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"തിരയുന്നു…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA തിരഞ്ഞെടുത്തത്"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"മെച്ചപ്പെടുത്തിയ 4G LTE മോഡ്"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"വിപുലമായ കോളിംഗ്"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"വോയ്സ്, മറ്റ് ആശയവിനിമയങ്ങൾ (ശുപാർശിതം) എന്നിവ മികച്ചതാക്കുന്നതിന് LTE സേവനങ്ങൾ ഉപയോഗിക്കുക"</string>
<string name="data_enabled" msgid="5972538663568715366">"ഡാറ്റ പ്രവർത്തനക്ഷമമാക്കി"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"ഡാറ്റ ഉപയോഗം അനുവദിക്കുക"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"സെല്ലുലാർ നെറ്റ്വർക്ക് ലഭ്യമല്ല. കോൾ വിളിക്കാൻ വയർലെസ്സ് നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്യുക."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"ഒരു കോൾ ചെയ്യുന്നതിന്, സാധുതയുള്ള നമ്പർ നൽകുക."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"കോൾ ചെയ്യാനായില്ല."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"കോൾ ഇപ്പോൾ ചേർക്കാനാകില്ല."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI സീക്വൻസ് ആരംഭിക്കുന്നു…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"സേവനം പിന്തുണയ്ക്കുന്നില്ല"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"കോളുകൾ മാറാനാവില്ല."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"കോൾ (കോളുകൾ) വിളിക്കാനാവില്ല."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"കോളുകൾ ഹോൾഡുചെയ്യാൻ കഴിയില്ല."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ഒരു കോൾ വിളിക്കാൻ വയർലെസ്സ് നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്യുക."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"കോൾ ചെയ്യാൻ Wi-Fi കോളിംഗ് പ്രവർത്തനക്ഷമമാക്കുക."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"അടിയന്തര കോൾ"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"റേഡിയോ ഓൺ ചെയ്യുന്നു…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"സേവനമൊന്നുമില്ല. വീണ്ടും ശ്രമിക്കുന്നു…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"വൈബ്രേറ്റുചെയ്യുക"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"വൈബ്രേറ്റുചെയ്യുക"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"വിഷ്വൽ വോയ്സ്മെയിൽ"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"പിൻ സജ്ജമാക്കുക"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"പിൻ മാറ്റുക"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ശബ്ദം"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"റിംഗ്ടോണും വൈബ്രേറ്റുചെയ്യലും"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"അന്തർ നിർമ്മിത സിം കാർഡുകൾ"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"അടിയന്തിര കോൾചെയ്യൽ മാത്രം"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM കാർഡ്, സ്ലോട്ട്: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"പ്രവേശനക്ഷമത"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"ഇൻകമിംഗ് വൈഫൈ കോൾ"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"ഈ വ്യക്തിയിൽ നിന്നുള്ള Wi-Fi കോൾ"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"വൈഫൈ കോൾ"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"തുറക്കുന്നതിന് വീണ്ടും ടാപ്പുചെയ്യുക"</string>
<string name="message_decode_error" msgid="3456481534066924855">"സന്ദേശം ഡീകോഡുചെയ്യുമ്പോൾ ഒരു പിശകുണ്ടായി."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"ഒരു SIM കാർഡ് നിങ്ങളുടെ സേവനം സജീവമാക്കി, ഫോണിന്റെ റോമിംഗ് ശേഷികൾ അപ്ഡേറ്റ് ചെയ്തു."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"നിരവധി കോളുകൾ നിലവിൽ സജീവമായുണ്ട്. പുതിയ കോൾ വിളിക്കുന്നതിനുമുമ്പ് നിലവിലുള്ള കോളുകൾ അവസാനിപ്പിക്കുകയോ ലയിപ്പിക്കുകയോ ചെയ്യുക."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"വോയ്സ്മെയിൽ പിൻ മാറ്റുക"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"തുടരുക"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"റദ്ദാക്കുക"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ശരി"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"നിങ്ങളുടെ പഴയ പിൻ സ്ഥിരീകരിക്കുക"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"തുടരാൻ നിങ്ങളുടെ വോയ്സ്മെയിൽ പിൻ നൽകുക."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"പുതിയ PIN സജ്ജമാക്കുക"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"പിന്നിൽ <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="8113764019347322170">"നിങ്ങളുടെ പിൻ സ്ഥിരീകരിക്കുക"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-കൾ പൊരുത്തപ്പെടുന്നില്ല"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"വോയ്സ്മെയിൽ പിൻ അപ്ഡേറ്റുചെയ്തു"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"പിൻ സജ്ജമാക്കാൻ കഴിയുന്നില്ല"</string>
</resources>
diff --git a/res/values-mn-rMN/strings.xml b/res/values-mn-rMN/strings.xml
index a922251..2b7a3a8 100644
--- a/res/values-mn-rMN/strings.xml
+++ b/res/values-mn-rMN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Ямар ч өөрчлөлт хийгдсэнгүй."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Дуут шуудангийн үйлчилгээг сонгох"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Таны оператор компани"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Хуучин PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Шинэ PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Түр хүлээнэ үү."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Шинэ PIN хэт богино байна."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Шинэ PIN хэт урт байна."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Шинэ PIN хэт амархан байна. Сайн нууц үгэнд үргэлжилсэн дараалал буюу давтагдсан цифр ордоггүй."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Хуучин PIN таарахгүй байна."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Шинэ PIN-д буруу тэмдэгт агуулагдаж байна."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN-г өөрчлөх боломжгүй"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Дэмжигдээгүй зурвасын төрөл, сонсохын тулд <xliff:g id="NUMBER">%s</xliff:g> руу залгана уу."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Үүрэн сүлжээний тохиргоо"</string>
<string name="label_available" msgid="1181658289009300430">"Боломжтой сүлжээнүүд"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Хайж байна..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA эхэнд нь"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Сайжруулсан 4G LTE горим"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Сайжруулсан дуудлага"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"LTE-г ашиглан дуут болон бусад төрлийн харилцаа холбооны хэрэгслийг сайжруул (зөвлөхүйц)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Өгөгдөл идэвхжсэн"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Дата ашиглалтыг зөвшөөрөх"</string>
@@ -305,9 +316,9 @@
<string name="enable_disable_technology_news" msgid="3517184627114999149">"Технологийн мэдээ"</string>
<string name="technology_news_enable" msgid="7995209394210455181">"Технологийн мэдээг идэвхжүүлсэн"</string>
<string name="technology_news_disable" msgid="5483490380561851946">"Технологийн мэдээг идэвхгүйжүүлсэн"</string>
- <string name="enable_disable_multi_category" msgid="626771003122899280">"Олон категори"</string>
- <string name="multi_category_enable" msgid="1179299804641721768">"Олон-категори идэвхжсэн"</string>
- <string name="multi_category_disable" msgid="880104702904139505">"Олон-категори идэвхгүйжсэн"</string>
+ <string name="enable_disable_multi_category" msgid="626771003122899280">"Олон ангилал"</string>
+ <string name="multi_category_enable" msgid="1179299804641721768">"Олон-ангилал идэвхжсэн"</string>
+ <string name="multi_category_disable" msgid="880104702904139505">"Олон-ангилал идэвхгүйжсэн"</string>
<string name="network_lte" msgid="7702681952521375754">"LTE (зөвлөмж болгосон)"</string>
<string name="network_4G" msgid="2723512640529983138">"4G (зөвлөмж болгосон)"</string>
<string name="network_global" msgid="1323190488685355309">"Глобал"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Үүрэн сүлжээнд холбогдох боломжгүй байна. Дуудлага хийхийн тулд утасгүй интернетэд холбогдоно уу."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Дуудлага хийхийн тулд хүчин төгөлдөр дугаар оруулна уу."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Дуудлага амжилтгүй болсон."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Одоо дуудлага нэмэх боломжгүй."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI дарааллыг эхлүүлж байна…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Үйлчилгээг дэмждэггүй байна"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Дуудлагыг солих боломжгүй байна."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Дуудлага чөлөөлөх боломжгүй байна."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Дуудлагыг хадгалах боломжгүй байна."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Дуудлага хийхийн тулд утасгүй интернетэд холбогдоно уу."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Дуудлага хийхийн тулд Wi-Fi дуудлагыг идэвхжүүлнэ үү."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Ослын дуудлага"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Радиог асааж байна…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ажиллагаагүй байна. Дахин оролдоно уу..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Чичиргээ"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Чичиргээ"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Уншиж болохуйц дуут шуудан"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN тохируулах"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN өөрчлөх"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Дуу"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Хонхны ая & Чичиргээ"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Суурилагдсан SIM карт"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Зөвхөн яаралтай дуудлага"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM карт, оролт: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Хандалт"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Орж ирсэн Wi-Fi дуудлага"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi дуудлага"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi дуудлага"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Нээхийн тулд дахин дарна уу"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Зурвасын кодыг тайлах явцад алдаа гарсан."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM карт таны үйлчилгээг идэвхжүүлж, утасны роаминг багтаамжийг шинэчиллээ."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Хэт олон идэвхтэй дуудлага байна. Шинэ дуудлага хийхийн өмнө одоогийн дуудлагуудыг таслах буюу нэгтгэнэ үү."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Дуут шуудангийн PIN-г өөрчлөх"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Үргэлжлүүлэх"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Цуцлах"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Хуучин PIN-ээ баталгаажуулна уу"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Үргэлжлүүлэхийн тулд дуут шуудангийн PIN оруулна уу."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Шинэ PIN тохируулах"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN <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="8113764019347322170">"PIN кодоо баталгаажуулна уу"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN код таарахгүй байна"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Дуут шуудангийн PIN шинэчлэгдсэн"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN тохируулах боломжгүй"</string>
</resources>
diff --git a/res/values-mr-rIN/strings.xml b/res/values-mr-rIN/strings.xml
index 2e9b8c3..279d874 100644
--- a/res/values-mr-rIN/strings.xml
+++ b/res/values-mr-rIN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"कोणतेही बदल केले नाहीत."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"व्हॉइसमेल सेवा निवडा"</string>
<string name="voicemail_default" msgid="2001233554889016880">"आपला वाहक"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"जुना पिन"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"नवीन पिन"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"कृपया प्रतीक्षा करा."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"नवीन पिन खूप लहान आहे."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"नवीन पिन खूप दीर्घ आहे."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"नवीन पिन खूप कमकुवत आहे. सशक्त संकेतशब्दामध्ये अखंड क्रमवारी किंवा पुनरावृत्ती केलेले अंक नसावेत."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"जुना पिन जुळत नाही."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"नवीन पिन मध्ये अवैध वर्ण आहेत."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"पिन बदलण्यात अक्षम"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"असमर्थित संदेश प्रकार, ऐकण्यासाठी <xliff:g id="NUMBER">%s</xliff:g> वर कॉल करा."</string>
<string name="mobile_networks" msgid="2843854043339307375">"सेल्युलर नेटवर्क सेटिंग्ज"</string>
<string name="label_available" msgid="1181658289009300430">"उपलब्ध नेटवर्क"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"शोधत आहे..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA प्राधान्यकृत"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"वर्धित 4G LTE मोड"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"प्रगत कॉलिंग"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"व्हॉइस आणि इतर संप्रेषणे (शिफारस केलेली) सुधारित करण्यासाठी LTE सेवांचा वापर करा"</string>
<string name="data_enabled" msgid="5972538663568715366">"डेटा सक्षम केला"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"डेटा वापरास अनुमती द्या"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"सेल्युलर नेटवर्क उपलब्ध नाही. कॉल करण्यासाठी वायरलेस नेटवर्कशी कनेक्ट करा."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"कॉल करण्यासाठी, एक वैध नंबर प्रविष्ट करा."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"कॉल अयशस्वी झाला."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"यावेळी कॉल जोडला जाऊ शकत नाही."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI क्रम प्रारंभ करीत आहे..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"सेवा समर्थित नाही"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"कॉल स्विच करू शकत नाही."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"कॉल रिलीझ करू शकत नाही."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"कॉल सुरु ठेवू शकत नाही."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"कॉल करण्यासाठी वायरलेस नेटवर्कशी कनेक्ट करा."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"कॉल करण्यासाठी वाय-फाय कॉलिंग सक्षम करा."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"आणीबाणीचा कॉल"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"रेडिओ चालू करीत आहे..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"सेवा नाही. पुन्हा प्रयत्न करत आहे…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"कंपन होणे"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"कंपन होणे"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"दृश्यमान व्हॉइसमेल"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"पिन सेट करा"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"पिन बदला"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ध्वनी"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"रिंगटोन आणि कंपन"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"अंगभूत सिम कार्डे"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"केवळ आणीबाणी कॉल करणे"</string>
<string name="sim_description_default" msgid="4778679519938775515">"सिम कार्ड, स्लॉट: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"प्रवेशयोग्यता"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"येणारा वाय-फाय कॉल"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"कडून Wi-Fi कॉल"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"वाय-फाय कॉल"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"उघडण्यासाठी पुन्हा टॅप करा"</string>
<string name="message_decode_error" msgid="3456481534066924855">"संदेश डीकोड करताना एक त्रुटी आली."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"सिम कार्डने आपली सेवा सक्रिय केली आहे आणि आपल्या फोनच्या रोमिंग क्षमता अद्यतनित केल्या."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"बरेच सक्रिय कॉल आहेत. कृपया नवीन एक कॉल करण्यापूर्वी विद्यमान कॉल समाप्त करा किंवा विलीन करा."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"व्हॉइसमेल पिन बदला"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"सुरू ठेवा"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"रद्द करा"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ठीक आहे"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"आपल्या जुन्या पिनची पुष्टी करा"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"सुरु ठेवण्यासाठी आपला व्हॉइसमेल पिन प्रविष्ट करा."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"नवीन पिन सेट करा"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"पिन <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="8113764019347322170">"आपल्या पिनची पुष्टी करा"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"पिन जुळत नाहीत"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"व्हॉइसमेल पिन अद्यतनित केला"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"पिन सेट करण्यात अक्षम"</string>
</resources>
diff --git a/res/values-ms-rMY/strings.xml b/res/values-ms-rMY/strings.xml
index bc0b731..be6200d 100644
--- a/res/values-ms-rMY/strings.xml
+++ b/res/values-ms-rMY/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Tiada perubahan dibuat."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Pilih perkhidmatan mel suara"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Pembawa anda"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN lama"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"PIN baharu"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Sila tunggu."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"PIN baharu terlalu pendek."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"PIN baharu terlalu panjang."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"PIN baharu terlalu lemah. Kata laluan yang kukuh tidak seharusnya mempunyai digit yang berturutan atau berulangan."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"PIN lama tidak sepadan."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"PIN baharu mengandungi aksara yang tidak sah."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Tidak dapat menukar PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Jenis mesej tidak disokong, hubungi <xliff:g id="NUMBER">%s</xliff:g> untuk mendengar."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Tetapan rangkaian selular"</string>
<string name="label_available" msgid="1181658289009300430">"Rangkaian sedia ada"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Mencari..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA diutamakan"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Mod 4G LTE Dipertingkat"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Panggilan Ke Hadapan"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Gunakan perkhidmatan LTE untuk memperbaik suara dan komunikasi lain (disyorkan)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data didayakan"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Benarkan penggunaan data"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Rangkaian selular tidak tersedia. Sambungkan ke rangkaian wayarles untuk membuat panggilan."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Untuk membuat panggilan, masukkan nombor yang sah."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Panggilan gagal."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Panggilan tidak boleh ditambahkan pada masa ini."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Memulakan jujukan MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Perkhidmatan tidak disokong"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Tidak dapat menukar panggilan."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Tidak dapat melepaskan panggilan."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Tidak dapat menunda panggilan."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Sambungkan ke rangkaian wayarles untuk membuat panggilan."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Dayakan panggilan Wi-Fi untuk membuat panggilan."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Panggilan kecemasan"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Menghidupkan radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Tiada perkhidmatan. Mencuba lagi..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Getar"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Getar"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Mel Suara Visual"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Tetapkan PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Tukar PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Bunyi"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Nada dering & Bergetar"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Kad SIM terbina dalam"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Panggilan kecemasan sahaja"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Kad SIM, slot: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Kebolehaksesan"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Panggilan Wi-Fi masuk"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Panggilan Wi-Fi daripada"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Panggilan Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Ketik lagi untuk membuka"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Terdapat ralat semasa menyahkodkan mesej."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Kad SIM telah mengaktifkan perkhidmatan anda dan mengemas kini keupayaan perayauan telefon anda."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Terlalu banyak panggilan aktif. Sila tamatkan atau gabungkan panggilan yang sedia ada sebelum membuat panggilan baharu."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Tukar PIN Mel Suara"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Teruskan"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Batal"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Ok"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Sahkan PIN lama anda"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Masukkan PIN mel suara anda untuk meneruskan."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Tetapkan PIN baharu"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN mestilah <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> digit."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Sahkan PIN anda"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN tidak sepadan"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN mel suara dikemas kini"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Tidak dapat menetapkan PIN"</string>
</resources>
diff --git a/res/values-my-rMM/strings.xml b/res/values-my-rMM/strings.xml
index 9a6f2e3..5dee45b 100644
--- a/res/values-my-rMM/strings.xml
+++ b/res/values-my-rMM/strings.xml
@@ -28,7 +28,7 @@
<string name="mmiStarted" msgid="6347869857061147003">"MMIကုတ်နံပါတ်ကို စတင်ပြီးပါပြီ"</string>
<string name="ussdRunning" msgid="485588686340541690">"USSD ကုဒ် လုပ်ဆောင်နေပါသည်…"</string>
<string name="mmiCancelled" msgid="2771923949751842276">"MMIကုတ်နံပါတ်ကို ပယ်ဖျက်ပြီးပါပြီ"</string>
- <string name="cancel" msgid="5044513931633602634">"မလုပ်တော့ပါ"</string>
+ <string name="cancel" msgid="5044513931633602634">"မလုပ်တော့"</string>
<string name="enter_input" msgid="1810529547726803893">"USSD စာများဟာ စာလုံးရေ <xliff:g id="MIN_LEN">%d</xliff:g> မှ<xliff:g id="MAX_LEN">%d</xliff:g> အတွင်း ဖြစ်ရပါမည်။ နောက်တစ်ခေါက်ကြိုးစားပါ"</string>
<string name="manageConferenceLabel" msgid="4691922394301969053">"ကွန်းဖရင့် ခေါ်ဆိုမှုကို ထိန်းချုပ်သည်"</string>
<string name="ok" msgid="3811371167865772377">"အိုကေ"</string>
@@ -39,7 +39,7 @@
<string name="wait_prompt_str" msgid="7601815427707856238">"အောက်ပါ တီးလုံးများကို ပို့မလား?\n"</string>
<string name="pause_prompt_str" msgid="1789964702154314806">"အသံ ပို့နေစဉ်\n"</string>
<string name="send_button" msgid="4106860097497818751">"ပို့ခြင်း"</string>
- <string name="pause_prompt_yes" msgid="3564467212025151797">"ဟုတ်ကဲ့"</string>
+ <string name="pause_prompt_yes" msgid="3564467212025151797">"Yes"</string>
<string name="pause_prompt_no" msgid="6686238803236884877">"No"</string>
<string name="wild_prompt_str" msgid="5543521676355533577">"wildစာလုံးကို အစားထိုးရန်မှာ"</string>
<string name="no_vm_number" msgid="4164780423805688336">"အသံစာပို့စနစ် နံပါတ် ပျောက်နေပါသည်"</string>
@@ -48,7 +48,7 @@
<string name="puk_unlocked" msgid="2284912838477558454">"သင့် ဆင်းမ်ကဒ်အား ပိတ်ဆို့မှုကို ဖယ်ရှားပြီးပါပြီ။ သင့်ဖုန်းဟာ သော့ဖွင့်နေပါသည်…"</string>
<string name="label_ndp" msgid="780479633159517250">"ဆင်းမ်ကဒ် ကွန်ရက် သော့ဖွင့်သော ပင်နံပါတ်"</string>
<string name="sim_ndp_unlock_text" msgid="683628237760543009">"ဖွင့်ရန်"</string>
- <string name="sim_ndp_dismiss_text" msgid="1604823375752456947">"လွှတ်လိုက်သည်"</string>
+ <string name="sim_ndp_dismiss_text" msgid="1604823375752456947">"ပယ်ရန်"</string>
<string name="requesting_unlock" msgid="6412629401033249351">"ကွန်ယက်သော့ဖွင့်ခြင်း တောင်းဆိုနေပါသည်…"</string>
<string name="unlock_failed" msgid="6490531697031504225">"ကွန်ယက်ဖွင့်ရန် တောင်းဆိုမှု မအောင်မြင်ပါ"</string>
<string name="unlock_success" msgid="6770085622238180152">"ကွန်ယက်ဖွင့်ခြင်း မအောင်မြင်ပါ"</string>
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"အပြောင်းအလဲများ မပြုလုပ်ထားပါ"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"အသံစာပို့စနစ် ဝန်ဆောင်မှု ရွေးပါ"</string>
<string name="voicemail_default" msgid="2001233554889016880">"သင့် မိုဘိုင်းဆက်သွယ်ရေး ဝန်ဆောင်မှုဌာန"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"ပင်နံပါတ်အဟောင်း"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"ပင်နံပါတ်အသစ်"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"ခဏစောင့်ပါ။"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"ပင်နံပါတ်အသစ်မှာ တိုလွန်းနေသည်။"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"ပင်နံပါတ်အသစ်မှာ ရှည်လွန်းနေသည်။"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"ပင်နံပါတ်အသစ်မှာ အားနည်းလွန်းနေသည်။ အားကောင်းသောစကားဝှက်တစ်ခုတွင် အစဉ်လိုက်စာလုံးများ (သို့) ထပ်တလဲလဲသုံးထားသောကိန်းဂဏန်းများ မပါသင့်ပါ။"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"ပင်နံပါတ်အဟောင်းမှာ မကိုက်ညီပါ။"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"ပင်နံပါတ်အသစ်တွင် အသုံးပြု၍မရသောစာလုံးများ ပါဝင်နေပါသည်။"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"ပင်နံပါတ်ကို ပြောင်း၍မရပါ"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"ပံ့ပိုးမထားသော မက်ဆေ့ဂျ်အမျိုးအစားဖြစ်၍ နားထောင်ရန် <xliff:g id="NUMBER">%s</xliff:g> ကို ခေါ်ဆိုပါ။"</string>
<string name="mobile_networks" msgid="2843854043339307375">"ဆဲလ်လူလာ ကွန်ရက် ဆက်တင်များ"</string>
<string name="label_available" msgid="1181658289009300430">"ရရှိနိုင်သော ကွန်ယက်များ"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"ရှာဖွေနေသည်…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferred"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"မြှင့်တင်ထား 4G LTE မုဒ်"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"အဆင့်မြင့်ဖုန်းခေါ်ဆိုခြင်း"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"အသံခေါ်ဆိုမှုနှင့် အခြားဆက်သွယ်ရေးများ တိုးတက်စေရန် LTE ဝန်ဆောင်မှုများ ကိုအသုံးပြုမည် (အကြံပြုထား)"</string>
<string name="data_enabled" msgid="5972538663568715366">"ဒေတာ ဖွင့်ထားပြီး"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"ဒေတာ သုံးစွဲမှု ခွင့်ပြုရန်"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"ဆဲလူလာ ကွန်ရက် မရပါ။ ဖုန်းခေါ်ရန် ကြိုးမဲ့ကွန်ရက်သို့ ချိတ်ဆက်ပါ။"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"ဖုန်းခေါ်ရန်အတွက်၊ သင့်လျော်သည့်နံပါတ် ရိုက်ထည့်ပါ။"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"ခေါ်ဆို၍ မရပါ။"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ယခုအချိန်တွင် ခေါ်ဆိုမှု ထပ်မထည့်နိုင်ပါ။"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI အမှတ်စဉ်ကို စတင်နေပါသည်…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"ဤဝန်ဆောင်မှုအား မပံ့ပိုးပါ။"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"ဖုန်းခေါ်ခြင်းများကြား မကူးပြောင်းနိုင်ပါ။"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"ဖုန်းခေါ်ခြင်း(များ)အား လွှတ်မပေးနိုင်ပါ။"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"ခေါ်ဆိုမှုများကို ကိုင်ထား၍မရပါ။"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ဖုန်းခေါ်ရန် ကြိုးမဲကွန်ယက်တစ်ခုသို့ ချိတ်ဆက်ပါ။"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"ဖုန်းဆက်ရန် Wi-Fi ခေါ်ဆိုခြင်းကို ဖွင့်ပါ။"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"အရေးပေါ်ခေါ်ဆိုမှု"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"ရေဒီယို ဖွင့်နေစဉ်…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"ဝန်ဆောင်မှု မရှိပါ။ ထပ်မံကြိုးစားပါ…"</string>
@@ -503,7 +516,7 @@
<string name="ota_successful" msgid="1880780692887077407">"သင့်ဖုန်းမှာ အခု အက်တီဗိတ် ဖြစ်နေပါပြီ။ ဝန်ဆောင်မှုများ စတင်ရန် ၁၅ မိနစ်ထိ ကြာနိုင်ပါသည်"</string>
<string name="ota_unsuccessful" msgid="8072141612635635357">"သင့်ဖုန်း အက်တီဗိတ် မဖြစ်ပါ။ \nဖုန်းလိုင်းအားပိုကောင်းသော နေရာကိုရှာပါ (ပြတင်းပေါက်နား, သို့မဟုတ် အပြင်ဖက်)။ \n\nပြန်လည်ကြိုးစားပါ သို့မဟုတ် သုံးစွဲသူအား အကူအညီပေးဝန်ဆောင်မှု ကို ဆက်သွယ်ပြီး နည်းလမ်းရှာပါ။"</string>
<string name="ota_spc_failure" msgid="3909983542575030796">"အလွန်အကျွံ SPC မအောင်မြင်မှုများ"</string>
- <string name="ota_call_end" msgid="4537279738134612388">"နောက်ပြန်သွားရန်"</string>
+ <string name="ota_call_end" msgid="4537279738134612388">"နောက်သို့"</string>
<string name="ota_try_again" msgid="7685477206465902290">"ပြန်ကြိုးစားပါ"</string>
<string name="ota_next" msgid="3904945374358235910">"ရှေ့ဆက်သွားရန်"</string>
<string name="ecm_exit_dialog" msgid="4448531867763097533">"EcmExitDialog"</string>
@@ -515,8 +528,8 @@
<item quantity="one"> ဒေတာဆက်သွယ်မှု <xliff:g id="COUNT_0">%s</xliff:g> မိနစ်မရှိပါ</item>
</plurals>
<plurals name="alert_dialog_exit_ecm" formatted="false" msgid="7179911675595441201">
- <item quantity="other"> ဖုန်းသည် <xliff:g id="COUNT_1">%s</xliff:g> မိနစ်လောက် အရေးပေါ် ပြန်ခေါ်ခြင်းမုဒ်တွင် ရှိနေလိမ့်မည်။ ဤမုဒ်တွင် ဒေတာချိတ်ဆက်မှုအသုံးပြုသည့် app များကို အသုံးပြု၍ ရနိုင်မည်မဟုတ်ပါ။ ယခုထွက်လိုပါသလား? </item>
- <item quantity="one"> ဖုန်းသည် <xliff:g id="COUNT_0">%s</xliff:g> မိနစ်လောက် အရေးပေါ် ပြန်ခေါ်ခြင်းမုဒ်တွင် ရှိနေလိမ့်မည်။ ဤမုဒ်တွင် ဒေတာချိတ်ဆက်မှုအသုံးပြုသည့် app များကို အသုံးပြု၍ ရနိုင်မည်မဟုတ်ပါ။ ယခုထွက်လိုပါသလား?</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="8042973425225093895">
<item quantity="other"> ရွေးချယ်ထားသော အပြုအမူမှာ အရေပေါ်ခေါ်ဆိုမှုပြုလုပ်နေစဉ် မရှိနိုင်ပါ။ ဖုန်းသည်ဤ မုဒ်တွင် <xliff:g id="COUNT_1">%s</xliff:g> မိနစ်ရှိနေမည်ဖြစ်သည်။ ယခုထွက်လိုပါသလား?</item>
@@ -524,9 +537,9 @@
</plurals>
<string name="alert_dialog_in_ecm_call" msgid="1886723687211887104">"ရွေးချယ်ထားသော အပြုအမူမှာ အရေပေါ်ခေါ်ဆိုမှုပြုလုပ်နေစဉ် မရှိနိုင်ပါ"</string>
<string name="progress_dialog_exiting_ecm" msgid="4835734101617817074">"အရေးပေါ်ပြန်လည်ခေါ်ဆိုမှု အခြေအနေအား ထွက်ပါမည်"</string>
- <string name="alert_dialog_yes" msgid="6674268047820703974">"ဟုတ်သည်"</string>
+ <string name="alert_dialog_yes" msgid="6674268047820703974">"Yes"</string>
<string name="alert_dialog_no" msgid="1476091437797628703">"No"</string>
- <string name="alert_dialog_dismiss" msgid="2491494287075907171">"လွှတ်လိုက်သည်"</string>
+ <string name="alert_dialog_dismiss" msgid="2491494287075907171">"ပယ်ရန်"</string>
<string name="voicemail_provider" msgid="5135942703327136909">"ဝန်ဆောင်မှု"</string>
<string name="voicemail_settings" msgid="72448049107749316">"ပြင်ဆင်သည်"</string>
<string name="voicemail_number_not_set" msgid="6724904736891087856">"မသတ်မှတ်ထားပါ"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"တုန်ခါခြင်း"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"တုန်ခါခြင်း"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"အမြင် အသံမေးလ်"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"ပင်နံပါတ်သတ်မှတ်ရန်"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"ပင်နံပါတ်ပြောင်းပါ"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"အသံ"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"ဖုန်းမြည်သံ & တုန်ခါသံ"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"တပ်ဆင်ပြီး ဆင်းမ် ကဒ်များ"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"အရေးပေါ် ခေါ်ဆိုမှုသာလျှင်"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM ကဒ်၊ အပေါက်: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ရယူသုံးနိုင်မှု"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"ဝင်လာသော ဝိုင်ဖိုင်ခေါ်ဆိုမှု"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"အောက်ပါမှ Wi-Fi ခေါ်ခြင်း"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"ဝိုင်ဖိုင်ခေါ်ဆိုမှု"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"ဖွင့်ရန် ထပ်တို့ပါ"</string>
<string name="message_decode_error" msgid="3456481534066924855">"စာကို ကုဒ်ဖွင့်နေစဉ် အမှားရှိခဲ့သည်။"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM ကဒ်သည် သင့် ဖုန်းဝန်ဆောင်မှုအား အသက်သွင်းခဲ့ပြီး သင့်ဖုန်း၏ ကွန်ယက်ပြင်ပဒေတာသုံးနိုင်စွမ်းအား ပြင်ဆင်မွမ်းမံပြီးဖြစ်၏။"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"လက်ရှိခေါ်ဆိုမှုများ အလွန်များနေပါသည်။ ခေါ်ဆိုမှုအသစ်တစ်ခု မပြုလုပ်ခင် လက်ရှိဖုန်းခေါ်ဆိုမှုများကို အဆုံးသတ် (သို့) ပေါင်း လိုက်ပါ။"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"အသံမေးလ်ပင်နံပါတ် ပြောင်းရန်"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"ဆက်လုပ်ရန်"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"မလုပ်တော့"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"အိုကေ"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"သင့်ပင်နံပါတ်အဟောင်းကို အတည်ပြုရန်"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"ဆက်လုပ်ရန် သင့်အသံမေးလ်ပင်နံပါတ် ထည့်ပါ။"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"ပင်နံပါတ်အသစ် သတ်မှတ်ရန်"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"ပင်နံပါတ်တွင် ဂဏန်း <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="8113764019347322170">"ပင်နံပါတ်အတည်ပြုရန်"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"ပင်နံပါတ်များ မကိုက်ညီပါ"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"အသံမေးလ်ပင်နံပါတ် အပ်ဒိတ်လုပ်ပြီးပါပြီ"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"ပင်နံပါတ်သတ်မှတ်၍ မရပါ"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 2211850..6617a71 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Ingen endringer ble utført."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Velg leverandør for talepostkasse"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operatøren din"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Gammel PIN-kode"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Ny PIN-kode"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Vent litt."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Den nye PIN-koden er for kort."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Den nye PIN-koden er for lang."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Den nye PIN-koden er for svak. Sterke passord inneholder ikke sammenhengende sekvenser eller gjentatte sifre."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Den gamle PIN-koden er feil."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Den nye PIN-koden inneholder ugyldige tegn."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Kan ikke bytte PIN-kode"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Meldingstypen støttes ikke. Ring <xliff:g id="NUMBER">%s</xliff:g> for å høre."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobilnettinnstillinger"</string>
<string name="label_available" msgid="1181658289009300430">"Tilgjengelige nettverk"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Søker …"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA foretrukket"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Forbedret 4G LTE-modus"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Avansert ringemodus"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Bruk LTE-tjenester for å forbedre stemme- og andre typer kommunikasjon (anbefalt)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data aktivert"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Tillat databruk"</string>
@@ -235,7 +246,7 @@
<string name="enable_disable_emergency_broadcast" msgid="2157014609041245335">"Nødkringkasting"</string>
<string name="emergency_broadcast_enable" msgid="2645980025414010211">"Nødkringkasting aktivert"</string>
<string name="emergency_broadcast_disable" msgid="3665199821267569426">"Nødkringkasting deaktivert"</string>
- <string name="enable_disable_administrative" msgid="6501582322182059412">"Administrativia"</string>
+ <string name="enable_disable_administrative" msgid="6501582322182059412">"Administrativ"</string>
<string name="administrative_enable" msgid="1750086122962032235">"Administrativia aktivert"</string>
<string name="administrative_disable" msgid="8433273857248698539">"Administartivia aktivert"</string>
<string name="enable_disable_maintenance" msgid="1819693083025106678">"Vedlikehold"</string>
@@ -442,6 +453,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobilnettverk er ikke tilgjengelig. Koble til et trådløst nettverk for å ringe."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Skriv inn et gyldig nummer for å plassere en samtale."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Anropet mislyktes."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Anropet kan ikke legges til akkurat nå."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Begynner MMI-sekvens…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Tjenesten støttes ikke"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Kan ikke bytte samtaler."</string>
@@ -452,6 +464,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Kan ikke frigjøre samtale(r)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Kan ikke sette samtaler på vent."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Koble til et trådløst nettverk for å ringe."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Slå på telefonanrop via Wi-Fi for å ringe."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Nødanrop"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Slår på radio…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ingen tjeneste. Prøver på nytt …"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrering"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrering"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visuell talepostkasse"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Angi PIN-kode"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Bytt PIN-kode"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Lyd"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ringetone og vibrering"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Innebygde SIM-kort"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Kun nødanrop"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-kort, spor: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Tilgjengelighet"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Wi-Fi-oppringing inn"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi-anrop fra"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Oppringing via Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Trykk på nytt for å åpne"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Det oppsto en feil under dekoding av meldingen."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Et SIM-kort har aktivert tjenesten din og oppdatert roamingfunksjonene for telefonen din."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Du har for mange aktive samtaler. Avslutt eller slå sammen eksisterende samtaler før du starter en ny samtale."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Endre PIN-kode for talemeldinger"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Fortsett"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Avbryt"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Bekreft den gamle PIN-koden din"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Skriv inn PIN-koden for talemeldinger for å fortsette."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Angi en ny PIN-kode"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN-koden må bestå av <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> sifre."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Bekreft PIN-koden"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-kodene stemmer ikke overens"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN-koden for talemeldinger ble oppdatert"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Kan ikke angi PIN-kode"</string>
</resources>
diff --git a/res/values-ne-rNP/strings.xml b/res/values-ne-rNP/strings.xml
index 23ab2a9..876f998 100644
--- a/res/values-ne-rNP/strings.xml
+++ b/res/values-ne-rNP/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"केही पनि फेरबदल गरिएन।"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"भ्वाइसमेल सेवा छान्नुहोस्"</string>
<string name="voicemail_default" msgid="2001233554889016880">"तपाईंको वाहक"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"पुरानो PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"नयाँ PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"कृपया प्रतीक्षा गर्नुहोस्।"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"नयाँ PIN अत्यन्त छोटो छ।"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"नयाँ PIN अत्यन्त लामो छ।"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"नयाँ PIN अत्यन्त कमजोर छ। बलियो पासवर्डमा लगातारको अनुक्रम वा दोहोरिएका अङ्कहरू हुनु हुँदैन।"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"पुरानो PIN मेल खाँदैन।"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"नयाँ PIN मा अमान्य वर्णहरू छन्।"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN परिवर्तन गर्न सकिएन"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"सन्देशको असमर्थित प्रकार, सुन्नका लागि <xliff:g id="NUMBER">%s</xliff:g> मा कल गर्नुहोस्।"</string>
<string name="mobile_networks" msgid="2843854043339307375">"सेलुलर सञ्जाल सेटिङहरू"</string>
<string name="label_available" msgid="1181658289009300430">"उपलब्ध नेटवर्कहरू"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"खोजी गर्दै..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA रुचाइएका"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Enhanced 4G LTE Mode"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"उन्नत कल गरिँदै"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"आवाज र अन्य सञ्चार सुधार गर्न LTE सेवाहरूको प्रयोग गर्नुहोस् (सिफारिस गरिएको)"</string>
<string name="data_enabled" msgid="5972538663568715366">"डेटा सक्षम भयो"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"डेटा उपयोगलाई अनुमति दिनुहोस्"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"सेलुलर सञ्जाल उपलब्ध छैन। एक कल गर्न ताररहितको सञ्जालमा जडान गर्नुहोस्।"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"एक कल गर्नको लागि, एक वैध नम्बर प्रविष्ट गर्नुहोस्।"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"कल विफल भयो।"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"यतिबेला कल थप गर्न सकिँदैन।"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI अनुक्रम सुरु गर्दै..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"सेवा समर्थित छैन"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"कल स्विच गर्न सक्दैन।"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"कल (हरू) जारी गर्न सकिँदैन ।"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"कल सञ्चालन गर्न सकिँदैन।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"एक कल गर्न एक ताररहितको सञ्जालमा जडान गर्नुहोस्।"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"कल गर्नका लागि Wi-Fi कलिङ सक्षम गर्नुहोस्।"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"आपतकालीन कल"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"रेडियो खोल्दै..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"कुनै सेवा छैन। फेरि प्रयास गर्दै ..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"भाइब्रेट"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"भाइब्रेट"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"भिजुअल भ्वाइस मेल"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN सेट गर्नुहोस्"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN परिवर्तन गर्नुहोस्"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"आवाज:"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"रिङ्गटोन र भाइब्रेट"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"निर्मित SIM कार्डहरू"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"आपातकालीन कल मात्र"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM कार्ड, स्लट: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"पहुँचता"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"आगमन Wi-Fi कल"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"बाट Wi-Fi मार्फत आएको कल"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi कल"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"खोल्न पुनः ट्याप गर्नुहोस्"</string>
<string name="message_decode_error" msgid="3456481534066924855">"सन्देश डिकोड गर्दा एउटा समस्या भयो।"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM कार्डले तपाईँको सेवा सक्रिय गर्नुका तथा फोनको रोमिङ क्षमताहरू पनि अद्यावधिक गरिदिएको छ।"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"धेरै सक्रिय कलहरू छन्। कृपया कुनै नयाँ राख्नु अघि विद्यमान कलहरूलाई अन्त्य वा मर्ज गर्नुहोस्।"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"भ्वाइस मेलको PIN परिवर्तन गर्नुहोस्"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"जारी राख्नुहोस्"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"रद्द गर्नुहोस्"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ठीक छ"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"आफ्नो पुरानो PIN को पुष्टि गर्नुहोस्"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"जारी राख्नका लागि आफ्नो भ्वाइस मेलको PIN प्रविष्ट गर्नुहोस्।"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"एउटा नयाँ PIN सेट गर्नुहोस्"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN <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="8113764019347322170">"तपाईँको PIN को पुष्टि गर्नुहोस्"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN हरू मेल खाँदैनन्"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"भ्वाइस मेल PIN अद्यावधिक गरियो"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN सेट गर्न असमर्थ भयो"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 6277a82..1f1c11b 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/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="1107073389495104784">"Mobiele gegevens"</string>
+ <string name="phoneAppLabel" product="tablet" msgid="1107073389495104784">"Mobiele data"</string>
<string name="phoneAppLabel" product="default" msgid="6790717591729922998">"Telefoonservices"</string>
<string name="emergencyDialerIconLabel" msgid="7812140032168171053">"Kiezer noodoproep"</string>
<string name="phoneIconLabel" msgid="2331230813161304895">"Telefoon"</string>
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Er zijn geen wijzigingen aangebracht."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Service voor voicemail selecteren"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Je provider"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Oude pincode"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nieuwe pincode"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Een ogenblik geduld."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"De nieuwe pincode is te kort."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"De nieuwe pincode is te lang."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"De nieuwe pincode is niet sterk genoeg. Een sterk wachtwoord mag geen opeenvolgende cijferreeks of herhaalde cijfers bevatten."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"De oude pincode komt niet overeen."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"De nieuwe pincode bevat ongeldige tekens."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Kan pincode niet wijzigen"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Niet-ondersteund berichttype, bel <xliff:g id="NUMBER">%s</xliff:g> om te luisteren."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Instellingen voor mobiele netwerken"</string>
<string name="label_available" msgid="1181658289009300430">"Beschikbare netwerken"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Zoeken..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Voorkeur voor GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Geoptimaliseerde 4G LTE-modus"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Geavanceerd bellen"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"LTE-services gebruiken voor betere spraak- en andere communicatie (aanbevolen)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Gegevenstoegang aan"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Gegevensgebruik toestaan"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobiel netwerk is niet beschikbaar. Maak verbinding met een draadloos netwerk om te bellen."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Als je wilt bellen, moet je een geldig nummer invoeren."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Oproep mislukt."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Oproep kan momenteel niet worden toegevoegd."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI-reeks starten..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Service wordt niet ondersteund"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Kan niet overschakelen tussen oproepen."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Kan oproep(en) niet vrijgeven."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Kan gesprekken niet in de wacht zetten."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Maak verbinding met een draadloos netwerk om te bellen."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Schakel bellen via wifi in om te bellen."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Noodoproep"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Radio aanzetten..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Geen bereik. Opnieuw proberen…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Trillen"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Trillen"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visuele voicemail"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Pincode instellen"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Pincode wijzigen"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Geluid"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Beltoon en trillen"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Ingebouwde simkaarten"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Alleen noodoproepen"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Simkaart, sleuf: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Toegankelijkheid"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Inkomende wifi-oproep"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wifi-oproep van"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wifi-oproep"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Tik nogmaals om te openen"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Er is een fout opgetreden tijdens het decoderen van het bericht."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Een simkaart heeft je service geactiveerd en heeft de roaming-mogelijkheden van je telefoon geüpdatet."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Er zijn te veel actieve oproepen. Beëindig bestaande oproepen of voeg ze samen voordat je een nieuwe oproep start."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Voicemailpincode wijzigen"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Doorgaan"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Annuleren"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Bevestig je oude pincode"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Geef je voicemailpincode op om door te gaan."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Een nieuwe pincode instellen"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Pincode moet <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> cijfers zijn."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"De pincode bevestigen"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Pincodes komen niet overeen"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Voicemailpincode geüpdatet"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Kan pincode niet instellen"</string>
</resources>
diff --git a/res/values-pa-rIN/strings.xml b/res/values-pa-rIN/strings.xml
index c85d93e..f0ab174 100644
--- a/res/values-pa-rIN/strings.xml
+++ b/res/values-pa-rIN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"ਕੋਈ ਬਦਲਾਵ ਨਹੀਂ ਕੀਤੇ ਗਏ ਹਨ।"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"ਵੌਇਸਮੇਲ ਸੇਵਾ ਚੁਣੋ"</string>
<string name="voicemail_default" msgid="2001233554889016880">"ਤੁਹਾਡਾ ਕੈਰੀਅਰ"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"ਪੁਰਾਣਾ PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"ਨਵਾਂ PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"ਕਿਰਪਾ ਕਰਕੇ ਉਡੀਕ ਕਰੋ।"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"ਨਵਾਂ PIN ਬਹੁਤ ਹੀ ਛੋਟਾ ਹੈ।"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"ਨਵਾਂ PIN ਬਹੁਤ ਹੀ ਵੱਡਾ ਹੈ।"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"ਨਵਾਂ PIN ਬਹੁਤ ਹੀ ਕਮਜ਼ੋਰ ਹੈ। ਮਜ਼ਬੂਤ ਪਾਸਵਰਡ ਵਿੱਚ ਨਿਰੰਤਰ ਲੜੀ ਜਾਂ ਦੁਹਰਾਏ ਗਏ ਅੰਕ ਹੋਣੇ ਚਾਹੀਦੇ ਹਨ।"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"ਪੁਰਾਣਾ PIN ਮੇਲ ਨਹੀਂ ਖਾਂਦਾ।"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"ਨਵੇਂ PIN ਵਿੱਚ ਅਵੈਧ ਅੱਖਰ-ਚਿੰਨ੍ਹ ਹਨ।"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN ਨੂੰ ਬਦਲਣ ਵਿੱਚ ਅਸਮਰੱਥ"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"ਅਸਮਰਥਿਤ ਸੁਨੇਹਾ ਕਿਸਮ, ਸੁਣਨ ਲਈ <xliff:g id="NUMBER">%s</xliff:g> \'ਤੇ ਕਾਲ ਕਰੋ।"</string>
<string name="mobile_networks" msgid="2843854043339307375">"ਸੈਲਿਊਲਰ ਨੈਟਵਰਕ ਸੈਟਿੰਗਾਂ"</string>
<string name="label_available" msgid="1181658289009300430">"ਉਪਲਬਧ ਨੈਟਵਰਕ"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"ਖੋਜ ਰਿਹਾ ਹੈ..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA ਤਰਜੀਹੀ"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"ਵਿਸਤ੍ਰਿਤ 4G LTE ਮੋਡ"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"ਉੱਨਤ ਕਾਲਿੰਗ"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"ਵੌਇਸ ਅਤੇ ਹੋਰ ਸੰਚਾਰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ LTE ਸੇਵਾਵਾਂ ਵਰਤੋ (ਸਿਫਾਰਿਸ਼ ਕੀਤਾ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"ਡਾਟਾ ਸਮਰਥਿਤ"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"ਡਾਟਾ ਵਰਤੋਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"ਸੈਲਿਊਲਰ ਨੈਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਇੱਕ ਕਾਲ ਕਰਨ ਲਈ ਇੱਕ ਵਾਇਰਲੈਸ ਨੈਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰੋ।"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"ਇੱਕ ਕਾਲ ਕਰਨ ਲਈ, ਇੱਕ ਪ੍ਰਮਾਣਿਕ ਨੰਬਰ ਦਰਜ ਕਰੋ।"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"ਕਾਲ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ।"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ਇਸ ਵੇਲੇ ਕਾਲ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ।"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI ਕੜੀ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"ਸੇਵਾ ਸਮਰਥਿਤ ਨਹੀਂ"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"ਕਾਲਾਂ ਸਵਿਚ ਨਹੀਂ ਕਰ ਸਕਦਾ।"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"ਕਾਲ(ਕਾਲਾਂ) ਰਿਲੀਜ ਨਹੀਂ ਕਰ ਸਕਦਾ।"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"ਕਾਲਾਂ ਹੋਲਡ ਨਹੀਂ ਕੀਤੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ਇੱਕ ਕਾਲ ਕਰਨ ਲਈ ਇੱਕ ਵਾਇਰਲੈਸ ਨੈਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰੋ।"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"ਇੱਕ ਕਾਲ ਕਰਨ ਲਈ Wi-Fi ਕਾਲਿੰਗ ਯੋਗ ਬਣਾਓ।"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"ਐਮਰਜੈਂਸੀ ਕਾਲ"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"ਰੇਡੀਓ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"ਕੋਈ ਸੇਵਾ ਨਹੀਂ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰ ਰਿਹਾ ਹੈ…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"ਥਰਥਰਾਹਟ ਕਰੋ"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"ਥਰਥਰਾਹਟ ਕਰੋ"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"ਵਿਜੁਅਲ ਵੌਇਸਮੇਲ"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN ਸੈੱਟ ਕਰੋ"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN ਬਦਲੋ"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ਅਵਾਜ਼"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"ਰਿੰਗਟੋਨ ਅਤੇ ਥਰਥਰਾਹਟ"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"ਬਿਲਟ-ਇਨ SIM ਕਾਰਡ"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"ਕੇਵਲ ਐਮਰਜੈਂਸੀ ਕਾਲਿੰਗ"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM ਕਾਰਡ, ਸਲੌਟ: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ਪਹੁੰਚਯੋਗਤਾ"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"ਇਨਕਮਿੰਗ Wi-Fi ਕਾਲ"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"ਇਸ ਤੋਂ Wi-Fi ਕਾਲ"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi ਕਾਲ"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"ਖੋਲ੍ਹਣ ਲਈ ਦੁਬਾਰਾ ਟੈਪ ਕਰੋ"</string>
<string name="message_decode_error" msgid="3456481534066924855">"ਸੁਨੇਹਾ ਡੀਕੋਡ ਕਰਦੇ ਸਮੇਂ ਇੱਕ ਅਸ਼ੁੱਧੀ ਹੋਈ ਸੀ।"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"ਇੱਕ SIM ਕਾਰਡ ਨੇ ਤੁਹਾਡੀ ਸੇਵਾ ਸਕਿਰਿਆ ਕੀਤੀ ਹੈ ਅਤੇ ਤੁਹਾਡੇ ਫੋਨ ਦੀਆਂ ਰੋਮਿੰਗ ਸਮਰੱਥਤਾਵਾਂ ਅਪਡੇਟ ਕੀਤੀਆਂ ਹਨ।"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"ਇੱਥੇ ਬਹੁਤ ਸਾਰੀਆਂ ਕਿਰਿਆਸ਼ੀਲ ਕਾਲਾਂ ਹਨ। ਕਿਰਪਾ ਕਰਕੇ ਇੱਕ ਨਵੀਂ ਕਾਲ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਮੌਜੂਦਾ ਕਾਲਾਂ ਨੂੰ ਸਮਾਪਤ ਜਾਂ ਮਿਲਾਓ।"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"ਵੌਇਸਮੇਲ PIN ਬਦਲੋ"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"ਜਾਰੀ ਰੱਖੋ"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"ਰੱਦ ਕਰੋ"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ਠੀਕ"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"ਆਪਣੇ ਪੁਰਾਣੇ PIN ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਵੌਇਸਮੇਲ PIN ਦਾਖਲ ਕਰੋ।"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"ਇੱਕ ਨਵਾਂ PIN ਸੈੱਟ ਕਰੋ"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN ਲਾਜ਼ਮੀ ਤੌਰ \'ਤੇ <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="8113764019347322170">"ਆਪਣੇ PIN ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN ਮੇਲ ਨਹੀਂ ਖਾਂਦੇ"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"ਵੌਇਸਮੇਲ PIN ਅੱਪਡੇਟ ਕੀਤਾ ਗਿਆ"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN ਸਥਾਪਤ ਕਰਨ ਦੇ ਅਯੋਗ"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 59dd841..997022d 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Nie dokonano żadnych zmian."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Wybierz usługę poczty głosowej"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Mój operator"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Stary PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nowy PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Poczekaj."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Nowy PIN jest za krótki."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Nowy PIN jest za długi."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Nowy PIN jest zbyt słaby. Silne hasło nie może zawierać ciągu kolejnych cyfr lub powtarzających się cyfr."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Stary PIN jest nieprawidłowy."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Nowy PIN zawiera nieprawidłowe znaki."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Nie udało się zmienić kodu PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Nieobsługiwany typ wiadomości – aby ją odsłuchać, zadzwoń pod numer <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Ustawienia sieci komórkowej"</string>
<string name="label_available" msgid="1181658289009300430">"Dostępne sieci"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Wyszukiwanie..."</string>
@@ -198,8 +208,9 @@
<item msgid="3817924849415716259">"Preferowany GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Tryb rozszerzonego 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Zaawansowane połączenia"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Użyj usług LTE, by poprawić łączność głosową i inną (zalecane)"</string>
- <string name="data_enabled" msgid="5972538663568715366">"Włącz przesył danych"</string>
+ <string name="data_enabled" msgid="5972538663568715366">"Włączone przesyłanie danych"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Zezwalaj na transmisję danych"</string>
<string name="dialog_alert_title" msgid="6751344986194435476">"Uwaga"</string>
<string name="roaming" msgid="8871412572928323707">"Roaming danych"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Sieć komórkowa jest niedostępna. Połącz się z siecią bezprzewodową, by zadzwonić."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Aby zadzwonić, wybierz prawidłowy numer."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Nie udało się połączyć."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Nie można w tej chwili dodać połączenia."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Rozpoczynanie sekwencji MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Usługa nie jest obsługiwana"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Nie można przełączyć połączeń."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Nie można zwolnić połączeń."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Nie można zawieszać połączeń."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Połącz się z siecią bezprzewodową, by zadzwonić."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Włącz Połączenia przez Wi-Fi, aby nawiązać połączenie."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Połączenie alarmowe"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Trwa włączanie sieci bezprzewodowych..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Brak sieci. Próbuję ponownie…"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Wibracje"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Wibracje"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Wizualna poczta głosowa"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Ustaw kod PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Zmień PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Dźwięk"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Dzwonek i wibracje"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Wbudowane karty SIM"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Tylko połączenia alarmowe"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Karta SIM, gniazdo: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Ułatwienia dostępu"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Przychodzące połączenie przez Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Połączenie przez Wi-Fi od:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Połączenie przez Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Dotknij ponownie, by otworzyć"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Podczas dekodowania wiadomości wystąpił błąd."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Karta SIM aktywowała usługę i zaktualizowała funkcje roamingowe telefonu."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Masz za dużo aktywnych połączeń. Scal lub zakończ istniejące połączenia, aby nawiązać nowe."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Zmień kod PIN poczty głosowej"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Dalej"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Anuluj"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Potwierdź stary kod PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Wpisz kod PIN poczty głosowej, aby przejść dalej."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Ustaw nowy kod PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Kod PIN musi zawierać od <xliff:g id="MIN">%1$d</xliff:g> do <xliff:g id="MAX">%2$d</xliff:g> cyfr."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Potwierdź kod PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Kody PIN nie są identyczne."</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Kod PIN poczty głosowej został zaktualizowany."</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Nie udało się ustawić kodu PIN"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 2ca7655..e50f2dd 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Não foram efectuadas alterações."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Escolha o serviço de correio de voz"</string>
<string name="voicemail_default" msgid="2001233554889016880">"O seu operador"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN antigo"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Novo PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Aguarde."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"O novo PIN é demasiado curto."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"O novo PIN é demasiado longo."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"O novo PIN é demasiado fraco. Uma palavra-passe forte não deve ter uma sequência de dígitos contínua ou repetida."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"O PIN antigo é diferente."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"O novo PIN contém carateres inválidos."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Não é possível alterar o PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Tipo de mensagem não suportada, ligue para o número <xliff:g id="NUMBER">%s</xliff:g> para ouvir."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Definições de rede móvel"</string>
<string name="label_available" msgid="1181658289009300430">"Redes disponíveis"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"A pesquisar..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferido"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Modo 4G LTE avançado"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Chamadas avançadas"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Utilizar os serviços LTE para melhorar a voz e outras comunicações (recomendado)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Dados ativados"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Permitir a utilização de dados"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"A rede móvel não está disponível. Ligue-se a uma rede sem fios para fazer uma chamada."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Para telefonar, introduza um número válido."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"A chamada falhou."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Não é possível adicionar a chamada neste momento."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"A iniciar sequência de MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Serviço não suportado"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Não é possível alternar chamadas."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Não é possível libertar a(s) chamada(s)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Não é possível colocar as chamadas em espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Ligue-se a uma rede sem fios para fazer uma chamada."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Ativar as chamadas através de Wi-Fi para fazer uma chamada."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Chamada de emergência"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"A ligar o rádio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Sem serviço. A tentar novamente…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrar"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrar"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Correio de voz visual"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Definir PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Alterar PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Som"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Tocar e Vibrar"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Cartões SIM incorporados"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Apenas chamadas de emergência"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Cartão SIM, ranhura: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Acessibilidade"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Chamada Wi-Fi recebida"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Chamada a partir da rede Wi-Fi de"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Chamada Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Toque novamente para abrir"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Ocorreu um erro durante a descodificação da mensagem."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Um cartão SIM ativou o seu serviço e atualizou as capacidades de roaming do seu telemóvel."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Existem demasiadas chamadas ativas. Termine ou intercale as chamadas existentes antes de efetuar uma nova chamada."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Alterar o PIN do correio de voz"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continuar"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancelar"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirme o seu PIN antigo"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Introduza o PIN do seu correio de voz para continuar."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Definir um PIN novo"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"O PIN tem de ter <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> dígitos."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirmar PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Os PINs não correspondem"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"O PIN do correio de voz foi atualizado"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Não é possível definir o seu PIN"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index fe89fbd..cb257ae 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -30,7 +30,7 @@
<string name="mmiCancelled" msgid="2771923949751842276">"Código MMI cancelado"</string>
<string name="cancel" msgid="5044513931633602634">"Cancelar"</string>
<string name="enter_input" msgid="1810529547726803893">"A mensagem USSD deve ter de <xliff:g id="MIN_LEN">%d</xliff:g> a <xliff:g id="MAX_LEN">%d</xliff:g> caracteres. Tente novamente."</string>
- <string name="manageConferenceLabel" msgid="4691922394301969053">"Gerenciar conferência telefônica"</string>
+ <string name="manageConferenceLabel" msgid="4691922394301969053">"Gerenciar teleconferência"</string>
<string name="ok" msgid="3811371167865772377">"OK"</string>
<string name="audio_mode_speaker" msgid="27649582100085266">"Alto-falante"</string>
<string name="audio_mode_earpiece" msgid="4156527186373869107">"Minifone do aparelho"</string>
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Nenhuma alteração foi feita."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Escolha o serviço de correio de voz"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Sua operadora"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN antigo"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Novo PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Aguarde."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"O novo PIN é curto demais."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"O novo PIN é longo demais."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"O novo PIN é fácil demais. Uma senha segura não deve ter uma sequência contínua nem dígitos repetidos."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"O PIN antigo não corresponde."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"O novo PIN contém caracteres inválidos."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Não foi possível alterar o PIN."</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Tipo de mensagem incompatível, para ouvi-la, ligue para <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Configurações de rede celular"</string>
<string name="label_available" msgid="1181658289009300430">"Redes disponíveis"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Pesquisando..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferencial"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Modo 4G LTE avançado"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Chamada avançada"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Usar serviços de LTE para melhorar a voz e outras comunicações (recomendado)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Dados ativados"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Permitir o uso de dados"</string>
@@ -416,7 +427,7 @@
<string name="voicemail_settings_number_label" msgid="8524164258691887790">"Número correio de voz"</string>
<string name="card_title_dialing" msgid="5769417478498348054">"Discando"</string>
<string name="card_title_redialing" msgid="8253487008234167266">"Rediscando"</string>
- <string name="card_title_conf_call" msgid="1162980346189744501">"Conferência telefônica"</string>
+ <string name="card_title_conf_call" msgid="1162980346189744501">"teleconferência"</string>
<string name="card_title_incoming_call" msgid="7364539451234646909">"Recebendo chamada"</string>
<string name="card_title_call_ended" msgid="5544730338889702298">"Chamada encerrada"</string>
<string name="card_title_on_hold" msgid="821463117892339942">"Em espera"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"A rede celular não está disponível. Conecte-se a uma rede sem fio para fazer uma chamada."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Para realizar uma chamada, digite um número válido."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Falha na chamada."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"No momento, não é possível adicionar a chamada."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Iniciando sequência MMI…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Serviço não suportado"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Não é possível alternar as chamadas."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Não é possível liberar chamadas."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Não é possível colocar chamadas em espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Conecte-se a uma rede sem fio para fazer uma chamada."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Ative as chamadas por Wi-Fi para fazer uma chamada."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Chamada de emergência"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Ativando o rádio…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Sem serviço. Tentando novamente..."</string>
@@ -458,7 +471,7 @@
<string name="onscreenShowDialpadText" msgid="8561805492659639893">"Teclado"</string>
<string name="onscreenMuteText" msgid="5011369181754261374">"Desativar som"</string>
<string name="onscreenAddCallText" msgid="5140385634712287403">"Adicionar chamada"</string>
- <string name="onscreenMergeCallsText" msgid="6640195098064538950">"Mesclar chamadas"</string>
+ <string name="onscreenMergeCallsText" msgid="6640195098064538950">"Juntar chamadas"</string>
<string name="onscreenSwapCallsText" msgid="1602990689244030047">"Trocar"</string>
<string name="onscreenManageCallsText" msgid="5473231160123254154">"Gerenciar chamadas"</string>
<string name="onscreenManageConferenceText" msgid="6485935856534311346">"Gerenciar conferência"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrar"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrar"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Correio de voz visual"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Definir PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Alterar PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Som"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Toque e vibração"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Cartões SIM integrados"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Somente chamadas de emergência"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Cartão SIM, slot: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Acessibilidade"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Chamada por Wi-Fi recebida"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Chamada via Wi-Fi de"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Chamada por Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Toque novamente para abrir"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Ocorreu um erro ao decodificar a mensagem."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Um cartão SIM ativou seu serviço e atualizou os recursos de roaming do smartphone."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Há muitas chamadas ativas. Finalize ou mescle as chamadas existentes antes de fazer uma nova."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Alterar o PIN do correio de voz"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continuar"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Cancelar"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirme seu PIN antigo"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Digite o PIN do correio de voz para continuar."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Defina um novo PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"O PIN precisa ter de <xliff:g id="MIN">%1$d</xliff:g> a <xliff:g id="MAX">%2$d</xliff:g> dígitos."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirme seu PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Os PINs não correspondem"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN do correio de voz atualizado"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Não foi possível definir o PIN"</string>
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 3cc8422..98663a1 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Nicio schimbare efectuată."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Alegeți serviciul de mesagerie vocală"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operatorul dvs."</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Codul PIN vechi"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Codul PIN nou"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Așteptați."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Codul PIN nou este prea scurt."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Codul PIN nou este prea lung."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Codul PIN nou este prea slab. O parolă puternică nu ar trebui să aibă o secvență continuă sau cifre repetitive."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Codul PIN vechi nu corespunde."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Codul PIN nou conține caractere nevalide."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Nu se poate schimba codul PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Tip de mesaj neacceptat. Apelează numărul <xliff:g id="NUMBER">%s</xliff:g> pentru a-l asculta."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Setările pentru rețeaua mobilă"</string>
<string name="label_available" msgid="1181658289009300430">"Rețele disponibile"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Se caută…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA preferat"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Mod 4G LTE îmbunătățit"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Apelare avansată"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Folosiți servicii LTE pt. a îmbunătăți comunicări vocale și altele (recomandat)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Date activate"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Permiteți utilizarea datelor"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Rețeaua mobilă nu este disponibilă. Pentru a apela, conectați-vă la o rețea wireless."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Pentru a apela, introduceți un număr valid."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Apelul nu a fost inițiat."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Apelul nu poate fi adăugat în acest moment."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Se pornește secvența MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Serviciul nu este compatibil"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Apelurile nu pot fi comutate."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Apelurile nu pot fi eliberate."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Apelurile nu pot fi puse în așteptare."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Pentru a apela, conectați-vă la o rețea wireless."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Activați apelarea prin Wi-Fi pentru a iniția un apel."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Apel de urgență"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Se activează semnalul radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Fără semnal. Se încearcă din nou..."</string>
@@ -543,6 +556,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrații"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrații"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Mesagerie vocală vizuală"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Setați codul PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Schimbați codul PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Sunet"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ton de apel și vibrare"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Carduri SIM încorporate"</string>
@@ -554,10 +569,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Numai apeluri de urgență"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Cardul SIM, slotul: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accesibilitate"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Apel prin Wi-Fi primit"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Apel prin Wi-Fi de la"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Apel prin Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Atingeți din nou pentru a deschide"</string>
<string name="message_decode_error" msgid="3456481534066924855">"A apărut o eroare la decodificarea mesajului."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Un card SIM a activat serviciul și a actualizat funcțiile de roaming ale telefonului."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Prea multe apeluri active. Încheiați sau îmbinați apeluri existente înainte de a iniția unul nou."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Schimbați codul PIN pentru mesageria vocală"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Continuați"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Anulați"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Confirmați vechiul cod PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Introduceți codul PIN pentru mesageria vocală pentru a continua."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Setați un cod PIN nou"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Codul PIN trebuie să aibă între <xliff:g id="MIN">%1$d</xliff:g> - <xliff:g id="MAX">%2$d</xliff:g> cifre."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Confirmați codul PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Codurile PIN nu corespund"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Codul PIN pentru mesageria vocală a fost actualizat"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Nu s-a putut seta codul PIN"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 29e07a9..981387f 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Номер не изменен."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Выберите службу голосовой почты"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Ваш оператор связи"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Старый PIN-код"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Новый PIN-код"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Подождите…"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Новый PIN-код слишком короткий"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Новый PIN-код слишком длинный"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Новый PIN-код слишком простой. Чтобы пароль был надежным, он не должен содержать непрерывную последовательность чисел или повторяющиеся цифры."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Старый PIN-код указан неверно"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Новый PIN-код содержит недопустимые символы"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Не удалось сменить PIN-код"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Неподдерживаемый тип сообщения. Чтобы его прослушать, позвоните по телефону <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Настройки мобильных сетей"</string>
<string name="label_available" msgid="1181658289009300430">"Доступные сети"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Поиск…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA (предпочтительно)"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Режим 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Расширенный вызов"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Использовать сервисы LTE, чтобы улучшить качество связи (рекомендуется)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Передача данных"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Разрешить использование данных"</string>
@@ -438,6 +449,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Мобильная сеть недоступна. Чтобы позвонить, подключитесь к Wi-Fi."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Недействительный номер."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Не удалось отправить вызов."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Невозможно позвонить в данный момент."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Запуск последовательности MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Сервис не поддерживается"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Не удалось переключить вызов."</string>
@@ -448,6 +460,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Не удалось разъединить."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Удержание невозможно."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Чтобы позвонить, подключитесь к Wi-Fi."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Чтобы позвонить, включите звонки через Wi-Fi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Экстренный вызов"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Включение радио…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Нет сигнала. Повторная попытка…"</string>
@@ -548,6 +561,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Вибросигнал"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Вибросигнал"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Визуальная голосовая почта"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Установка PIN-кода"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Изменение PIN-кода"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Звук"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Рингтон и вибросигнал"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Встроенные SIM-карты"</string>
@@ -559,10 +574,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Только экстренные вызовы"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-карта, слот: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Специальные возможности"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Входящий Wi-Fi-звонок"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Вызов по Wi-Fi от"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi-звонок"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Чтобы открыть, нажмите ещё раз"</string>
<string name="message_decode_error" msgid="3456481534066924855">"При расшифровке сообщения произошла ошибка."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"В вашем телефоне уже настроен роуминг и активирована SIM-карта."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Слишком много активных вызовов. Чтобы выполнить новый вызов, завершите или объедините существующие."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Сменить PIN-код голосовой почты"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Продолжить"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Отмена"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ОК"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Подтвердите предыдущий PIN-код"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Чтобы продолжить, введите PIN-код голосовой почты"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Задайте новый PIN-код"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN-код должен содержать <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="8113764019347322170">"Подтвердите PIN-код"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-коды не совпадают."</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN-код голосовой почты обновлен"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Не удалось установить PIN-код"</string>
</resources>
diff --git a/res/values-si-rLK/strings.xml b/res/values-si-rLK/strings.xml
index 95dc439..106a817 100644
--- a/res/values-si-rLK/strings.xml
+++ b/res/values-si-rLK/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"කිසිඳු වෙනස්කමක් සිදු නොකෙරුණි."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"හඬ තැපැල් සේවාව තෝරන්න"</string>
<string name="voicemail_default" msgid="2001233554889016880">"ඔබගේ වාහකයා"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"පැරණි PIN අංකය"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"නව PIN අංකය"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"කරුණාකර රැඳී සිටින්න."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"නව PIN අංකය කෙටි වැඩිය."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"නව PIN අංකය දිග වැඩිය."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"නව PIN අංකය දුර්වල වැඩිය. ශක්තිමත් මුරපදයක අඛණ්ඩ අනුපිළිවෙළක් හෝ පුනරාවර්ත ඉලක්කම් නොතිබිය යුතුය."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"පැරණි PIN අංකය නොගැළපේ."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"නව PIN අංකයෙහි අවලංගු අනුලකුණු අන්තර්ගත වේ."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN අංකය මාරු කිරීමට නොහැකිය"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"සහාය නොදක්වන පණිවිඩය වර්ගය, සවන් දීමට <xliff:g id="NUMBER">%s</xliff:g> අමතන්න."</string>
<string name="mobile_networks" msgid="2843854043339307375">"සෙලියුලර් ජාල සැකසීම්"</string>
<string name="label_available" msgid="1181658289009300430">"තිබෙන ජාල"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"සොයමින්..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA කැමතියි"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"දියුණු කරන ලද 4G LTE මෝඩය"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"උසස් ඇමතුම්"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"හඬ සහ වෙනත් සන්නිවේදනයන් දියුණු කිරීමට LTE සේවාව භාවිතා කරන්න (නිර්දේශ කළ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"දත්ත සබලයි"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"දත්ත භාවිතයට ඉඩ දෙන්න"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"සෙලියුලර් ජාලය ලබාගත නොහැක. ඇමතුමක් ගැනීමට රැහැන් රහිත ජාලයකට සම්බන්ධ වෙන්න."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"ඇමතුමක් ලබාගැනීමට, වලංගු අංකයක් ලබාගන්න."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"ඇමතුම අසාර්ථක විය."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ඇමතුම මේ අවස්ථාවේදී එක් කළ නොහැකිය."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI අනුපිළිවෙල ආරම්භ කරමින්…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"සේවාවට සහාය දක්වන්නේ නැත"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"ඇමතුම් මාරු කිරීම කළ නොහැක."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"ඇමතුම(ම්) මුදාහැරීම කළ නොහැක."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"ඇමතුම් රඳවා තැබීමට නොහැකිය."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"ඇමතුමක් ගැනීමට රැහැන් රහිත ජාලයක් වෙත සම්බන්ධ වෙන්න."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"ඇමතුමක් කිරීමට Wi-Fi ඇමතීම සබල කරන්න."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"හදිසි ඇමතුම"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"රේඩියෝව ආරම්භ කරමින්…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"සේවා නැත. නැවත උත්සාහ කරන්න…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"කම්පනය වීම"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"කම්පනය වීම"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"දෘශ්ය හඬ තැපෑල"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN අංකය සකසන්න"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN අංකය වෙනස් කරන්න"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ශබ්දය"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"රිගින් ටෝන් සහ කම්පනය කරන්න"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"තිළැලි SIM කාඩ් පත්"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"හදිස්සි ඇමතූම් පමණි"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM කාඩ්පත්, තව්ව: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ප්රවේශ්යතාව"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"පැමිණෙන Wi-Fi ඇමතුම"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"වෙතින් Wi-Fi ඇමතුම"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi ඇමතුම"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"විවෘත කිරීමට නැවත තට්ටු කරන්න"</string>
<string name="message_decode_error" msgid="3456481534066924855">"පණිවිඩය විකේතනය කරන අතරතුර දෝෂයක් සිදු විය."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM කාඩ්පතක් ඔබේ සේවාව සක්රිය කර ඔබේ දුරකථනයේ රෝමිං හැකියා යාවත්කාලීන කර තිබේ."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"සක්රිය ඇමතුම් ඉතා විශාල ගණනක් ඇත. කරුණාකර නව ඇමතුමක් ගැනීමට පෙර පවතින ඇමතුම් අවසන් හෝ ඒකාබද්ධ කරන්න."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"හඬ තැපැල් PIN අංකය වෙනස් කරන්න"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"දිගටම කර ගෙන යන්න"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"අවලංගු කරන්න"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"හරි"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"ඔබේ පැරණි PIN අංකය තහවුරු කරන්න"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"දිගටම කරගෙන යාමට ඔබ හඬ තැපැල් PIN අංකය ඇතුළු කරන්න."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"නව PIN අංකයක් සකසන්න"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN අංකය ඉලක්කම් <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="8113764019347322170">"ඔබගේ PIN අංකය තහවුරු කරන්න"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN අංකය නොගැළපේ"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"හඬ තැපැල් PIN අංකය යාවත්කාලීන කෙරිණි"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN අංකය සැකසීමට නොහැකිය"</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index afcde37..4dbfe9a 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Neuskutočnili sa žiadne zmeny."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Zvoliť službu hlasovej schránky"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Váš operátor"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Starý PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nový PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Čakajte, prosím."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Nový PIN je príliš krátky."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Nový PIN je príliš dlhý."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Nový PIN je príliš slabý. Silné heslo by nemalo obsahovať postupnosť ani opakujúce sa číslice."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Starý PIN sa nezhoduje."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Nový PIN obsahuje neplatné znaky."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN nie je možné zmeniť"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Nepodporovaný typ správy, zavolajte na číslo <xliff:g id="NUMBER">%s</xliff:g> a vypočujte si správu."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Nastavenia mobilnej siete"</string>
<string name="label_available" msgid="1181658289009300430">"Dostupné siete"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Hľadá sa…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM / WCDMA – preferované"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Zlepšený režim 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Rozšírené volanie"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Použiť služby LTE na vylepšenie hlasu a ďalších komunikácií (odporúčané)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Povoliť dát. prenosy"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Povoliť využívanie dát"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobilná sieť nie je k dispozícii. Ak chcete volať, pripojte sa k bezdrôtovej sieti."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Ak chcete volať, zadajte platné číslo"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Hovor zlyhal."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Hovor momentálne nie je možné pridať."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Prebieha spúšťanie sekvencie MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Služba nie je podporovaná"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Nedajú sa prepínať hovory"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Nedajú sa ukončiť hovory"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Hovory nie je možné podržať."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Ak chcete volať, pripojte sa k bezdrôtovej sieti"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Na uskutočnenie hovoru povoľte volanie cez Wi-Fi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Tiesňové volanie"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Prebieha zapínanie rádia..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Žiadna služba. Prebieha opätovný pokus…"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrovať"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrovať"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vizuálna hlasová schránka"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Nastavenie kódu PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Zmena kódu PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Zvuk"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Tón zvonenia a vibrovanie"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Vstavané SIM karty"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Tiesňové volania iba na čísla"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Slot na SIM kartu: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Dostupnosť"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Prich. hovor cez Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Hovor cez Wi-Fi od:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Hovor cez Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Otvoríte opätovným klepnutím"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Pri dekódovaní správy sa vyskytla chyba"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM karta aktivovala vašu službu a aktualizovala možnosti roamingu vášho telefónu"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Prebieha príliš veľa aktívnych hovorov. Skôr ako uskutočníte nový hovor, ukončite existujúce hovory alebo ich zlúčte."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Zmena kódu PIN hlasovej schránky"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Pokračovať"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Zrušiť"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Potvrďte starý kód PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Ak chcete pokračovať, zadajte kód PIN hlasovej schránky."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Nastavte nový kód PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Kód PIN musí mať tento počet číslic: <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="8113764019347322170">"Potvrďte kód PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Kódy PIN sa nezhodujú"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Kód PIN hlasovej schránky bol aktualizovaný"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Kód PIN sa nedá nastaviť"</string>
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 306a0fb..f42a4b3 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Narejena ni bila nobena sprememba."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Izberite storitev glasovne pošte"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Vaš operater"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Stara koda PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Nova koda PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Počakajte."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Nova koda PIN je prekratka."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Nova koda PIN je predolga."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Nova koda PIN je prešibka. Zapleteno geslo ne sme vsebovati zaporednih ali ponavljajočih se števk."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Stara koda PIN se ne ujema."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Nova koda PIN vsebuje neveljavne znake."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Ni mogoče spremeniti kode PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Nepodprta vrsta sporočila, za poslušanje pokličite <xliff:g id="NUMBER">%s</xliff:g>."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Nastavitve mobilnega omrežja"</string>
<string name="label_available" msgid="1181658289009300430">"Razpoložljiva omrežja"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Iskanje ..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Prednostno GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Izboljšan način 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Napredno klicanje"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Uporaba storitev LTE za izboljšanje glas. in drugih komunikacij (priporočeno)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Podatki omogočeni"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Dovoli prenos podatkov"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobilno omrežje ni na voljo. Povežite se v omrežje Wi-Fi, če želite opraviti klic."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Če želite opraviti klic, vnesite veljavno številko."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Klic ni uspel."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Klica trenutno ni mogoče dodati."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Začetek zaporedja MMI ..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Storitev ni podprta"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Preklop med klici ni mogoč."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Prevzem klicev ni mogoč."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Klicev ni mogoče zadržati."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Povežite se v omrežje Wi-Fi, če želite opraviti klic."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Če želite opraviti klic, omogočite klicanja prek Wi-Fi-ja."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Klic v sili"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Vklop radia …"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ni signala. Vnovičen poskus …"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibriraj"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibriraj"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vizualno sporočilo v odzivniku"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Nastavitev kode PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Sprememba kode PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Zvok"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Zvonjenje in vibriranje"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Vgrajene kartice SIM"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Samo klicanje v sili"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Kartica SIM, reža: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Funkcije za ljudi s posebnimi potrebami"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Dohodni klic Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Klic prek Wi-Fi-ja osebe"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Klic Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Znova se dotaknite, če želite odpreti"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Napaka pri dekodiranju sporočila."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Kartica SIM je aktivirala vašo storitev in posodobila zmožnosti telefona za gostovanje."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Preveč aktivnih klicev. Preden začnete nov klic, končajte ali združite obstoječe klice."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Sprememba kode PIN za sporočila v odzivniku"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Naprej"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Prekliči"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"V redu"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Potrditev stare kode PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Če želite nadaljevati, vnesite kodo PIN za sporočila v odzivniku."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Nastavitev nove kode PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Koda PIN mora imeti <xliff:g id="MIN">%1$d</xliff:g>–<xliff:g id="MAX">%2$d</xliff:g> števk."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Potrditev kode PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Kodi PIN se ne ujemata"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Koda PIN za sporočila v odzivniku je posodobljena"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Kode PIN ni mogoče nastaviti"</string>
</resources>
diff --git a/res/values-sq-rAL/strings.xml b/res/values-sq-rAL/strings.xml
index d28cc8c..eaaa97b 100644
--- a/res/values-sq-rAL/strings.xml
+++ b/res/values-sq-rAL/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Nuk u bë asnjë ndryshim."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Zgjidh shërbimin e postës zanore"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operatori yt"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Kodi PIN i vjetër"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Kodi PIN i ri"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Prit..."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Kodi i ri PIN është shumë i shkurtër."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Kodi i ri PIN është shumë i gjatë."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Kodi i ri PIN është shumë i dobët. Një fjalëkalim i fortë nuk duhet të ketë rend të vazhdueshëm ose shifra të përsëritura."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Kodi PIN i vjetër nuk përputhet."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Kodi PIN i ri përmban karaktere të pavlefshme."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Kodi PIN nuk u ndryshua."</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Lloj mesazhi i pambështetur, telefono <xliff:g id="NUMBER">%s</xliff:g> për ta dëgjuar."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Cilësimet e rrjetit celular"</string>
<string name="label_available" msgid="1181658289009300430">"Rrjete të arritshme"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Po kërkon..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA i preferuar"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Modaliteti i përparuar 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Telefonatë e avancuar"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Përdor shërbimet LTE për të përmirësuar komunikimet zanore dhe të tjera (rekomandohet)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Të dhënat janë të aktivizuara"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Lejo përdorimin e të dhënave"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Rrjeti celular nuk mundësohet. Lidhu me një rrjet me valë për të bërë një telefonatë."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Për të kryer një telefonatë, fut një numër të vlefshëm."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Thirrja dështoi."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Telefonata nuk mund të shtohet këtë herë."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Po fillon sekuencën MMI…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Shërbimi nuk mbështetet"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Nuk mund të ndryshojë telefonatat."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Nuk mund të lëshojë telefonatën(at)."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Telefonatat nuk mund të mbahen në pritje."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Lidhu me një rrjet me valë për të bërë një telefonatë."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Aktivizo telefonatat nëpërmjet rrjetit Wi-Fi për të bërë një telefonatë."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Telefonata e urgjencës"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Po aktivizon radion…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Nuk ka shërbim. Po provon sërish…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Dridhja"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Dridhja"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Posta zanore vizuale"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Konfiguro kodin PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Ndrysho kodin PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Tingulli"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Me zile dhe me dridhje"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Kartat e integruara SIM"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Vetëm telefonata urgjence"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Karta SIM, foleja: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Qasshmëria"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Telefonatë hyrëse Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Telefonatë Wi-Fi nga"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Telefonatë me Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Trokit përsëri për ta hapur"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Ndodhi një gabim gjatë dekodimit të mesazhit."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Një kartë SIM ka aktivizuar shërbimin tënd dhe ka përditësuar aftësitë e roaming-ut të telefonit tënd."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Ka shumë thirrje aktive. Përfundo ose të bashko thirrjet ekzistuese para kryerjes së një thirrjeje të re."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Ndrysho kodin PIN të postës zanore"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Vazhdo"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Anulo"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Në rregull"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Konfirmo kodin PIN të vjetër"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Shkruaj kodin PIN të postës zanore për të vazhduar."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Cakto një kod të ri PIN."</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Kodi PIN duhet të ketë <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> shifra."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Konfirmo kodin tënd PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Kodet PIN nuk përputhen"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Kodi PIN i postës zanore u përditësua"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Kodi PIN nuk u caktua"</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index 50b4ae0..6ea18a0 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -29,7 +29,7 @@
<string name="ussdRunning" msgid="485588686340541690">"USSD кôд је покренут…"</string>
<string name="mmiCancelled" msgid="2771923949751842276">"MMI кôд је отказан"</string>
<string name="cancel" msgid="5044513931633602634">"Откажи"</string>
- <string name="enter_input" msgid="1810529547726803893">"USSD порука мора да има између <xliff:g id="MIN_LEN">%d</xliff:g> и <xliff:g id="MAX_LEN">%d</xliff:g> знакова. Покушајте поново."</string>
+ <string name="enter_input" msgid="1810529547726803893">"USSD порука мора да има између <xliff:g id="MIN_LEN">%d</xliff:g> и <xliff:g id="MAX_LEN">%d</xliff:g> знакова. Пробајте поново."</string>
<string name="manageConferenceLabel" msgid="4691922394301969053">"Управљање конференцијским позивом"</string>
<string name="ok" msgid="3811371167865772377">"Потврди"</string>
<string name="audio_mode_speaker" msgid="27649582100085266">"Звучник"</string>
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Нису извршене никакве промене."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Одаберите услугу говорне поште"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Мобилни оператер"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Стари PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Нови PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Сачекајте."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Нови PIN је прекратак."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Нови PIN је предугачак."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Нови PIN је преслаб. Јака лозинка не треба да садржи узастопни низ ни поновљене цифре."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Стари PIN се не подудара."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Нови PIN садржи неважеће знакове."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Промена PIN-а није успела"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Неподржани тип поруке. Позовите <xliff:g id="NUMBER">%s</xliff:g> да бисте је преслушали."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Подешавања мобилне мреже"</string>
<string name="label_available" msgid="1181658289009300430">"Доступне мреже"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Претражује се…"</string>
@@ -155,7 +165,7 @@
<string name="network_query_error" msgid="6828516148953325006">"Грешка током тражења мрежа."</string>
<string name="register_on_network" msgid="9055203954040805084">"Регистровање на <xliff:g id="NETWORK">%s</xliff:g>…"</string>
<string name="not_allowed" msgid="5613353860205691579">"SIM картица не дозвољава везу са овом мрежом."</string>
- <string name="connect_later" msgid="2308119155752343975">"Тренутно није могуће повезати се са овом мрежом. Покушајте поново касније."</string>
+ <string name="connect_later" msgid="2308119155752343975">"Тренутно није могуће повезати се са овом мрежом. Пробајте поново касније."</string>
<string name="registration_done" msgid="495135664535876612">"Регистровано на мрежи."</string>
<string name="sum_carrier_select" msgid="3494252551249882718">"Изаберите мрежног оператера"</string>
<string name="sum_search_networks" msgid="2921092249873272715">"Потражи све доступне мреже"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA има предност"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Побољшани 4G LTE режим"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Напредно позивање"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Коришћење LTE услуга за побољшање гласовних и других комуникација (препоручено)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Подаци су омогућени"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Омогућавање потрошње података"</string>
@@ -384,8 +395,8 @@
<string name="oldPinLabel" msgid="5287773661246368314">"Стари PIN"</string>
<string name="newPinLabel" msgid="207488227285336897">"Нови PIN"</string>
<string name="confirmPinLabel" msgid="257597715098070206">"Потврдите нови PIN"</string>
- <string name="badPin" msgid="8955102849303984935">"Стари PIN кôд који сте унели је нетачан. Покушајте поново."</string>
- <string name="mismatchPin" msgid="5923253370683071889">"PIN кодови које сте унели се не подударају. Покушајте поново."</string>
+ <string name="badPin" msgid="8955102849303984935">"Стари PIN кôд који сте унели је нетачан. Пробајте поново."</string>
+ <string name="mismatchPin" msgid="5923253370683071889">"PIN кодови које сте унели се не подударају. Пробајте поново."</string>
<string name="invalidPin" msgid="5981171102258684792">"Откуцајте PIN који има од 4 до 8 бројева."</string>
<string name="disable_sim_pin" msgid="3419351358300716472">"Брисање PIN-а за SIM"</string>
<string name="enable_sim_pin" msgid="4845145659651484248">"Подешавање PIN-а за SIM"</string>
@@ -399,9 +410,9 @@
<string name="oldPin2Label" msgid="8559146795026261502">"Стари PIN2"</string>
<string name="newPin2Label" msgid="4573956902204349054">"Нови PIN2"</string>
<string name="confirmPin2Label" msgid="8100319484454787708">"Потврдите нови PIN2"</string>
- <string name="badPuk2" msgid="7910064009531541708">"PUK2 није тачан. Покушајте поново."</string>
- <string name="badPin2" msgid="6646896629970023109">"Стари PIN2 није тачан. Покушајте поново."</string>
- <string name="mismatchPin2" msgid="4177967478551851117">"PIN2 кодови се не подударају. Покушајте поново."</string>
+ <string name="badPuk2" msgid="7910064009531541708">"PUK2 није тачан. Пробајте поново."</string>
+ <string name="badPin2" msgid="6646896629970023109">"Стари PIN2 није тачан. Пробајте поново."</string>
+ <string name="mismatchPin2" msgid="4177967478551851117">"PIN2 кодови се не подударају. Пробајте поново."</string>
<string name="invalidPin2" msgid="1757045131429105595">"Унесите PIN2 који садржи 4 до 8 цифара."</string>
<string name="invalidPuk2" msgid="7059081153334815973">"Унесите PUK2 који садржи 8 цифара."</string>
<string name="pin2_changed" msgid="3724522579945610956">"PIN2 је ажуриран"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Мобилна мрежа није доступна. Повежите се на бежичну мрежу да бисте упутили позив."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Да бисте упутили позив, унесите важећи број."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Позив није успео."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Тренутно није могуће додати позив."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Покретање MMI секвенце"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Услуга није подржана"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Замена позива није успела."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Успостављање позива није успело."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Није могуће стављати позиве на чекање."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Повежите се на бежичну мрежу да бисте упутили позив."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Омогућите позивање преко Wi-Fi-ја да бисте упутили позив."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Хитан позив"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Укључивање радија…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Нема мреже. Поновни покушај…"</string>
@@ -501,10 +514,10 @@
<string name="ota_progress" msgid="460876637828044519">"Телефон се програмира…"</string>
<string name="ota_failure" msgid="7713756181204620397">"Програмирање телефона није успело"</string>
<string name="ota_successful" msgid="1880780692887077407">"Телефон је сада активиран. Можда ће бити потребно највише 15 минута да би се услуга покренула."</string>
- <string name="ota_unsuccessful" msgid="8072141612635635357">"Телефон се није активирао. \nМожда је потребно да пронађете област са бољом покривеношћу (близу прозора или напољу). \n\nПокушајте поново или позовите корисничку подршку за још опција."</string>
+ <string name="ota_unsuccessful" msgid="8072141612635635357">"Телефон се није активирао. \nМожда је потребно да пронађете област са бољом покривеношћу (близу прозора или напољу). \n\nПробајте поново или позовите корисничку подршку за још опција."</string>
<string name="ota_spc_failure" msgid="3909983542575030796">"СЛУЧАЈНА SPC ГРЕШКА"</string>
<string name="ota_call_end" msgid="4537279738134612388">"Назад"</string>
- <string name="ota_try_again" msgid="7685477206465902290">"Покушај поново"</string>
+ <string name="ota_try_again" msgid="7685477206465902290">"Пробај поново"</string>
<string name="ota_next" msgid="3904945374358235910">"Следеће"</string>
<string name="ecm_exit_dialog" msgid="4448531867763097533">"Дијалог за излазак из режима хитног повратног позива"</string>
<string name="phone_entered_ecm_text" msgid="6266424252578731203">"Унет је режим за хитан повратни позив"</string>
@@ -535,7 +548,7 @@
<string name="voicemail_number_not_set" msgid="6724904736891087856">"<Није подешено>"</string>
<string name="other_settings" msgid="3672912580359716394">"Друга подешавања позива"</string>
<string name="calling_via_template" msgid="4839419581866928142">"Позивање преко <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
- <string name="contactPhoto" msgid="4713193418046639466">"фотографија контакта"</string>
+ <string name="contactPhoto" msgid="4713193418046639466">"слика контакта"</string>
<string name="goPrivate" msgid="865837794424530980">"иди на приватно"</string>
<string name="selectContact" msgid="781975788478987237">"изаберите контакт"</string>
<string name="not_voice_capable" msgid="2739898841461577811">"Аудио позиви нису подржани"</string>
@@ -543,6 +556,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Вибрација"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Вибрација"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Визуелна говорна пошта"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Подесите PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Промените PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Звук"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Мелодија звона и вибрација"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Уграђене SIM картице"</string>
@@ -554,10 +569,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Само за хитне позиве"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM картица, отвор: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Приступачност"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Долазни Wi-Fi позив"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi позив од"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi позив"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Додирните поново да бисте отворили"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Дошло је до грешке при декодирању поруке."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM картица је активирала услугу и ажурирала функције роминга на телефону."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Има превише активних позива. Завршите или обједините постојеће позиве пре него што упутите нови."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Промените PIN кôд говорне поште"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Настави"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Откажи"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Потврди"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Потврдите стари PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"кôд говорне поште да бисте наставили."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Подесите нови PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Број цифара које PIN мора да садржи: <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="8113764019347322170">"Потврдите PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-ови се не подударају"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN кôд говорне поште је ажуриран"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Подешавање PIN-а није успело"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index a59ad9b..3e0313b 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Du har inte gjort några ändringar."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Välj tjänst för röstbrevlådan"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Din operatör"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Gammal pinkod"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Ny pinkod"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Vänta."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Den nya pinkoden är för kort."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Den nya pinkoden är för lång."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Den nya pinkoden är för svag. Ett säkert lösenord bör inte ha siffror i ordningsföljd eller upprepade siffror."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Den gamla pinkoden stämmer inte."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Den nya pinkoden innehåller ogiltiga tecken."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Det gick inte att ändra pinkoden"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Meddelandetypen stöds inte, ring <xliff:g id="NUMBER">%s</xliff:g> om du vill lyssna."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Inställningar för mobilnätverk"</string>
<string name="label_available" msgid="1181658289009300430">"Tillgängliga nätverk"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Söker…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Föredrar GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Förbättrat 4G LTE-läge"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Avancerade samtal"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Använd LTE-tjänster för att förbättra bl.a. röstkommunikation (rekommenderas)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data är aktiverat"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Tillåt dataanvändning"</string>
@@ -442,6 +453,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Det finns inga tillgängliga mobilnätverk. Anslut till ett trådlöst nätverk om du vill ringa."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Ange ett giltigt nummer om du vill ringa ett samtal."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Det gick inte att koppla samtalet."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Det går inte att lägga till samtalet just nu."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Startar sekvens för MMI-kod…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Tjänsten stöds inte"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Det gick inte att växla mellan samtal."</string>
@@ -452,6 +464,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Det gick inte att släppa samtal."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Det går inte att hålla kvar samtal."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Anslut till ett trådlöst nätverk om du vill ringa."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Aktivera Wi-Fi-samtal för att ringa."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Nödsamtal"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Sätter på radion…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ingen tjänst. Försök igen …"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Vibrera"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Vibrera"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visuell röstbrevlåda"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Ställ in pinkod"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Byt pinkod"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Ljud"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ringsignal och vibrera"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Inbyggda SIM-kort"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Endast nödsamtal"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-kortsplats: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Tillgänglighet"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Inkommande Wi-Fi-samtal"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi-samtal från"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi-samtal"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Tryck igen för att öppna"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Ett fel inträffade när meddelandet avkodades."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Ett SIM-kort har använts för att aktivera tjänsten och uppdatera roamingfunktionerna i mobilen."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Det finns för många aktiva samtal. Avsluta eller slå samman pågående samtal innan du ringer ett nytt."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Ändra röstbrevlådans pinkod"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Fortsätt"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Avbryt"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Bekräfta den gamla pinkoden"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Ange pinkoden till röstbrevlådan för att fortsätta."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Ange en ny pinkod"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"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="8113764019347322170">"Bekräfta pinkod"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Pinkoderna matchar inte"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Röstbrevlådans pinkod bekräftad"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Det går inte att ställa in pinkod"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 9e8c0ff..b796752 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Hakuna mabadiliko yaliyofanywa"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Chagua huduma ya barua ya sauti"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Mtoa huduma wako"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN ya zamani"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"PIN mpya"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Tafadhali subiri."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"PIN mpya ni fupi mno."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"PIN mpya ni ndefu mno."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"PIN mpya ni dhaifu mno. Nenosiri thabiti halifai kuwa na herufi zinazofuatana mfululizo au tarakimu zinazorudiwa."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"PIN ya zamani si sahihi."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"PIN mpya ina herufi zisizostahiki."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Imeshindwa kubadilisha PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Huwezi kuona ujumbe wa aina hii; piga <xliff:g id="NUMBER">%s</xliff:g> ili uusikilize."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mipangilio ya mitandao ya simu"</string>
<string name="label_available" msgid="1181658289009300430">"Mitandao inayopatikana"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Inatafuta…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA inapendelewa"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Hali Iliyoimarishwa ya 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Upigaji Simu Ulioimarishwa"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Tumia huduma za LTE ili uboreshe sauti na mawasiliano mengine (inapendekezwa)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Data imewashwa"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Ruhusu matumizi ya data"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Huduma ya mtandao wa simu za mkononi haupatikani. Unganisha kwenye mtandao pasiwaya ili upige simu."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Ili upige simu, weka nambari sahihi."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Imeshindwa kupiga simu."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Hangout haiwezi kuongezwa kwa wakati huu."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Inaanzisha msururu wa MMI…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Huduma haiwezi kutumika."</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Haiwezi kubadili simu."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Haiwezi kutoa simu."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Haiwezi kushikilia simu."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Unganisha kwenye mtandao pasiwaya ili upige simu."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Washa kipengele cha kupiga simu kupitia Wi-Fi ili upige simu."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Simu ya dharura"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Inawasha redio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Hakuna huduma. Inajaribu tena..."</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Mtetemo"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Mtetemo"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Ujumbe wa Sauti Unaoonekana"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Weka PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Badilisha PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Sauti"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Mlio wa simu na Mtetemo"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"SIM kadi zilizojengewa ndani"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Simu za dharula pekee"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM kadi, nafasi: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Zana za walio na matatizo ya kuona au kusikia"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Simu ya Wi-Fi inayoingia"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Simu kupitia Wi-Fi kutoka"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Simu ya Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Gonga tena ili ufungue"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Hitilafu imetokea wakati wa usimbuaji wa ujumbe."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM kadi yako imeanzisha huduma yako na kusasisha uwezo wa simu yako wa kutumia mitandao mingine."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Kuna simu nyingi mno zinazoendelea. Tafadhali kata au uunganishe simu zinazoendelea kabla hujapiga nyingine."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Badilisha PIN ya Ujumbe wa Sauti"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Endelea"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Ghairi"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Sawa"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Thibitisha PIN yako ya awali"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Weka PIN yako ya ujumbe wa sauti ili uendelee."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Weka PIN mpya"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN lazima iwe na nambari <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="8113764019347322170">"Thibitisha PIN yako"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN hazilingani"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN ya ujumbe wa sauti imesasishwa"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Imeshindwa kuweka PIN"</string>
</resources>
diff --git a/res/values-ta-rIN/strings.xml b/res/values-ta-rIN/strings.xml
index c316e31..169d31b 100644
--- a/res/values-ta-rIN/strings.xml
+++ b/res/values-ta-rIN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"மாற்றங்கள் எவையும் செய்யப்படவில்லை."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"குரலஞ்சல் சேவையைத் தேர்வுசெய்க"</string>
<string name="voicemail_default" msgid="2001233554889016880">"உங்கள் மொபைல் நிறுவனம்"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"பழைய பின்"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"புதிய பின்"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"காத்திருக்கவும்."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"புதிய பின் மிகவும் சிறியதாக உள்ளது."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"புதிய பின் மிகவும் நீளமாக உள்ளது."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"புதிய பின் மிகவும் வலுவற்றதாக உள்ளது. வலுவான கடவுச்சொல்லில் தொடர்வரிசையோ மீண்டும் மீண்டும் வரும் இலக்கங்களோ இருக்கக்கூடாது."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"பழைய பின் பொருந்தவில்லை."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"புதிய பின்னில் தவறான எழுத்துக்குறிகள் உள்ளன."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"பின்னை மாற்ற முடியவில்லை"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"ஆதரிக்கப்படாத செய்தி வகை, தகவலைக் கேட்க <xliff:g id="NUMBER">%s</xliff:g> என்ற எண்ணிற்கு அழைக்கவும்."</string>
<string name="mobile_networks" msgid="2843854043339307375">"செல்லுலார் நெட்வொர்க் அமைப்பு"</string>
<string name="label_available" msgid="1181658289009300430">"கிடைக்கின்ற நெட்வொர்க்குகள்"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"தேடுகிறது..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA பரிந்துரைக்கப்பட்டது"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"மேம்பட்ட 4G LTE பயன்முறை"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"மேம்பட்ட அழைப்பு"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"குரல் மற்றும் பிற தொடர்புமுறைகளை மேம்படுத்த, LTE சேவைகளைப் பயன்படுத்தவும் (பரிந்துரைக்கப்பட்டது)"</string>
<string name="data_enabled" msgid="5972538663568715366">"தரவு இயக்கப்பட்டது"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"தரவுப் பயன்பாட்டை அனுமதி"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"செல்லுலார் நெட்வொர்க் கிடைக்கவில்லை. அழைக்க, வயர்லெஸ் நெட்வொர்க்குடன் இணைக்கவும்."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"அழைக்க, சரியான எண்ணை உள்ளிடவும்."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"அழைப்பு தோல்வியடைந்தது."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"இப்போது அழைப்பைச் சேர்க்க முடியாது."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI வரிசையைத் தொடங்குகிறது..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"சேவை ஆதரிக்கப்படவில்லை"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"அழைப்புகளில் மாற முடியாது."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"அழைப்பை(அழைப்புகளை) விடுவிக்க முடியாது."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"அழைப்புகளை ஹோல்டு செய்ய முடியாது."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"அழைக்க, வயர்லெஸ் நெட்வொர்க்குடன் இணைக்கவும்."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"அழைக்க, வைஃபை அழைப்பை இயக்கவும்."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"அவசரகால அழைப்பு"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"ரேடியோவை இயக்குகிறது…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"சேவை இல்லை. மீண்டும் முயற்சிக்கிறது…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"அதிர்வு"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"அதிர்வு"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"விஷூவல் குரலஞ்சல்"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"பின்னை அமை"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"பின்னை மாற்றவும்"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ஒலி"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"ரிங்டோன் & அதிர்வு"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"உள்ளமைந்த சிம் கார்டுகள்"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"அவசர அழைப்பு மட்டுமே"</string>
<string name="sim_description_default" msgid="4778679519938775515">"சிம் கார்டு, ஸ்லாட்: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"அணுகல் தன்மை"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"உள்வரும் வைஃபை அழைப்பு"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"வைஃபை அழைப்பு:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"வைஃபை அழைப்பு"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"திறக்க, மீண்டும் தட்டவும்"</string>
<string name="message_decode_error" msgid="3456481534066924855">"செய்தியைக் குறிவிலக்கும்போது பிழை ஏற்பட்டது."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"ஏற்கனவே சிம் கார்டைப் பயன்படுத்தி சேவை இயக்கப்பட்டது மற்றும் மொபைலின் ரோமிங் செயல்திறன்கள் புதுப்பிக்கப்பட்டன."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"மிகவும் அதிக அளவிலான அழைப்புகள் செயலில் உள்ளன. புதிய அழைப்பை மேற்கொள்ளும் முன், ஏற்கனவேயுள்ள அழைப்புகளைத் துண்டிக்கவும் அல்லது ஒன்றாகப் பிணைக்கவும்."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"குரலஞ்சல் பின்னை மாற்றவும்"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"தொடர்க"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"ரத்துசெய்"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"சரி"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"பழைய பின்னை உறுதிப்படுத்தவும்"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"தொடர, குரலஞ்சல் பின்னை உள்ளிடவும்."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"புதிய பின்னை அமைக்கவும்"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"பின்னில் <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="8113764019347322170">"பின்னை உறுதிசெய்யவும்"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"பின்கள் பொருந்தவில்லை"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"குரலஞ்சல் பின் மாற்றப்பட்டது"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"பின்னை அமைக்க முடியவில்லை"</string>
</resources>
diff --git a/res/values-te-rIN/strings.xml b/res/values-te-rIN/strings.xml
index 0845e46..ea3e43e 100644
--- a/res/values-te-rIN/strings.xml
+++ b/res/values-te-rIN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"మార్పులు ఏవీ చేయబడలేదు."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"వాయిస్ మెయిల్ సేవను ఎంచుకోండి"</string>
<string name="voicemail_default" msgid="2001233554889016880">"మీ క్యారియర్"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"పాత PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"కొత్త PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"దయచేసి వేచి ఉండండి."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"కొత్త PIN చాలా చిన్నదిగా ఉంది."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"కొత్త PIN చాలా పొడవు ఉంది."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"కొత్త PIN చాలా బలహీనంగా ఉంది. శక్తివంతమైన పాస్వర్డ్లో వరుస శ్రేణిలో అక్షరాలు/అంకెలు లేదా పునరావృత అంకెలు ఉండకూడదు."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"పాత PIN సరిపోలలేదు."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"కొత్త PIN చెల్లని అక్షరాలను కలిగి ఉంది."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PINని మార్చడం సాధ్యపడలేదు"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"మద్దతులేని సందేశ రకం, వినడానికి <xliff:g id="NUMBER">%s</xliff:g>కి కాల్ చేయండి."</string>
<string name="mobile_networks" msgid="2843854043339307375">"సెల్యులార్ నెట్వర్క్ సెట్టింగ్లు"</string>
<string name="label_available" msgid="1181658289009300430">"అందుబాటులో ఉన్న నెట్వర్క్లు"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"శోధిస్తోంది..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMAకు ప్రాధాన్యత"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"మెరుగుపరిచిన 4G LTE మోడ్"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"అధునాతన కాలింగ్"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"వాయిస్, ఇతర కమ్యూనికే. మెరుగుపరచడానికి LTE సేవలను ఉపయోగించు (సిఫార్సు చేయబడింది)"</string>
<string name="data_enabled" msgid="5972538663568715366">"డేటా ప్రారంభించబడింది"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"డేటా వినియోగాన్ని అనుమతించు"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"సెల్యులార్ నెట్వర్క్ అందుబాటులో లేదు. కాల్ చేయడానికి వైర్లెస్ నెట్వర్క్కి కనెక్ట్ చేయండి."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"కాల్ చేయడానికి, చెల్లుబాటు అయ్యే నంబర్ను నమోదు చేయండి."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"కాల్ విఫలమైంది."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ఈ సమయంలో కాల్ను జోడించడం సాధ్యపడదు."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI శ్రేణిని ప్రారంభిస్తోంది…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"సేవకు మద్దతు లేదు"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"కాల్లను మార్చలేరు."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"కాల్(ల)ను విడిచిపెట్టలేరు."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"కాల్లను హోల్డ్ చేయలేరు."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"కాల్ చేయడానికి వైర్లెస్ నెట్వర్క్కు కనెక్ట్ చేయండి."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"కాల్ను చేయడానికి Wi-Fi కాలింగ్ను ప్రారంభించండి."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"అత్యవసర కాల్"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"రేడియోను ప్రారంభిస్తోంది…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"సేవ లేదు. మళ్లీ ప్రయత్నిస్తోంది…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"వైబ్రేట్"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"వైబ్రేట్"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"దృశ్యమాన వాయిస్మెయిల్"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PINని సెట్ చేయండి"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PINను మార్చు"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"ధ్వని"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"రింగ్టోన్ & వైబ్రేట్"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"అంతర్నిర్మిత SIM కార్డులు"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"అత్యవసర కాలింగ్ మాత్రమే"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM కార్డ్, స్లాట్: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"ప్రాప్యత సామర్థ్యం"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"ఇన్కమింగ్ Wi-Fi కాల్"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"వీరి నుండి Wi-Fi కాల్"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi కాల్"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"తెరవడానికి మళ్లీ నొక్కండి"</string>
<string name="message_decode_error" msgid="3456481534066924855">"సందేశాన్ని డీకోడ్ చేస్తున్నప్పుడు లోపం సంభవించింది."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM కార్డ్ మీ సేవను సక్రియం చేసింది మరియు మీ ఫోన్ రోమింగ్ సామర్థ్యాలను నవీకరించింది."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"చాలా ఎక్కువ కాల్లు సక్రియంగా ఉన్నాయి. దయచేసి మరొక కొత్త కాల్ చేసే ముందు ఇప్పటికే ఉన్న కాల్లను ముగించండి లేదా విలీనం చేయండి."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"వాయిస్ మెయిల్ PINని మార్చండి"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"కొనసాగించు"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"రద్దు చేయి"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"సరే"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"మీ పాత PINని నిర్ధారించండి"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"కొనసాగించడానికి మీ వాయిస్ మెయిల్ PINని నమోదు చేయండి."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"కొత్త PINని సెట్ చేయండి"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN తప్పనిసరిగా <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="8113764019347322170">"మీ PINని నిర్ధారించండి"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PINలు సరిపోలలేదు"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"వాయిస్ మెయిల్ PIN నవీకరించబడింది"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PINని సెట్ చేయడం సాధ్యపడలేదు"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 9f2aa13..0bf2410 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"ไม่มีการเปลี่ยนแปลง"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"เลือกบริการข้อความเสียง"</string>
<string name="voicemail_default" msgid="2001233554889016880">"ผู้ให้บริการของคุณ"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"PIN เก่า"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"PIN ใหม่"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"โปรดรอสักครู่"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"PIN ใหม่สั้นเกินไป"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"PIN ใหม่ยาวเกินไป"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"PIN ใหม่เดาง่ายเกินไป รหัสผ่านที่เดายากไม่ควรมีตัวเลขที่เรียงค่ากันหรือตัวเลขซ้ำๆ"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"PIN เก่าไม่ถูกต้อง"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"PIN ใหม่มีอักขระที่ไม่ถูกต้อง"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"ไม่สามารถเปลี่ยน PIN ได้"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"ไม่รองรับข้อความประเภทนี้ โปรดโทร <xliff:g id="NUMBER">%s</xliff:g> เพื่อฟังข้อความเสียง"</string>
<string name="mobile_networks" msgid="2843854043339307375">"การตั้งค่าเครือข่ายมือถือ"</string>
<string name="label_available" msgid="1181658289009300430">"เครือข่ายที่ใช้งานได้"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"กำลังค้นหา…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"ต้องการ GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"โหมด 4G LTE ที่ปรับปรุงแล้ว"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"การโทรขั้นสูง"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"ใช้บริการ LTE เพื่อปรับปรุงเสียงและการติดต่อสื่อสารด้วยวิธีอื่นๆ (แนะนำ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"เปิดใช้งานข้อมูลแล้ว"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"อนุญาตการใช้ข้อมูล"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"เครือข่ายมือถือไม่พร้อมใช้งาน โปรดเชื่อมต่อเครือข่ายไร้สายเพื่อโทรออก"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"หากต้องการโทรออก โปรดป้อนหมายเลขที่ถูกต้อง"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"การโทรล้มเหลว"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"ไม่สามารถเพิ่มสายได้ในขณะนี้"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"กำลังเริ่มต้นลำดับ MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"บริการนี้ไม่ได้รับการสนับสนุน"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"ไม่สามารถสลับสายได้"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"ไม่สามารถเริ่มการโทรได้"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"ไม่สามารถถือสายรอได้"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"เชื่อมต่อเครือข่ายไร้สายเพื่อโทรออก"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"เปิดใช้การโทรผ่าน Wi-Fi เพื่อโทรออก"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"หมายเลขฉุกเฉิน"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"กำลังเปิดวิทยุ…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"ไม่มีบริการ โปรดลองอีกครั้ง…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"สั่น"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"สั่น"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"ข้อความเสียงพร้อมภาพ"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"ตั้งค่า PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"เปลี่ยน PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"เสียง"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"เสียงเรียกเข้าและสั่น"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"ซิมการ์ดในตัว"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"เฉพาะหมายเลขฉุกเฉินเท่านั้น"</string>
<string name="sim_description_default" msgid="4778679519938775515">"ซิมการ์ด ช่อง: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"การเข้าถึง"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"สายโทรเข้าผ่าน Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"โทรผ่าน Wi-Fi จาก"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"การโทรผ่าน Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"แตะอีกครั้งเพื่อเปิด"</string>
<string name="message_decode_error" msgid="3456481534066924855">"เกิดข้อผิดพลาดขณะถอดรหัสข้อความ"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"ซิมการ์ดได้เปิดใช้บริการของคุณและอัปเดตความสามารถในการโรมมิ่งของโทรศัพท์"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"มีสายที่ใช้งานอยู่มากเกินไป โปรดวางสายหรือรวมสายที่มีก่อนโทรออกครั้งใหม่"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"เปลี่ยน PIN ข้อความเสียง"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"ดำเนินการต่อ"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"ยกเลิก"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ตกลง"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"ยืนยัน PIN เก่าของคุณ"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"ป้อน PIN ข้อความเสียงเพื่อดำเนินการต่อ"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"ตั้งค่า PIN ใหม่"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN ต้องยาวระหว่าง <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="8113764019347322170">"ยืนยัน PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN ไม่ตรงกัน"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"อัปเดต PIN ข้อความเสียงแล้ว"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"ไม่สามารถตั้งค่า PIN"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index b5f7cc3..0e80bbe 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Walang ginawang mga pagbabago."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Piliin ang serbisyo ng voicemail"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Ang iyong carrier"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Lumang PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Bagong PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Pakihintay."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Masyadong maikli ang bagong PIN."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Masyadong mahaba ang bagong PIN."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Masyadong mahina ang bagong PIN. Ang isang malakas na password ay hindi dapat magkaroon ng tuloy-tuloy na sequence o paulit-ulit na mga digit."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Hindi tumutugma ang lumang PIN."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Ang bagong PIN ay naglalaman ng mga di-wastong character."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Hindi nabago ang PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Hindi sinusuportahang uri ng mensahe, tawagan ang <xliff:g id="NUMBER">%s</xliff:g> upang pakinggan."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Setting ng cellular network"</string>
<string name="label_available" msgid="1181658289009300430">"Mga available na network"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Naghahanap…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Ninanais ang GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Enhanced 4G LTE Mode"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Advanced na Pagtawag"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Gamitin ang LTE upang pahusayin ang voice at ibang komunikasyon (inirerekomenda)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Pinagana ang data"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Payagan ang paggamit ng data"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Hindi available ang cellular network. Kumonekta sa isang wireless network upang makatawag."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Upang tumawag, maglagay ng wastong numero."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Nabigo ang tawag."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Hindi maidaragdag ang tawag sa oras na ito."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Sinisimulan ang pagkakasunud-sunod ng MMI…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Hindi sinusuportahan ang serbisyo"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Hindi mailipat ang mga tawag."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Hindi mailabas ang (mga) tawag."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Hindi makakapag-hold ng mga tawag."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Kumonekta sa isang wireless network upang makatawag."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"I-enable ang pagtawag sa Wi-Fi upang tumawag."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Emergency na tawag"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Ino-on ang radyo…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Walang serbisyo. Sinusubukang muli…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Mag-vibrate"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Mag-vibrate"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visual Voicemail"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Magtakda ng PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Baguhin ang PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Tunog"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ringtone at Pag-vibrate"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Mga built-in na SIM card"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Emergency na pagtawag lang"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM card, slot: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Pagiging Naa-access"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Papasok na tawag sa Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Tawag sa Wi-Fi mula kay"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Tawag sa Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"I-tap muli upang buksan"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Nagkaroon ng error habang dine-decode ang mensahe."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Na-activate ng isang SIM card ang iyong serbisyo at na-update ang mga kakayahang roaming ng iyong telepono."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Masyadong maraming aktibong tawag. Mangyaring tapusin o pagsamahin ang mga umiiral na tawag bago gumawa ng bago."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Baguhin ang PIN sa Voicemail"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Magpatuloy"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Kanselahin"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Ok"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Kumpirmahin ang luma mong PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Ilagay ang iyong PIN sa voicemail upang magpatuloy."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Magtakda ng bagong PIN"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Ang PIN ay dapat <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> (na) digit."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Kumpirmahin ang iyong PIN"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Hindi tugma ang mga PIN"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"In-update ang PIN sa voicemail"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Hindi naitakda ang PIN"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 5fe17d7..1f6eead 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Hiçbir değişiklik yapılmadı."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Sesli mesaj hizmetini seç"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Operatörünüz"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Eski PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Yeni PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Lütfen bekleyin."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Yeni PIN çok kısa."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Yeni PIN çok uzun."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Yeni PIN çok zayıf. Güçlü bir şifrede birbirini sıralı şekilde takip eden veya yinelenen rakamlar bulunmamalıdır."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Eski PIN eşleşmiyor."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Yeni PIN, geçersiz karakterler içeriyor."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN değiştirilemedi"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Desteklenmeyen mesaj türü. Dinlemek için <xliff:g id="NUMBER">%s</xliff:g> numaralı telefonu arayın."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Hücresel ağ ayarları"</string>
<string name="label_available" msgid="1181658289009300430">"Kullanılabilir ağlar"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Aranıyor..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA tercih edilen"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Geliştirilmiş 4G LTE Modu"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Gelişmiş Çağrı"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Sesi ve diğer iletişimleri iyileştirmek için LTE hizmetlerini kullanın (önerilir)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Veri etkin"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Veri kullanımına izin ver"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Hücresel ağ kullanılamıyor. Telefon etmek için kablosuz ağa bağlanın."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Arama yapmak için geçerli bir numara girin."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Sesli arama başarısız oldu."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Çağrı şu anda eklenemiyor."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI dizisi başlatılıyor..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Hizmet desteklenmiyor"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Çağrı geçişi yapılamıyor."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Çağrılar bırakılamıyor."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Çağrılar beklemeye alınamıyor."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Telefon etmek için kablosuz ağa bağlanın."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Telefon etmek için Kablosuz çağrı\'yı etkinleştirin."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Acil durum çağrısı"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Radyo açılıyor..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Servis yok. Tekrar deneniyor…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Titreşim"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Titreşim"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Görsel Sesli Mesaj"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN\'i ayarlayın"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN\'i değiştirin"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Ses"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Zil Sesi ve Titreşim"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Yerleşik SIM kartlar"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Yalnızca acil durum çağrısı"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM kart, yuva: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Erişilebilirlik"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Gelen kablosuz çağrı"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Gelen çağrı (kablosuz):"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Kablosuz çağrı"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Açmak için tekrar dokunun"</string>
<string name="message_decode_error" msgid="3456481534066924855">"İletinin kodu çözülürken bir hata oluştu."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Bir SIM kart, hizmetinizi etkinleştirdi ve telefonunuzun dolaşım özelliklerini güncelledi."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Etkin çağrıların sayısı çok fazla. Yeni bir çağrı yapmadan önce lütfen mevcut çağrıları sonlandırın veya birleştirin."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Sesli Mesaj PIN\'ini Değiştirin"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Devam"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"İptal"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Tamam"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Eski PIN\'inizi onaylayın"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Devam etmek için sesli mesaj PIN\'inizi girin."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Yeni PIN oluşturun"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN, <xliff:g id="MIN">%1$d</xliff:g> ila <xliff:g id="MAX">%2$d</xliff:g> basamaklı olmalıdır."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"PIN\'inizi onaylayın"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN\'ler eşleşmiyor"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Sesli mesaj PIN\'i güncellendi"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN ayarlanamadı"</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 0e15703..0957cc7 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Не здійсн. жодних змін."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Вибер. службу голос. пошти"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Ваш оператор"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Старий PIN-код"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Новий PIN-код"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Зачекайте."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Новий PIN-код закороткий."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Новий PIN-код задовгий."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Новий PIN-код недостатньо надійний. Надійний PIN-код не має містити прямих послідовностей або повторюваних цифр."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Старий PIN-код неправильний."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Новий PIN-код містить недійсні символи"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Не вдалося змінити PIN-код"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Повідомлення непідтримуваного типу. Зателефонуйте на номер <xliff:g id="NUMBER">%s</xliff:g>, щоб прослухати."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Налаштування моб. мереж"</string>
<string name="label_available" msgid="1181658289009300430">"Доступні мережі"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Пошук…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Рекомендовано GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Розширений режим 4G LTE"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Дзвінки з розширеними можливостями"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Використ. служби LTE для покращення голосового й інших типів зв’язку (рекоменд.)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Передавання даних"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Дозволити використання даних"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Мобільна мережа недоступна. Щоб зателефонувати, під’єднайтеся до бездротової мережі."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Щоб зателефонувати, введіть дійсний номер."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Не вдалося здійснити виклик."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Зараз не можна додати виклик."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Запуск ряду MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Служба не підтримується"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Неможливо переключитися між викликами."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Неможливо телефонувати."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Не можна призупиняти виклики."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Щоб зателефонувати, під’єднайтеся до бездротової мережі."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Щоб мати змогу телефонувати, увімкніть виклики через Wi-Fi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Аварійний виклик"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Увімкнення радіо…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Зв’язку немає. Повторна спроба…"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Вібросигнал"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Вібросигнал"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Візуальна голосова пошта"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Установити PIN-код"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Змінити PIN-код"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Звук"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Сигнал дзвінка та вібросигнал"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Вбудовані SIM-карти"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Лише екстрені виклики"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM-карта, роз’єм: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Спеціальні можливості"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Вхід. дзвінок через Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Виклик Wi-Fi від"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Дзвінок через Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Торкніться знову, щоб відкрити"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Під час розшифрування повідомлення сталася помилка."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Коли ви вставили SIM-карту, було активовано мобільний зв’язок і оновлено можливості роумінгу вашого телефона."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Забагато активних викликів. Перш ніж зателефонувати новому абоненту, завершіть або об’єднайте поточні виклики."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Змінити PIN-код голосової пошти"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Продовжити"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Скасувати"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Підтвердьте старий PIN-код"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Щоб продовжити, введіть PIN-код голосової пошти."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Введіть новий PIN-код"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Рекомендована кількість цифр у PIN-коді: <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="8113764019347322170">"Підтвердьте свій PIN-код"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN-коди не збігаються"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"PIN-код голосової пошти змінено"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Не вдалося встановити PIN-код"</string>
</resources>
diff --git a/res/values-ur-rPK/strings.xml b/res/values-ur-rPK/strings.xml
index 02f1237..7195f1c 100644
--- a/res/values-ur-rPK/strings.xml
+++ b/res/values-ur-rPK/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"کوئی تبدیلیاں نہیں ہوئی تھیں۔"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"صوتی میل سروس کا انتخاب کریں"</string>
<string name="voicemail_default" msgid="2001233554889016880">"آپ کا کیریئر"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"پرانا PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"نیا PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"براہ کرم انتظار کریں۔"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"نیا PIN بہت ہی مختصر ہے۔"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"نیا PIN بہت ہی طویل ہے۔"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"نیا PIN بہت ہی کمزور ہے۔ مضبوط پاسورڈ میں مسلسل ترتیب یا دہرے عدد نہیں ہونے چاہئیں۔"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"پرانا PIN مماثل نہیں ہے۔"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"نئے PIN میں غلط کریکٹرز شامل ہیں۔"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN تبدیل کرنے سے قاصر"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"پیغام کی غیر تعاون یافتہ قسم، سننے کیلئے <xliff:g id="NUMBER">%s</xliff:g> پر کال کریں۔"</string>
<string name="mobile_networks" msgid="2843854043339307375">"سیلولر نیٹ ورک کی ترتیبات"</string>
<string name="label_available" msgid="1181658289009300430">"دستیاب نیٹ ورکس"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"تلاش کر رہا ہے…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA ترجیحی"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Enhanced 4G LTE وضع"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"اعلی درجے کی کالنگ"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"صوتی اور دیگر مواصلات کو بہتر بنانے کیلئے LTE سروسز استعمال کریں (تجویز کردہ)"</string>
<string name="data_enabled" msgid="5972538663568715366">"ڈیٹا فعال ہوگیا"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"ڈیٹا کے استعمال کی اجازت دیں"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"سیلولر نیٹ ورک دستیاب نہیں ہے۔ کال کرنے کیلئے کسی وائرلیس نیٹ ورک سے منسلک ہوں۔"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"کال کرنے کیلئے، ایک درست نمبر درج کریں۔"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"کال ناکام ہوگئی۔"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"اس وقت کال شامل نہیں ہو سکتی۔"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI ترتیب شروع ہو رہی ہے…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"سروس تعاون یافتہ نہیں ہے"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"کالز سوئچ نہیں کر سکتے۔"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"کال(ز) ریلیز نہیں کر سکتے۔"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"کالز کو ہولڈ نہیں کیا جا سکتا۔"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"کال کرنے کیلئے کسی وائرلیس نیٹ ورک سے منسلک ہوں۔"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"کال کرنے کیلئے Wi-Fi کالنگ فعال کریں۔"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"ہنگامی کال"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"ریڈیو آن کر رہا ہے…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"کوئی سروس نہیں ہے۔ دوبارہ کوشش کی جا رہی ہے…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"وائبریٹ"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"وائبریٹ"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"بصری صوتی میل"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN سیٹ کریں"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN تبدیل کریں"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"آواز"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"رنگ ٹون اور وائبریٹ"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"پہلے سے شامل SIM کارڈز"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"صرف ہنگامی کالنگ"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM کارڈ، سلاٹ: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Accessibility"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"آنے والی Wi-Fi کال"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi کال منجانب"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi کال"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"کھولنے کیلئے دوبارہ تھپتھپائیں"</string>
<string name="message_decode_error" msgid="3456481534066924855">"پیغام کو ڈیکوڈ کرتے وقت ایک خرابی پیش آ گئی۔"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"ایک SIM کارڈ نے آپ کی سروس فعال کر دی ہے اور آپ کے فون کی رومنگ اہلیتیں اپ ڈیٹ کر دی ہیں۔"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"بہت زیادہ فعال کالیں ہیں۔ براہ کرم نئی کال کرنے سے پہلے موجودہ کالوں کو ضم کریں یا ختم کریں۔"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"صوتی میل PIN تبدیل کریں"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"جاری رکھیں"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"منسوخ کریں"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"ٹھیک ہے"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"اپنی پرانی PIN کی توثیق کریں"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"جاری رکھنے کیلئے اپنی صوتی میل PIN داخل کریں۔"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"ایک نئی PIN سیٹ کریں"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN <xliff:g id="MAX">%2$d</xliff:g>-<xliff:g id="MIN">%1$d</xliff:g> اعداد کی ہونی چاہئیے۔"</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"اپنے PIN کی توثیق کریں"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PINs مماثل نہیں ہیں"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"صوتی میل PIN اپ ڈیٹ ہو گئی"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN سیٹ کرنے سے قاصر"</string>
</resources>
diff --git a/res/values-uz-rUZ/strings.xml b/res/values-uz-rUZ/strings.xml
index cbff20f..0c59092 100644
--- a/res/values-uz-rUZ/strings.xml
+++ b/res/values-uz-rUZ/strings.xml
@@ -48,7 +48,7 @@
<string name="puk_unlocked" msgid="2284912838477558454">"To‘sib qo‘yilgan SIM kartangiz ochildi. Telefoningiz qulfdan chiqarilmoqda…"</string>
<string name="label_ndp" msgid="780479633159517250">"SIM kartani tarmoqdagi qulfidan chiqarish PIN kodi"</string>
<string name="sim_ndp_unlock_text" msgid="683628237760543009">"Qulfdan chiqarish"</string>
- <string name="sim_ndp_dismiss_text" msgid="1604823375752456947">"Rad qilish"</string>
+ <string name="sim_ndp_dismiss_text" msgid="1604823375752456947">"Rad etish"</string>
<string name="requesting_unlock" msgid="6412629401033249351">"Tarmoqni qulfdan chiqarish so‘ralmoqda…"</string>
<string name="unlock_failed" msgid="6490531697031504225">"Tarmoqni qulfdan chiqarish so‘rovi muvaffaqiyatli amalga oshmadi."</string>
<string name="unlock_success" msgid="6770085622238180152">"Tarmoqni qulfdan chiqarish muvaffaqiyatli amalga oshdi."</string>
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"O‘zgarishlar qilinmadi."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Ovozli xabar xizmatini tanlash"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Aloqa operatoringiz"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Eski PIN kod"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Yangi PIN kod"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Iltimos, kuting."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Yangi PIN kod juda qisqa."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Yangi PIN kod juda uzun."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Yangi PIN kod juda sodda. Ishonchli PIN kodda ketma-ket takrorlanadigan raqamlar bo‘lmasligi lozim."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Eski PIN kod mos kelmayapti."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Yangi PIN kodda yaroqsiz belgilar mavjud."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"PIN kodni o‘zgartirib bo‘lmadi"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Bu xabar turi qo‘llab-quvvatlanmaydi. Uni eshitish uchun <xliff:g id="NUMBER">%s</xliff:g> raqamiga qo‘ng‘iroq qiling."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Mobil tarmoq sozlamalari"</string>
<string name="label_available" msgid="1181658289009300430">"Mavjud tarmoqlar"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Qidirilmoqda…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA xohishingiz bo‘yicha"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Kuchaytirilgan 4G LTE rejimi"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Keng imkoniyatli qo‘ng‘iroqlar"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Ovozli va boshqa aloqalarni yaxshilash uchun LTE xizmatlaridan foydalaning"</string>
<string name="data_enabled" msgid="5972538663568715366">"Internet yoqildi"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Mobil internetdan foydalanishga ruxsat"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Mobil tarmoq mavjud emas. Qo‘ng‘iroq qilish uchun simsiz tarmoqqa ulaning."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Qo‘ng‘iroq qilish uchun raqamni to‘g‘ri kiriting."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Qo‘ng‘iroq amalga oshmadi."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Hozirgi vaqtda qo‘ng‘iroq qo‘shib bo‘lmaydi."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"MMI tartibi ishga tushmoqda..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Bu xizmat qo‘llab-quvvatlanmaydi"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Qo‘ng‘iroqlarni almashtirib bo‘lmadi."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Qo‘ng‘iroq(lar)ni chiqarib bo‘lmadi."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Qo‘ng‘iroqlarni ushlab turib bo‘lmadi."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Qo‘ng‘iroq qilish uchun simsiz tarmoqqa ulaning"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Qo‘ng‘iroq qilish uchun Wi-Fi qo‘ng‘iroqlar funksiyasini yoqing."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Favqulodda chaqiruv"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Radio yoqilmoqda…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Aloqa yo‘q. Qayta urinilmoqda…"</string>
@@ -457,7 +470,7 @@
<string name="onscreenEndCallText" msgid="4403855834875398585">"Tugatish"</string>
<string name="onscreenShowDialpadText" msgid="8561805492659639893">"Terish paneli"</string>
<string name="onscreenMuteText" msgid="5011369181754261374">"Ovozni o‘chirish"</string>
- <string name="onscreenAddCallText" msgid="5140385634712287403">"Qo‘ng‘iroq qo‘shish"</string>
+ <string name="onscreenAddCallText" msgid="5140385634712287403">"Chaqiruv qo‘shish"</string>
<string name="onscreenMergeCallsText" msgid="6640195098064538950">"Qo‘ng‘iroqlarni birlashtirish"</string>
<string name="onscreenSwapCallsText" msgid="1602990689244030047">"Almashish"</string>
<string name="onscreenManageCallsText" msgid="5473231160123254154">"Qo‘ng‘iroqlarni boshqarish"</string>
@@ -526,7 +539,7 @@
<string name="progress_dialog_exiting_ecm" msgid="4835734101617817074">"Favqulodda teskari qo‘ng‘iroq rejimidan chiqilmoqda"</string>
<string name="alert_dialog_yes" msgid="6674268047820703974">"Ha"</string>
<string name="alert_dialog_no" msgid="1476091437797628703">"Yo‘q"</string>
- <string name="alert_dialog_dismiss" msgid="2491494287075907171">"Rad qilish"</string>
+ <string name="alert_dialog_dismiss" msgid="2491494287075907171">"Rad etish"</string>
<string name="voicemail_provider" msgid="5135942703327136909">"Xizmat"</string>
<string name="voicemail_settings" msgid="72448049107749316">"Sozlash"</string>
<string name="voicemail_number_not_set" msgid="6724904736891087856">"<Ko‘rsatilmagan>"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Tebranish"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Tebratish"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Vizual ovozli pochta"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"PIN kodni o‘rnatish"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"PIN kodni o‘zgartirish"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Ovoz"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Qo‘ng‘iroq ohangi & tebranish"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Ichki o‘rnatilgan SIM kartalar"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Faqat favqulodda qo‘ng‘iroqlar"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM karta, teshik: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Maxsus imkoniyatlar"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Kiruvchi Wi-Fi qo‘ng‘irog‘i"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi orqali qo‘ng‘iroq:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi qo‘ng‘irog‘i"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Ochish uchun yana bosing"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Xabarni kodsizlashda xatolik yuz berdi."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Telefoningizda rouming xizmati sozlangan va SIM karta faollashtirilgan."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Hozir bir nechta qo‘ng‘iroqlar amalda. Boshqa abonentga qo‘ng‘iroq qilishdan avval, amaldagi qo‘ng‘iroqlarni tugating yoki ularni konferens-aloqaga birlashtiring."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Ovozli pochta PIN kodini o‘zgartirish"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Davom etish"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Bekor qilish"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Eski PIN kodni tasdiqlang"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Davom etish uchun ovozli pochta PIN kodini kiriting."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Yangi PIN kod o‘rnatish"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN kod <xliff:g id="MIN">%1$d</xliff:g> – <xliff:g id="MAX">%2$d</xliff:g> raqamdan iborat bo‘lishi lozim."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"PIN kodni tasdiqlang"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN kodlar bir-biriga mos kelmadi"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Ovozli pochta PIN kodi yangilandi"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"PIN kodni o‘rnatib bo‘lmadi"</string>
</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 220bf6a..c42020f 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Không thay đổi nào được thực hiện."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Chọn dịch vụ thư thoại"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Nhà cung cấp dịch vụ của bạn"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"Mã PIN cũ"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"Mã PIN mới"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Vui lòng đợi."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"Mã PIN mới quá ngắn."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"Mã PIN mới quá dài."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"Mã PIN mới quá yếu. Một mật khẩu mạnh không nên có các chữ số lặp lại hoặc chuỗi liên tiếp."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"Mã PIN cũ không khớp."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"Mã PIN mới chứa các ký tự không hợp lệ."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Không thể thay đổi mã PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Loại tin nhắn không được hỗ trợ, hãy gọi số <xliff:g id="NUMBER">%s</xliff:g> để nghe."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Cài đặt mạng di động"</string>
<string name="label_available" msgid="1181658289009300430">"Mạng khả dụng"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Đang tìm kiếm…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA được ưa thích"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Chế độ 4G LTE tăng cường"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Tính năng gọi nâng cao"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Sử dụng dịch vụ LTE để cải tiến tính năng thoại và các phương thức giao tiếp khác (khuyến nghị)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Đã bật dữ liệu"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Cho phép sử dụng dữ liệu"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Hiện không có mạng di động. Hãy kết nối với mạng không dây để thực hiện cuộc gọi."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Để thực hiện cuộc gọi, hãy nhập một số hợp lệ."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Cuộc gọi không thành công."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Không thể thêm cuộc gọi tại thời điểm này."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Khởi động chuỗi MMI…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Dịch vụ không được hỗ trợ"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Không chuyển đổi được cuộc gọi."</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Không thực hiện được cuộc gọi."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Không thể giữ cuộc gọi."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Kết nối với mạng không dây để thực hiện cuộc gọi."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Bật gọi điện qua Wi-Fi để thực hiện cuộc gọi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Cuộc gọi khẩn cấp"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Đang bật radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Không có dịch vụ nào. Đang thử lại…"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Rung"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Rung"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Thư thoại kèm theo hình ảnh"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Đặt mã PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Thay đổi mã PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Âm thanh"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Nhạc chuông và rung"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Thẻ SIM tích hợp sẵn"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Chỉ gọi điện khẩn cấp"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Thẻ SIM, rãnh: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Trợ năng"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Cuộc gọi đến qua Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Cuộc gọi qua Wi-Fi từ"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Cuộc gọi qua Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Nhấn lại để mở"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Đã xảy ra lỗi khi giải mã tin nhắn."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Thẻ SIM đã kích hoạt dịch vụ của bạn và đã cập nhật chức năng chuyển vùng của điện thoại."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Có quá nhiều cuộc gọi hiện hoạt. Vui lòng kết thúc hoặc hợp nhất các cuộc gọi hiện có trước khi thực hiện cuộc gọi mới."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Thay đổi mã PIN thư thoại"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Tiếp tục"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Hủy"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"OK"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Xác nhận mã PIN cũ của bạn"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Nhập mã PIN thư thoại của bạn để tiếp tục."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Đặt mã PIN mới"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"Mã PIN phải bao gồm <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> chữ số."</string>
+ <string name="change_pin_confirm_pin_header" msgid="8113764019347322170">"Xác nhận mã PIN của bạn"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Các mã PIN không khớp"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"Đã cập nhật mã PIN thư thoại"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Không thể đặt mã PIN"</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index f013c7b..238a2e0 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"未做任何更改。"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"选择语音信箱服务"</string>
<string name="voicemail_default" msgid="2001233554889016880">"您的运营商"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"旧的 PIN 码"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"新的 PIN 码"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"请稍候。"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"新的 PIN 码太短。"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"新的 PIN 码太长。"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"新的 PIN 码安全系数太低。如要提高密码强度,请勿使用连续或重复的数字。"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"旧的 PIN 码不匹配。"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"新的 PIN 码包含无效字符。"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"无法更改 PIN 码"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"不受支持的语音邮件类型,请拨打 <xliff:g id="NUMBER">%s</xliff:g> 收听。"</string>
<string name="mobile_networks" msgid="2843854043339307375">"移动网络设置"</string>
<string name="label_available" msgid="1181658289009300430">"可用网络"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"正在搜索..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"首选 GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"增强型 4G LTE 模式"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"高级通话"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"使用 LTE 服务改进语音和其他通信功能(推荐)"</string>
<string name="data_enabled" msgid="5972538663568715366">"启用移动数据网络"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"允许使用数据流量"</string>
@@ -436,6 +447,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"移动网络不可用。需连接至无线网络才能拨打电话。"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"要拨打电话,请输入有效的电话号码。"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"无法通话。"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"目前无法添加通话。"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"正在启动 MMI 序列..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"服务不受支持"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"无法切换通话。"</string>
@@ -446,6 +458,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"无法挂断电话。"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"无法保持通话。"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"需连接至无线网络才能拨打电话。"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"启用 WLAN 通话功能以拨打电话。"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"紧急呼救"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"正在打开天线..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"无服务,正在重试…"</string>
@@ -453,7 +466,7 @@
<string name="dial_emergency_error" msgid="1509085166367420355">"无法拨打该电话。<xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> 不是紧急呼救号码。"</string>
<string name="dial_emergency_empty_error" msgid="9130194953830414638">"无法拨打该电话。请拨打紧急呼救电话。"</string>
<string name="dialerKeyboardHintText" msgid="9192914825413747792">"使用键盘拨号"</string>
- <string name="onscreenHoldText" msgid="2285258239691145872">"等待"</string>
+ <string name="onscreenHoldText" msgid="2285258239691145872">"保持"</string>
<string name="onscreenEndCallText" msgid="4403855834875398585">"挂断"</string>
<string name="onscreenShowDialpadText" msgid="8561805492659639893">"拨号键盘"</string>
<string name="onscreenMuteText" msgid="5011369181754261374">"静音"</string>
@@ -540,6 +553,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"振动"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"振动"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"可视语音邮箱"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"设置 PIN 码"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"更改 PIN 码"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"提示音"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"铃声和振动"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"内置SIM卡"</string>
@@ -551,10 +566,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"只能拨打紧急呼救电话"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM 卡,插槽:<xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"无障碍功能"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"WLAN 来电"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"WLAN 通话来电:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"WLAN 通话"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"再次点按即可打开"</string>
<string name="message_decode_error" msgid="3456481534066924855">"对邮件解码时出错。"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM 卡已启用您的服务,并更新了您手机的漫游功能。"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"进行中的通话过多。请结束现有通话或将其合并,然后再拨打新的电话。"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"更改语音信箱 PIN 码"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"继续"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"取消"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"确定"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"确认旧 PIN 码"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"输入语音信箱 PIN 码以继续操作。"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"设置新 PIN 码"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN 码必须为 <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="8113764019347322170">"确认 PIN 码"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN 码不一致"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"语音信箱 PIN 码已更新"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"无法设置 PIN 码"</string>
</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index d2749b4..15c8cc6 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"沒有更改。"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"選擇語音信箱服務"</string>
<string name="voicemail_default" msgid="2001233554889016880">"您的流動網絡供應商"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"舊的 PIN"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"新的 PIN"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"請稍候。"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"新的 PIN 太短。"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"新的 PIN 太長。"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"新的 PIN 太弱。強效密碼不應包含連續序列或重複數字。"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"舊的 PIN 不符。"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"新的 PIN 包含無效字元。"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"無法變更 PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"不支援的訊息類型,撥打 <xliff:g id="NUMBER">%s</xliff:g> 即可聆聽。"</string>
<string name="mobile_networks" msgid="2843854043339307375">"流動網絡設定"</string>
<string name="label_available" msgid="1181658289009300430">"可用的網絡"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"正在搜尋..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"首選 GSM/WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"強化 4G LTE 模式"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"進階通話功能"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"使用 LTE 服務改善語音及其他通訊 (建議)"</string>
<string name="data_enabled" msgid="5972538663568715366">"啟用流動數據"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"允許使用數據"</string>
@@ -442,6 +453,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"無法使用流動網絡。連接無線網絡,以撥打電話。"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"要撥打電話,請輸入有效的號碼。"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"無法接通。"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"目前無法新增通話。"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"開始 MMI 序列..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"不支援的服務"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"無法切換通話。"</string>
@@ -452,6 +464,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"無法釋放通話。"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"無法保留通話。"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"連接無線網絡,以撥打電話。"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"啟用 Wi-Fi 通話功能以撥打電話。"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"緊急電話"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"正在開啟無線電..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"沒有服務。請再試一次…"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"震動"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"震動"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Visual Voicemail"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"設定 PIN 碼"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"變更 PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"音效"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"鈴聲與震動"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"內置 SIM 卡"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"只限緊急通話"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM 卡,插槽:<xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"無障礙功能"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Wi-Fi 來電"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi 通話來自"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi 通話"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"再次輕按即可開啟"</string>
<string name="message_decode_error" msgid="3456481534066924855">"為訊息解碼時發生錯誤。"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM 卡已啟動您的服務,並更新了您的手機漫遊功能。"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"進行中的通話過多。請先結束或合併現有通話,再重新撥打。"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"變更語音信箱 PIN 碼"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"繼續"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"取消"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"確認"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"確認舊 PIN 碼"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"請輸入您的語音信箱 PIN 碼,然後繼續操作。"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"設定新 PIN 碼"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"PIN 碼長度必須介乎 <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="8113764019347322170">"確認 PIN 碼"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"PIN 碼不符"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"已更新語音信箱 PIN 碼"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"無法設定 PIN 碼"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index 111896a..dd5fa36 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"未變更設定。"</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"選擇語音信箱服務"</string>
<string name="voicemail_default" msgid="2001233554889016880">"您的行動通訊業者"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"舊的 PIN 碼"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"新的 PIN 碼"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"請稍候。"</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"新的 PIN 碼太短。"</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"新的 PIN 碼太長。"</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"新的 PIN 碼不夠安全。安全強度高的密碼不得使用連續或重複的數字。"</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"舊的 PIN 碼不符。"</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"新的 PIN 碼包含無效的字元。"</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"無法變更 PIN 碼"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"不支援的訊息類型,請撥打 <xliff:g id="NUMBER">%s</xliff:g> 聽取留言。"</string>
<string name="mobile_networks" msgid="2843854043339307375">"行動網路設定"</string>
<string name="label_available" msgid="1181658289009300430">"可用的網路"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"搜尋中…"</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"GSM/WCDMA 優先"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"加強型 4G LTE 模式"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"進階通話功能"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"使用 LTE 服務提升語音通訊和其他通訊的效能 (建議)"</string>
<string name="data_enabled" msgid="5972538663568715366">"啟用行動數據服務"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"允許使用行動數據"</string>
@@ -442,6 +453,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"無法使用行動通訊網路。但連上 Wi-Fi 網路即可撥打電話。"</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"如要撥打電話,請輸入有效的號碼。"</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"無法通話。"</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"目前無法新增通話。"</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"開始 MMI 序列…"</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"不支援的服務"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"無法切換通話。"</string>
@@ -452,6 +464,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"無法掛斷電話。"</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"無法保留通話。"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"連上無線網路即可撥打電話。"</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"請啟用 Wi-Fi 通話功能以撥打電話。"</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"緊急電話"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"開啟無線通訊中…"</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"找不到服務訊號,正在重試…"</string>
@@ -546,6 +559,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"震動"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"震動"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"具有畫面的語音信箱"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"設定語音信箱密碼"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"變更 PIN 碼"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"音效"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"鈴聲與震動"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"內建 SIM 卡"</string>
@@ -557,10 +572,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"僅限撥打緊急電話"</string>
<string name="sim_description_default" msgid="4778679519938775515">"SIM 卡,插槽:<xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"協助工具"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Wi-Fi 來電"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Wi-Fi 通話來電:"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Wi-Fi 通話"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"再次輕觸即可開啟"</string>
<string name="message_decode_error" msgid="3456481534066924855">"為郵件解碼時發生錯誤。"</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"SIM 卡已啟用您的服務並更新了手機的漫遊功能。"</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"進行中的通話過多。請先結束或合併現有通話,再撥打新的電話。"</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"變更語音信箱密碼"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"繼續"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"取消"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"確定"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"確認舊的語音信箱密碼"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"請輸入語音信箱密碼以繼續進行。"</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"設定新的語音信箱密碼"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"語音信箱密碼長度必須介於 <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="8113764019347322170">"確認語音信箱密碼"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"語音信箱密碼不符"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"已更新語音信箱密碼"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"無法設定語音信箱密碼"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index a146aeb..c08ff98 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -147,6 +147,16 @@
<string name="no_change" msgid="3186040086622435212">"Azikho izinguquko ezenziwe."</string>
<string name="sum_voicemail_choose_provider" msgid="59911196126278922">"Khetha insizikalo yemeyili yezwi"</string>
<string name="voicemail_default" msgid="2001233554889016880">"Inkampani yakho yenethiwekhi"</string>
+ <string name="vm_change_pin_old_pin" msgid="7295220109886682573">"I-PIN endala"</string>
+ <string name="vm_change_pin_new_pin" msgid="5412922262839438097">"I-PIN entsha"</string>
+ <string name="vm_change_pin_progress_message" msgid="3977357361934350336">"Sicela ulinde."</string>
+ <string name="vm_change_pin_error_too_short" msgid="5974971097302710497">"I-PIN entsha imfushane kakhulu."</string>
+ <string name="vm_change_pin_error_too_long" msgid="8476870806115051865">"I-PIN entsha yinde kakhulu."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="7883744811891784882">"I-PIN entsha ibuthakathaka. Iphasiwedi eqinile akufanele ibe nokulandelana okuqhubekayo noma amadijithi aphindaphindiwe."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="2754685537970757317">"I-PIN endala ayifani."</string>
+ <string name="vm_change_pin_error_invalid" msgid="3972205462701668653">"I-PIN entsha iqukethe izinhlamvu ezingavumelekile."</string>
+ <string name="vm_change_pin_error_system_error" msgid="6610603326230000207">"Ayikwazi ukushintsha i-PIN"</string>
+ <string name="vvm_unsupported_message_format" msgid="11795090778411977">"Uhlobo lomlayezo ongasekelwa, shayela ku-<xliff:g id="NUMBER">%s</xliff:g> ukuze ulalele."</string>
<string name="mobile_networks" msgid="2843854043339307375">"Izilungiselelo zenethiwekhi yeselula"</string>
<string name="label_available" msgid="1181658289009300430">"Amanethiwekhi atholakalayo"</string>
<string name="load_networks_progress" msgid="5230707536168902952">"Iyasesha..."</string>
@@ -198,6 +208,7 @@
<item msgid="3817924849415716259">"Okukhethwayo kwe-GSM / WCDMA"</item>
</string-array>
<string name="enhanced_4g_lte_mode_title" msgid="522191650223239171">"Imodi ye-4G LTE ethuthukisiwe"</string>
+ <string name="enhanced_4g_lte_mode_title_variant" msgid="4871126028907265406">"Ukushaya okuthuthukile"</string>
<string name="enhanced_4g_lte_mode_summary" msgid="2332175070522125850">"Sebenzisa amasevisi we-LTE ukuze uthuthukise izwi nokunye ukuxhumana (kunconyiwe)"</string>
<string name="data_enabled" msgid="5972538663568715366">"Idatha ivunyelwe"</string>
<string name="data_enable_summary" msgid="2382798156640007971">"Vumela ukusetshenziswa kwedatha"</string>
@@ -440,6 +451,7 @@
<string name="incall_error_out_of_service_wfc" msgid="323851839058697057">"Inethiwekhi yeselula ayitholakali. Xhumeka kunethiwekhi engenantambo ukuze wenze ikholi."</string>
<string name="incall_error_no_phone_number_supplied" msgid="1150414018684246528">"Ukuze wenze ikholi, faka inombolo evumelekile."</string>
<string name="incall_error_call_failed" msgid="5891978320269774095">"Ikholi ihlulekile."</string>
+ <string name="incall_error_cannot_add_call" msgid="5206923515522412110">"Ikholi ayikwazi ukungezwa ngalesi sikhathi."</string>
<string name="incall_status_dialed_mmi" msgid="3672498861336189563">"Iqalisa ukulandelana kwe-MMI..."</string>
<string name="incall_error_supp_service_unknown" msgid="655570339115407698">"Isevisi ayisekelwe"</string>
<string name="incall_error_supp_service_switch" msgid="5237002176899962862">"Ayikwazi ukushintsha amakholi."</string>
@@ -450,6 +462,7 @@
<string name="incall_error_supp_service_hangup" msgid="7434513517153834426">"Ayikwazi ukukhipha amakholi."</string>
<string name="incall_error_supp_service_hold" msgid="7967020511232222078">"Ayikwazi ukubamba amakholi."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="1782466780452640089">"Xhumeka kunethiwekhi engenantambo ukuze wenze ikholi."</string>
+ <string name="incall_error_promote_wfc" msgid="106510757624022064">"Nika amandla ukushaya kwevoyisimeyili ukuze wenze ikholi."</string>
<string name="emergency_enable_radio_dialog_title" msgid="4627849966634578257">"Ikholi ephuthumayo"</string>
<string name="emergency_enable_radio_dialog_message" msgid="207613549344420291">"Ivula umsakazo..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="5960061579996526883">"Ayikho isevisi. Iyazama futhi…"</string>
@@ -544,6 +557,8 @@
<string name="voicemail_notification_vibrate_when_title" msgid="8361970092063604886">"Dlidliza"</string>
<string name="voicemail_notification_vibarte_when_dialog_title" msgid="5739583146522136440">"Dlidliza"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="5012622186976275457">"Ivoyisimeyili ebonakalayo"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="2797924461029093837">"Setha IPHINI"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="6035421908626121564">"Shintsha i-PIN"</string>
<string name="voicemail_notification_ringtone_title" msgid="2609519527849101590">"Umsindo"</string>
<string name="preference_category_ringtone" msgid="5197960752529332721">"Ithoni yokukhala nokudlidliza"</string>
<string name="pstn_connection_service_label" msgid="1743245930577325900">"Amakhadi we-SIM akhelwe ngaphakathi"</string>
@@ -555,10 +570,22 @@
<string name="sim_description_emergency_calls" msgid="7535215397212301562">"Ikholi ephuthumayo kuphela"</string>
<string name="sim_description_default" msgid="4778679519938775515">"Ikhadi le-SIM, isilothi: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="8562004288733103868">"Ukufinyeleleka"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="8772915926382037499">"Ikholi ye-Wi-Fi engenayo"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="5932176406432044638">"Ikholi ye-Wi-Fi kusukela ku-"</string>
<string name="status_hint_label_wifi_call" msgid="8900805254974653903">"Ikholi ye-Wi-Fi"</string>
<string name="emergency_action_launch_hint" msgid="4906759256275562674">"Thepha futhi ukuze uvule"</string>
<string name="message_decode_error" msgid="3456481534066924855">"Kube nephutha ngenkathi kukhishwa ikhodi kumlayezo."</string>
<string name="callFailed_cdma_activation" msgid="2307989779233262164">"Ikhadi le-SIM lenze kwasebenza isevisi yakho laphinde labuyekeza amakhono okuzula wefoni yakho."</string>
<string name="callFailed_cdma_call_limit" msgid="1556916577171457086">"Kunamakholi amaningi asebenzayo. Sicela uphelise noma uhlanganise amakholi akhona ngaphambi kokubeka eyodwa."</string>
+ <string name="change_pin_title" msgid="7790232089699034029">"Shintsha IPHINI yevoyisimeyili"</string>
+ <string name="change_pin_continue_label" msgid="2135088662420163447">"Qhubeka"</string>
+ <string name="change_pin_cancel_label" msgid="353535488390948596">"Khansela"</string>
+ <string name="change_pin_ok_label" msgid="6204308560844889926">"Kulungile"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="419179847657548887">"Qinisekisa IPHINI yakho endala"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8579171678763615453">"Faka IPHINI yakho yevoyisimeyili ukuze uqhubeke."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="2611191814590251532">"Setha i-PIN entsha"</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2322940054329689309">"IPHINI kufanele ibe amadijithi angu-<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="8113764019347322170">"Qinisekisa i-PIN yakho"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="4795052654904027909">"Amaphini awafani"</string>
+ <string name="change_pin_succeeded" msgid="2022852286442211151">"IPHINI yevoyisimeyili ibuyekeziwe"</string>
+ <string name="change_pin_system_error" msgid="8308462387154257840">"Ayikwazi ukusetha IPHINI"</string>
</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 67572ed..870d692 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -54,9 +54,4 @@
<color name="dialer_dialpad_touch_tint">#330288d1</color>
<color name="floating_action_button_touch_tint">#80ffffff</color>
-
- <color name="network_operators_color_primary">#ff263238</color>
- <color name="network_operators_color_primary_dark">#ff21272b</color>
-
- <color name="emergency_dialer_background">#ff263238</color>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 7b64448..1f23c6b 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -207,6 +207,9 @@
<!-- Flag indicating whether to allow visual voicemail if available on the device.[DO NOT TRANSLATE] -->
<bool name="allow_visual_voicemail">true</bool>
+ <!-- Flag to enable VVM3 visual voicemail. VVM3 is used by Verizon Wireless. -->
+ <bool name="vvm3_enabled">false</bool>
+
<!-- Flag indicating whether to allow pstn phone accounts [DO NOT TRANSLATE] -->
<bool name="config_pstn_phone_accounts_enabled">true</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index b30f8ce..34cdeb5 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -330,6 +330,28 @@
<!-- Call settings screen, "Voicemail" screen, default option - Your Carrier -->
<string name="voicemail_default">Your carrier</string>
+ <!-- Hint for the old PIN field in the change vociemail PIN dialog -->
+ <string name="vm_change_pin_old_pin">Old PIN</string>
+ <!-- Hint for the new PIN field in the change vociemail PIN dialog -->
+ <string name="vm_change_pin_new_pin">New PIN</string>
+
+ <!-- Message on the dialog when PIN changing is in progress -->
+ <string name="vm_change_pin_progress_message">Please wait.</string>
+ <!-- Error message for the voicemail PIN change if the PIN is too short -->
+ <string name="vm_change_pin_error_too_short">The new PIN is too short.</string>
+ <!-- Error message for the voicemail PIN change if the PIN is too long -->
+ <string name="vm_change_pin_error_too_long">The new PIN is too long.</string>
+ <!-- Error message for the voicemail PIN change if the PIN is too weak -->
+ <string name="vm_change_pin_error_too_weak">The new PIN is too weak. A strong password should not have continuous sequence or repeated digits.</string>
+ <!-- Error message for the voicemail PIN change if the old PIN entered doesn't match -->
+ <string name="vm_change_pin_error_mismatch">The old PIN does not match.</string>
+ <!-- Error message for the voicemail PIN change if the new PIN contains invalid character -->
+ <string name="vm_change_pin_error_invalid">The new PIN contains invalid characters.</string>
+ <!-- Error message for the voicemail PIN change if operation has failed -->
+ <string name="vm_change_pin_error_system_error">Unable to change PIN</string>
+ <!-- Message to replace the transcription if a visual voicemail message is not supported-->
+ <string name="vvm_unsupported_message_format">Unsupported message type, call <xliff:g id="number" example="*86">%s</xliff:g> to listen.</string>
+
<!-- networks setting strings --><skip/>
<!-- Mobile network settings screen title -->
<string name="mobile_networks">Cellular network settings</string>
@@ -430,6 +452,8 @@
</string-array>
<!-- Cellular network 4G title [CHAR LIMIT=30] -->
<string name="enhanced_4g_lte_mode_title">Enhanced 4G LTE Mode</string>
+ <!-- Carrier variant of Enhaced 4G LTE Mode title. [CHAR LIMIT=50] -->
+ <string name="enhanced_4g_lte_mode_title_variant">Advanced Calling</string>
<!-- Cellular network 4G summary [CHAR LIMIT=80] -->
<string name="enhanced_4g_lte_mode_summary">Use LTE services to improve voice and other communications (recommended)</string>
@@ -971,6 +995,8 @@
<string name="incall_error_no_phone_number_supplied">To place a call, enter a valid number.</string>
<!-- In-call screen: call failure message displayed in an error dialog -->
<string name="incall_error_call_failed">Call failed.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog -->
+ <string name="incall_error_cannot_add_call">Call cannot be added at this time.</string>
<!-- In-call screen: status message displayed in a dialog when starting an MMI -->
<string name="incall_status_dialed_mmi">Starting MMI sequence\u2026</string>
<!-- In-call screen: message displayed in an error dialog -->
@@ -991,6 +1017,8 @@
<string name="incall_error_supp_service_hold">Can\'t hold calls.</string>
<!-- In-call screen: call failure message displayed in an error dialog when WFC is enabled, is wifi-only, and not connected to a wireless network. [CHAR_LIMIT=NONE] -->
<string name="incall_error_wfc_only_no_wireless_network">Connect to a wireless network to make a call.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog when the user is connected to a wireless network, but wifi calling is turned off. [CHAR_LIMIT=NONE] -->
+ <string name="incall_error_promote_wfc">Enable Wi-Fi calling to make a call.</string>
<!-- Dialog title for the "radio enable" UI for emergency calls -->
<string name="emergency_enable_radio_dialog_title">Emergency call</string>
@@ -1235,6 +1263,11 @@
<!-- Visual voicemail on/off title [CHAR LIMIT=40] -->
<string name="voicemail_visual_voicemail_switch_title">Visual Voicemail</string>
+ <!-- Voicemail change PIN dialog title [CHAR LIMIT=40] -->
+ <string name="voicemail_set_pin_dialog_title">Set PIN</string>
+ <!-- Voicemail change PIN dialog title [CHAR LIMIT=40] -->
+ <string name="voicemail_change_pin_dialog_title">Change PIN</string>
+
<!-- Voicemail ringtone title. The user clicks on this preference to select
which sound to play when a voicemail notification is received.
[CHAR LIMIT=30] -->
@@ -1292,7 +1325,7 @@
<!-- Status hint label for an incoming call over a wifi network which has not been accepted yet.
[CHAR LIMIT=25] -->
- <string name="status_hint_label_incoming_wifi_call">Incoming Wi-Fi call</string>
+ <string name="status_hint_label_incoming_wifi_call">Wi-Fi call from</string>
<!-- Status hint label for a call being made over a wifi network. [CHAR LIMIT=25] -->
<string name="status_hint_label_wifi_call">Wi-Fi call</string>
@@ -1302,6 +1335,8 @@
<string name="voicemail_notification_vibrate_key">voicemail_notification_vibrate_key</string>
<!-- DO NOT TRANSLATE. Internal key for a visual voicemail preference. -->
<string name="voicemail_visual_voicemail_key">voicemail_visual_voicemail_key</string>
+ <!-- DO NOT TRANSLATE. Internal key for a voicemail change pin preference. -->
+ <string name="voicemail_change_pin_key">voicemail_change_pin_key</string>
<!-- DO NOT TRANSLATE. Internal key for tty mode preference. -->
<string name="tty_mode_key">button_tty_mode_key</string>
<!-- DO NOT TRANSLATE. Internal key for a voicemail notification preference. -->
@@ -1326,4 +1361,28 @@
There are too many active calls. Please end or merge existing calls before placing a new one.
</string>
+ <!-- The title for the change voicemail PIN activity -->
+ <string name="change_pin_title">Change Voicemail PIN</string>
+ <!-- The label for the continue button in change voicemail PIN activity -->
+ <string name="change_pin_continue_label">Continue</string>
+ <!-- The label for the cancel button in change voicemail PIN activity -->
+ <string name="change_pin_cancel_label">Cancel</string>
+ <!-- The label for the ok button in change voicemail PIN activity -->
+ <string name="change_pin_ok_label">Ok</string>
+ <!-- The title for the enter old pin step in change voicemail PIN activity -->
+ <string name="change_pin_enter_old_pin_header">Confirm your old PIN</string>
+ <!-- The hint for the enter old pin step in change voicemail PIN activity -->
+ <string name="change_pin_enter_old_pin_hint">Enter your voicemail PIN to continue.</string>
+ <!-- The title for the enter new pin step in change voicemail PIN activity -->
+ <string name="change_pin_enter_new_pin_header">Set a new PIN</string>
+ <!-- The hint for the enter new pin step in change voicemail PIN activity -->
+ <string name="change_pin_enter_new_pin_hint">PIN must be <xliff:g id="min" example="4">%1$d</xliff:g>-<xliff:g id="max" example="7">%2$d</xliff:g> digits.</string>
+ <!-- The title for the confirm new pin step in change voicemail PIN activity -->
+ <string name="change_pin_confirm_pin_header">Confirm your PIN</string>
+ <!-- The error message for th confirm new pin step in change voicemail PIN activity, if the pin doen't match the one previously entered -->
+ <string name="change_pin_confirm_pins_dont_match">PINs don\'t match</string>
+ <!-- The toast to show after the voicemail PIN has been successfully changed -->
+ <string name="change_pin_succeeded">Voicemail PIN updated</string>
+ <!-- The error message to show if the server reported an error while attempting to change the voicemail PIN -->
+ <string name="change_pin_system_error">Unable to set PIN</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 9d2d47f..057352d 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -153,13 +153,6 @@
<item name="android:layout_marginEnd">5dip</item>
</style>
- <!-- Theme for the activity com.android.phone.Settings, which is the
- "Mobile network settings" screen (used on non-voice-capable
- tablets as well as regular phone devices.) -->
- <style name="Theme.Settings" parent="@android:style/Theme.Holo.DialogWhenLarge">
- <item name="android:windowCloseOnTouchOutside">true</item>
- </style>
-
<style name="SettingsLight" parent="android:Theme.Material.Light">
<item name="android:windowBackground">@color/phone_settings_background_color</item>
<item name="android:windowContentOverlay">@null</item>
@@ -186,11 +179,7 @@
<item name="android:textColor">?android:attr/textColorPrimaryInverseDisableOnly</item>
</style>
- <style name="NetworkOperatorsSettingsTheme" parent="@android:style/Theme.Material.Light">
- <item name="android:actionBarTheme">@android:style/ThemeOverlay.Material.Dark.ActionBar</item>
- <item name="android:colorPrimary">@color/network_operators_color_primary</item>
- <item name="android:colorPrimaryDark">@color/network_operators_color_primary_dark</item>
- </style>
+ <style name="NetworkOperatorsSettingsTheme" parent="@android:style/Theme.DeviceDefault.Settings" />
<style name="Empty" parent="@android:style/Theme.Material.Light">
<item name="android:windowIsTranslucent">true</item>
@@ -256,10 +245,9 @@
<item name="android:src">@drawable/overflow_menu</item>
</style>
- <style name="EmergencyDialerTheme" parent="@android:style/Theme.Material.NoActionBar">
- <item name="android:colorPrimary">@color/emergency_dialer_background</item>
- <item name="android:colorPrimaryDark">@color/emergency_dialer_background</item>
- <item name="android:windowBackground">@color/emergency_dialer_background</item>
+ <style name="EmergencyDialerTheme" parent="@*android:style/Theme.DeviceDefault.Settings.Dark.NoActionBar">
+ <item name="android:colorPrimaryDark">?android:attr/colorPrimary</item>
+ <item name="android:windowBackground">?android:attr/colorPrimary</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:homeAsUpIndicator">@drawable/ic_back_arrow</item>
@@ -296,8 +284,4 @@
<item name="android:backgroundDimEnabled">false</item>
</style>
- <style name="Theme.Material.Settings" parent="@android:style/Theme.Material.Settings">
- <item name="@*android:actionBarSize">56dip</item>
- <item name="preferenceBackgroundColor">@drawable/preference_background</item>
- </style>
</resources>
diff --git a/res/xml/voicemail_settings.xml b/res/xml/voicemail_settings.xml
index 9334566..e1dafb0 100644
--- a/res/xml/voicemail_settings.xml
+++ b/res/xml/voicemail_settings.xml
@@ -60,8 +60,12 @@
android:key="@string/voicemail_notification_vibrate_key"
android:title="@string/voicemail_notification_vibrate_when_title"
android:persistent="true" />
+
<SwitchPreference
android:key="@string/voicemail_visual_voicemail_key"
android:title="@string/voicemail_visual_voicemail_switch_title" />"
+ <Preference
+ android:key="@string/voicemail_change_pin_key"
+ android:title="@string/voicemail_change_pin_dialog_title" />
</PreferenceScreen>
diff --git a/res/xml/vvm_config.xml b/res/xml/vvm_config.xml
new file mode 100644
index 0000000..fad246f
--- /dev/null
+++ b/res/xml/vvm_config.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+
+<list name="carrier_config_list">
+ <pbundle_as_map>
+ <!-- Test -->
+ <string-array name="mccmnc">
+ <item value="TEST"/>
+ </string-array>
+ </pbundle_as_map>
+
+ <pbundle_as_map>
+ <!-- Orange France -->
+ <string-array name="mccmnc">
+ <item value="20801"/>
+ <item value="20802"/>
+ </string-array>
+
+ <int name="vvm_port_number_int" value="20481"/>
+ <string name="vvm_destination_number_string">21101</string>
+ <string-array name="carrier_vvm_package_name_string_array">
+ <item value="com.orange.vvm"/>
+ </string-array>
+ <string name="vvm_type_string">vvm_type_omtp</string>
+ <boolean name="vvm_cellular_data_required_bool" value="true"/>
+ </pbundle_as_map>
+
+ <pbundle_as_map>
+ <!-- T-Mobile USA-->
+ <string-array name="mccmnc">
+ <item value="310160"/>
+ <item value="310200"/>
+ <item value="310210"/>
+ <item value="310220"/>
+ <item value="310230"/>
+ <item value="310240"/>
+ <item value="310250"/>
+ <item value="310260"/>
+ <item value="310270"/>
+ <item value="310300"/>
+ <item value="310310"/>
+ <item value="310490"/>
+ <item value="310530"/>
+ <item value="310590"/>
+ <item value="310640"/>
+ <item value="310660"/>
+ <item value="310800"/>
+ </string-array>
+
+ <int name="vvm_port_number_int" value="1808"/>
+ <int name="vvm_ssl_port_number_int" value="993"/>
+ <string name="vvm_destination_number_string">122</string>
+ <string-array name="carrier_vvm_package_name_string_array">
+ <item value="com.tmobile.vvm.application"/>
+ </string-array>
+ <string name="vvm_type_string">vvm_type_cvvm</string>>
+ <string-array name="vvm_disabled_capabilities_string_array">
+ <!-- b/28717550 -->
+ <item value="AUTH=DIGEST-MD5"/>
+ </string-array>
+ </pbundle_as_map>
+
+ <pbundle_as_map>
+ <!-- Verizon USA -->
+ <string-array name="mccmnc">
+ <item value="310004"/>
+ <item value="310010"/>
+ <item value="310012"/>
+ <item value="310013"/>
+ <item value="310590"/>
+ <item value="310890"/>
+ <item value="310910"/>
+ <item value="311110"/>
+ <item value="311270"/>
+ <item value="311271"/>
+ <item value="311272"/>
+ <item value="311273"/>
+ <item value="311274"/>
+ <item value="311275"/>
+ <item value="311276"/>
+ <item value="311277"/>
+ <item value="311278"/>
+ <item value="311279"/>
+ <item value="311280"/>
+ <item value="311281"/>
+ <item value="311282"/>
+ <item value="311283"/>
+ <item value="311284"/>
+ <item value="311285"/>
+ <item value="311286"/>
+ <item value="311287"/>
+ <item value="311288"/>
+ <item value="311289"/>
+ <item value="311390"/>
+ <item value="311480"/>
+ <item value="311481"/>
+ <item value="311482"/>
+ <item value="311483"/>
+ <item value="311484"/>
+ <item value="311485"/>
+ <item value="311486"/>
+ <item value="311487"/>
+ <item value="311488"/>
+ <item value="311489"/>
+ </string-array>
+
+ <int name="vvm_port_number_int" value="0"/>
+ <string name="vvm_destination_number_string">900080006200</string>
+ <string name="vvm_type_string">vvm_type_vvm3</string>
+ <string name="vvm_client_prefix_string">//VZWVVM</string>
+ <boolean name="vvm_cellular_data_required_bool" value="true"/>
+ <boolean name="vvm_legacy_mode_enabled_bool" value="true"/>
+ <!-- VVM3 specific value for the voicemail management gateway to use if the SMS didn't provide
+ one -->
+ <string name="default_vmg_url">https://mobile.vzw.com/VMGIMS/VMServices</string>
+ </pbundle_as_map>
+</list>
diff --git a/sip/res/values-af/strings.xml b/sip/res/values-af/strings.xml
index b621aa9..569953e 100644
--- a/sip/res/values-af/strings.xml
+++ b/sip/res/values-af/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Opsionele instellings"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Stawinggebruikernaam"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Gebruikernaam gebruik vir stawing"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nie gestel nie>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nie gestel nie>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nie gestel nie>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nie gestel nie>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Dieselfde as gebruikernaam>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opsioneel>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Raak om almal te wys"</string>
diff --git a/sip/res/values-am/strings.xml b/sip/res/values-am/strings.xml
index 3d3c7a0..9f86bff 100644
--- a/sip/res/values-am/strings.xml
+++ b/sip/res/values-am/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"አማራጭ ቅንብሮች"</string>
<string name="auth_username_title" msgid="8262491689004708265">"የማረጋገጫ የተጠቃሚ ስም"</string>
<string name="auth_username_summary" msgid="941160241371436473">"ተጠቃሚ ስም ለማረጋገጫ ተጠቅሟል"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<አልተዘጋጀም>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<አልተዘጋጀም>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<አልተዘጋጀም>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<አልተዘጋጀም>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<ከተጠቃሚ ስም ጋር አንድ አይነት>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<አስገዳጅ ያልሆነ>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"ሁሉን ለማሳየት ▷ ይንኩ"</string>
diff --git a/sip/res/values-ar/strings.xml b/sip/res/values-ar/strings.xml
index 1e21f1d..1544bfd 100644
--- a/sip/res/values-ar/strings.xml
+++ b/sip/res/values-ar/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"الإعدادات الاختيارية"</string>
<string name="auth_username_title" msgid="8262491689004708265">"اسم المستخدِم للمصادقة"</string>
<string name="auth_username_summary" msgid="941160241371436473">"اسم المستخدِم المستخدَم للمصادقة"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<لم يتم التعيين>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<لم يتم التعيين>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<لم يتم التعيين>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<لم يتم التعيين>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<مثل اسم المستخدم>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<اختياري>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ المس لإظهار الكل"</string>
diff --git a/sip/res/values-az-rAZ/strings.xml b/sip/res/values-az-rAZ/strings.xml
index eaeebe7..4e88535 100644
--- a/sip/res/values-az-rAZ/strings.xml
+++ b/sip/res/values-az-rAZ/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Əlavə seçimlər"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Autentifikasiya istifadəçi adı"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Autentifikasiya üçün istifadə edilən istifadəçi adı"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Təyin edilməyib>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Təyin edilməyib>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Təyin edilməyib>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Təyin edilməyib>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<İstifadəçi adı ilə eyni>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<İstəyə görə>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"Hamısını göstərmək üçün toxunun ▷"</string>
diff --git a/sip/res/values-bg/strings.xml b/sip/res/values-bg/strings.xml
index df5cbf9..97c7ef4 100644
--- a/sip/res/values-bg/strings.xml
+++ b/sip/res/values-bg/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Незадължителни настройки"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Потребит. име за удостоверяване"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Потребителско име, използвано за удостоверяване"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Не е зададено>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Не е зададено>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Не е зададено>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Не е зададено>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Същото като потребителското име>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<По избор>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Докоснете за показване на всички"</string>
diff --git a/sip/res/values-bn-rBD/strings.xml b/sip/res/values-bn-rBD/strings.xml
index d77cca9..fc238ea 100644
--- a/sip/res/values-bn-rBD/strings.xml
+++ b/sip/res/values-bn-rBD/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"ঐচ্ছিক সেটিংস"</string>
<string name="auth_username_title" msgid="8262491689004708265">"প্রমাণীকরণের ব্যবহারকারীর নাম"</string>
<string name="auth_username_summary" msgid="941160241371436473">"প্রমাণীকরণের জন্য ব্যবহৃত ব্যবহারকারী নাম"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<সেট করা নেই>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<সেট করা নেই>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<সেট করা নেই>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<সেট করা নেই>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<ব্যবহারকারী নামের অনুরূপ>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<ঐচ্ছিক>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ সবকিছু দেখানোর জন্য স্পর্শ করুন"</string>
diff --git a/sip/res/values-ca/strings.xml b/sip/res/values-ca/strings.xml
index a626944..4f6d30a 100644
--- a/sip/res/values-ca/strings.xml
+++ b/sip/res/values-ca/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Configuració opcional"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nom d\'usuari per a l\'autenticació"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nom d\'usuari utilitzat per a l\'autenticació"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<No definit>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<No definit>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<No definit>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<No definit>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Igual que el nom d\'usuari>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opcional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Toca per mostrar-ho tot."</string>
diff --git a/sip/res/values-cs/strings.xml b/sip/res/values-cs/strings.xml
index 2d7c682..0b71b53 100644
--- a/sip/res/values-cs/strings.xml
+++ b/sip/res/values-cs/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Nepovinná nastavení"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Ověřovací uživatelské jméno"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Uživatelské jméno používané k ověření"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nenastaveno>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nenastaveno>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nenastaveno>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nenastaveno>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Stejné jako uživatelské jméno>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Nepovinné>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Výběrem této položky zobrazíte všechna nastavení"</string>
diff --git a/sip/res/values-da/strings.xml b/sip/res/values-da/strings.xml
index fc5e443..6ccbaec 100644
--- a/sip/res/values-da/strings.xml
+++ b/sip/res/values-da/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Valgfri indstillinger"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Brugernavn til godkendelse"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Brugernavn ved godkendelse"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ikke angivet>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ikke angivet>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ikke angivet>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ikke angivet>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Samme som brugernavn>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Valgfrit>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Tryk for at vise alle"</string>
diff --git a/sip/res/values-de/strings.xml b/sip/res/values-de/strings.xml
index 9b1d47a..2e8c8a2 100644
--- a/sip/res/values-de/strings.xml
+++ b/sip/res/values-de/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Optionale Einstellungen"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nutzername für die Authentifizierung"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Für die Authentifizierung verwendeter Nutzername"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nicht festgelegt>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nicht festgelegt>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nicht festgelegt>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nicht festgelegt>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Wie Nutzername>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Optional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Tippen, um alle einzublenden"</string>
diff --git a/sip/res/values-el/strings.xml b/sip/res/values-el/strings.xml
index 01f8270..4c04b81 100644
--- a/sip/res/values-el/strings.xml
+++ b/sip/res/values-el/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Προαιρετικές ρυθμίσεις"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Όνομα χρήστη ελέγχου ταυτότητας"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Όνομα χρήστη που χρησιμοποιείται για έλεγχο ταυτότητας"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Δεν έχει οριστεί>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Δεν έχει οριστεί>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Δεν έχει οριστεί>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Δεν έχει οριστεί>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Ίδιο με το όνομα χρήστη>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Προαιρετικό>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Αγγίξτε για εμφάνιση όλων"</string>
diff --git a/sip/res/values-en-rAU/strings.xml b/sip/res/values-en-rAU/strings.xml
index 59a9b16..24693a4 100644
--- a/sip/res/values-en-rAU/strings.xml
+++ b/sip/res/values-en-rAU/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Optional settings"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Authentication username"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Username used for authentication"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Not set>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Not set>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Not set>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Not set>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Same as username>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Optional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Touch to show all"</string>
diff --git a/sip/res/values-en-rGB/strings.xml b/sip/res/values-en-rGB/strings.xml
index 59a9b16..24693a4 100644
--- a/sip/res/values-en-rGB/strings.xml
+++ b/sip/res/values-en-rGB/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Optional settings"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Authentication username"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Username used for authentication"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Not set>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Not set>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Not set>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Not set>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Same as username>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Optional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Touch to show all"</string>
diff --git a/sip/res/values-en-rIN/strings.xml b/sip/res/values-en-rIN/strings.xml
index 59a9b16..24693a4 100644
--- a/sip/res/values-en-rIN/strings.xml
+++ b/sip/res/values-en-rIN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Optional settings"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Authentication username"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Username used for authentication"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Not set>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Not set>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Not set>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Not set>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Same as username>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Optional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Touch to show all"</string>
diff --git a/sip/res/values-es-rUS/strings.xml b/sip/res/values-es-rUS/strings.xml
index c16d375..168ab60 100644
--- a/sip/res/values-es-rUS/strings.xml
+++ b/sip/res/values-es-rUS/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Configuración opcional"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nombre de usuario de autenticación"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nombre de usuario utilizado para autenticación"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Sin configurar>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<No establecido>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<No establecida>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<No establecida>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Igual que el nombre de usuario>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opcional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Tocar para mostrar todo"</string>
diff --git a/sip/res/values-es/strings.xml b/sip/res/values-es/strings.xml
index 61f8b1c..46e2021 100644
--- a/sip/res/values-es/strings.xml
+++ b/sip/res/values-es/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Ajustes opcionales"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nombre de usuario de autenticación"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nombre de usuario utilizado para la autenticación"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<No definido>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<No configurado>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<No configurada>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<No configurada>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Igual que el nombre de usuario>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opcional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Tocar para mostrar todo"</string>
diff --git a/sip/res/values-et-rEE/strings.xml b/sip/res/values-et-rEE/strings.xml
index f3b467b..46891c5 100644
--- a/sip/res/values-et-rEE/strings.xml
+++ b/sip/res/values-et-rEE/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Valikulised seaded"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Autentimise kasutajanimi"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Autentimiseks kasutatav kasutajanimi"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Määramata>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Määramata>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Määramata>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Määramata>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Sama kui kasutajanimi>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Valikuline>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Puudutage kõige kuvamiseks"</string>
diff --git a/sip/res/values-eu-rES/strings.xml b/sip/res/values-eu-rES/strings.xml
index b128da6..f9800f4 100644
--- a/sip/res/values-eu-rES/strings.xml
+++ b/sip/res/values-eu-rES/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Aukerako ezarpenak"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Autentifikatzeko erabiltzaile-izena"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Autentifikatzeko erabili den erabiltzaile-izena"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ezarri gabe>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ezarri gabe>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ezarri gabe>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ezarri gabe>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Erabiltzaile-izenaren berdina>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Aukerakoa>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Guztiak erakusteko, ukitu"</string>
diff --git a/sip/res/values-fa/strings.xml b/sip/res/values-fa/strings.xml
index 2298385..d0552d9 100644
--- a/sip/res/values-fa/strings.xml
+++ b/sip/res/values-fa/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"تنظیمات اختیاری"</string>
<string name="auth_username_title" msgid="8262491689004708265">"نام کاربری برای احراز هویت"</string>
<string name="auth_username_summary" msgid="941160241371436473">"نام کاربری مورد استفاده برای احراز هویت"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<تنظیم نشده>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<تنظیم نشده>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<تنظیم نشده>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<تنظیم نشده>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<مانند نام کاربری>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<اختیاری>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ جهت نمایش همه لمس کنید"</string>
diff --git a/sip/res/values-fi/strings.xml b/sip/res/values-fi/strings.xml
index 05aa2a1..fd39cfd 100644
--- a/sip/res/values-fi/strings.xml
+++ b/sip/res/values-fi/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Lisäasetukset"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Todennuksessa käytettävä käyttäjänimi"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Käyttäjänimeä käytetään todennukseen"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ei asetettu>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ei määritetty>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ei määritetty>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ei määritetty>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Sama kuin käyttäjänimi>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Valinnainen>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Näytä kaikki koskettamalla"</string>
diff --git a/sip/res/values-fr-rCA/strings.xml b/sip/res/values-fr-rCA/strings.xml
index 60bd945..1c501b0 100644
--- a/sip/res/values-fr-rCA/strings.xml
+++ b/sip/res/values-fr-rCA/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Paramètres facultatifs"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nom d\'utilisateur d\'authentification"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nom d\'utilisateur utilisé pour l\'authentification"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Non défini>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Non défini>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Non défini>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Non défini>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Identique au nom d\'utilisateur>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Facultatif>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"Touchez ▷ pour tout afficher"</string>
diff --git a/sip/res/values-fr/strings.xml b/sip/res/values-fr/strings.xml
index 359576e..5773ff3 100644
--- a/sip/res/values-fr/strings.xml
+++ b/sip/res/values-fr/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Paramètres facultatifs"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nom d\'utilisateur d\'authentification"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nom d\'utilisateur utilisé pour l\'authentification"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Non défini>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Non défini>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Non défini>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Non définie>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Identique au nom d\'utilisateur>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Facultatif>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Appuyer ici pour tout afficher"</string>
diff --git a/sip/res/values-gl-rES/strings.xml b/sip/res/values-gl-rES/strings.xml
index 8368de0..74b9e4f 100644
--- a/sip/res/values-gl-rES/strings.xml
+++ b/sip/res/values-gl-rES/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Configuración opcional"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nome de usuario da autenticación"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nome de usuario utilizado para a autenticación"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Sen configurar>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Sen definir>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Sen definir>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Sen definir>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Igual que o nome de usuario>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opcional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Toca aquí para mostrar todo"</string>
diff --git a/sip/res/values-gu-rIN/strings.xml b/sip/res/values-gu-rIN/strings.xml
index e4e72e9..b7f3f17 100644
--- a/sip/res/values-gu-rIN/strings.xml
+++ b/sip/res/values-gu-rIN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"વૈકલ્પિક સેટિંગ્સ"</string>
<string name="auth_username_title" msgid="8262491689004708265">"પ્રમાણીકરણ વપરાશકર્તાનામ"</string>
<string name="auth_username_summary" msgid="941160241371436473">"પ્રમાણીકરણ માટે ઉપયોગમાં લેવાયેલ વપરાશકર્તાનામ"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<સેટ કરેલ નથી>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<સેટ કરેલ નથી>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<સેટ કરેલ નથી>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<સેટ કરેલ નથી>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<વપરાશકર્તાનામના સમાન>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<વૈકલ્પિક>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ બધુ દર્શાવવા માટે ટચ કરો"</string>
diff --git a/sip/res/values-hi/strings.xml b/sip/res/values-hi/strings.xml
index ea665cb..61122d5 100644
--- a/sip/res/values-hi/strings.xml
+++ b/sip/res/values-hi/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"वैकल्पिक सेटिंग"</string>
<string name="auth_username_title" msgid="8262491689004708265">"प्रमाणीकरण उपयोगकर्ता नाम"</string>
<string name="auth_username_summary" msgid="941160241371436473">"प्रमाणीकरण के लिए उपयोग होने वाला उपयोगकर्ता नाम"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<सेट नहीं है>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<सेट नहीं है>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<सेट नहीं है>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<सेट नहीं है>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<उपयोगकर्ता नाम के समान>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<वैकल्पिक>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ सभी दिखाने के लिए स्पर्श करें"</string>
diff --git a/sip/res/values-hr/strings.xml b/sip/res/values-hr/strings.xml
index cf57269..ba6cbc0 100644
--- a/sip/res/values-hr/strings.xml
+++ b/sip/res/values-hr/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Izborne postavke"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Korisničko ime za autentifikaciju"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Korisničko ime koje se upotrebljava za autentifikaciju"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nije postavljeno>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nije postavljeno>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nije postavljeno>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nije postavljeno>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Isto kao korisničko ime>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Izborno>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Dodirnite da biste prikazali sve"</string>
diff --git a/sip/res/values-hu/strings.xml b/sip/res/values-hu/strings.xml
index 12aef74..520255f 100644
--- a/sip/res/values-hu/strings.xml
+++ b/sip/res/values-hu/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"További beállítások"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Azonosításhoz használt felhasználónév"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Azonosításhoz használt felhasználónév"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nincs beállítva>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nincs megadva>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nincs megadva>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nincs megadva>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Ugyanaz, mint a felhasználónév>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Nem kötelező>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Érintse meg az összes megjelenítéséhez"</string>
diff --git a/sip/res/values-hy-rAM/strings.xml b/sip/res/values-hy-rAM/strings.xml
index cc1d26a..8ff66c2 100644
--- a/sip/res/values-hy-rAM/strings.xml
+++ b/sip/res/values-hy-rAM/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Ընտրովի կարգավորումներ"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Նույնականացման օգտանուն"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Օգտանունն օգտագործվել է նույնականացման համար"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Կարգավորված չէ>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Սահմանված չէ>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Սահմանված չէ>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Սահմանված չէ>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Նույնը, ինչ օգտանունը>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Ընտրովի>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Հպեք՝ ցուցադրելու ամենը"</string>
diff --git a/sip/res/values-in/strings.xml b/sip/res/values-in/strings.xml
index 6b4bb10..c2f40b7 100644
--- a/sip/res/values-in/strings.xml
+++ b/sip/res/values-in/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Setelan opsional"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nama pengguna autentikasi"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nama pengguna yang digunakan untuk autentikasi"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Tidak disetel>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Tidak disetel>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Tidak disetel>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Tidak disetel>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Sama dengan nama pengguna>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opsional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Sentuh untuk menampilkan semua"</string>
diff --git a/sip/res/values-is-rIS/strings.xml b/sip/res/values-is-rIS/strings.xml
index 4033ca7..ff15909 100644
--- a/sip/res/values-is-rIS/strings.xml
+++ b/sip/res/values-is-rIS/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Valfrjálsar stillingar"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Notandanafn til auðkenningar"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Notandanafn notað til auðkenningar"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ekki valið>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ekki valið>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ekki valið>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ekki valið>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Sama og notandanafnið>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Valfrjálst>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Snertu til að sýna allt"</string>
diff --git a/sip/res/values-it/strings.xml b/sip/res/values-it/strings.xml
index ab04f42..1915746 100644
--- a/sip/res/values-it/strings.xml
+++ b/sip/res/values-it/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Impostazioni facoltative"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nome utente per autenticazione"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nome utente utilizzato per l\'autenticazione"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Non impostato>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Non impostato>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Non impostato>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Non impostato>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Uguale al nome utente>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Facoltativo>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Tocca per mostrare tutto"</string>
diff --git a/sip/res/values-iw/strings.xml b/sip/res/values-iw/strings.xml
index 7505f1d..f358c2d 100644
--- a/sip/res/values-iw/strings.xml
+++ b/sip/res/values-iw/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"הגדרות אופציונליות"</string>
<string name="auth_username_title" msgid="8262491689004708265">"שם משתמש לאימות"</string>
<string name="auth_username_summary" msgid="941160241371436473">"שם משתמש המשמש לאימות"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<לא הוגדר>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<לא מוגדר>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<לא מוגדרת>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<לא מוגדרת>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<זהה לשם משתמש>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<אופציונלי>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"גע כדי להציג את הכל"</string>
diff --git a/sip/res/values-ja/strings.xml b/sip/res/values-ja/strings.xml
index 8487e9e..3e48194 100644
--- a/sip/res/values-ja/strings.xml
+++ b/sip/res/values-ja/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"オプション設定"</string>
<string name="auth_username_title" msgid="8262491689004708265">"認証ユーザー名"</string>
<string name="auth_username_summary" msgid="941160241371436473">"認証に使用するユーザー名"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<未設定>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<未設定>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<未設定>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<未設定>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<ユーザー名と同じ>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<オプション>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷すべて表示"</string>
diff --git a/sip/res/values-ka-rGE/strings.xml b/sip/res/values-ka-rGE/strings.xml
index 87eaa97..3559f65 100644
--- a/sip/res/values-ka-rGE/strings.xml
+++ b/sip/res/values-ka-rGE/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"არასავალდებულო პარამეტრები"</string>
<string name="auth_username_title" msgid="8262491689004708265">"ავტორიზაციის მომხმარებლის სახელი"</string>
<string name="auth_username_summary" msgid="941160241371436473">"ავტორიზაციისათვის გამოყენებული მომხმარებლის სახელი"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<არ არის დაყენებული>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<არ არის დაყენებული>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<არ არის დაყენებული>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<არ არის დაყენებული>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<იგივეა, რაც მომხმარებლის სახელი>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<სურვილისამებრ>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ შეეხეთ ყველას საჩვენებლად"</string>
diff --git a/sip/res/values-kk-rKZ/strings.xml b/sip/res/values-kk-rKZ/strings.xml
index b07dacd..03eef64 100644
--- a/sip/res/values-kk-rKZ/strings.xml
+++ b/sip/res/values-kk-rKZ/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Қосымша параметрлер"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Аутентификациялау пайдаланушы аты"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Аутентификациялау үшін пайдаланылатын пайдаланушы аты"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Орнатылмаған>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Орнатылмаған>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Орнатылмаған>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Орнатылмаған>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Пайдаланушы атымен бірдей>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Міндетті емес>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Барлығын көрсету үшін түрту"</string>
diff --git a/sip/res/values-km-rKH/strings.xml b/sip/res/values-km-rKH/strings.xml
index cd5a2d9..2936007 100644
--- a/sip/res/values-km-rKH/strings.xml
+++ b/sip/res/values-km-rKH/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"ការកំណត់ជាជម្រើស"</string>
<string name="auth_username_title" msgid="8262491689004708265">"ឈ្មោះអ្នកប្រើប្រាស់សម្រាប់ផ្ទៀងផ្ទាត់"</string>
<string name="auth_username_summary" msgid="941160241371436473">"ឈ្មោះអ្នកប្រើប្រាស់ដែលបានប្រើសម្រាប់ផ្ទៀងផ្ទាត់"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<មិនបានកំណត់>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<មិនបានកំណត់>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<មិនបានកំណត់>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<មិនបានកំណត់>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<ដូចឈ្មោះអ្នកប្រើ>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<ជាជម្រើស>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"ប៉ះ ▷ ដើម្បីបង្ហាញទាំងអស់"</string>
diff --git a/sip/res/values-kn-rIN/strings.xml b/sip/res/values-kn-rIN/strings.xml
index 5698355..c2b9583 100644
--- a/sip/res/values-kn-rIN/strings.xml
+++ b/sip/res/values-kn-rIN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"ಐಚ್ಛಿಕ ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
<string name="auth_username_title" msgid="8262491689004708265">"ದೃಢೀಕರಣ ಬಳಕೆದಾರಹೆಸರು"</string>
<string name="auth_username_summary" msgid="941160241371436473">"ದೃಢೀಕರಣಕ್ಕಾಗಿ ಬಳಕೆದಾರ ಹೆಸರನ್ನು ಬಳಸಲಾಗಿದೆ"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<ಹೊಂದಿಸಿಲ್ಲ>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<ಹೊಂದಿಸಿಲ್ಲ>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<ಹೊಂದಿಸಿಲ್ಲ>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<ಹೊಂದಿಸಿಲ್ಲ>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<ಬಳಕೆದಾರ ಹೆಸರಿನಂತೆ>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<ಐಚ್ಛಿಕ>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ ಎಲ್ಲವನ್ನೂ ತೋರಿಸಲು ಸ್ಪರ್ಶಿಸಿ"</string>
diff --git a/sip/res/values-ko/strings.xml b/sip/res/values-ko/strings.xml
index afdb473..3274adc 100644
--- a/sip/res/values-ko/strings.xml
+++ b/sip/res/values-ko/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"설정(선택사항)"</string>
<string name="auth_username_title" msgid="8262491689004708265">"인증 사용자 이름"</string>
<string name="auth_username_summary" msgid="941160241371436473">"인증에 사용된 사용자 이름"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<설정 안됨>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<설정 안됨>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<설정 안됨>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<설정 안됨>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<사용자 이름과 동일>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<선택사항>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ 모두 표시하려면 터치"</string>
diff --git a/sip/res/values-ky-rKG/strings.xml b/sip/res/values-ky-rKG/strings.xml
index 5f22df1..afde29d 100644
--- a/sip/res/values-ky-rKG/strings.xml
+++ b/sip/res/values-ky-rKG/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Кошумча жөндөөлөр"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Аныктыкты текшерүүчү колдонуучунун ысымы"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Колдонуучунун ысымы аныктыкты текшерүү үчүн колдонулат"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Коюлган эмес>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Коюлган эмес>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Коюлган эмес>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Коюлган эмес>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Колдонуучунун ысымына окшош>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Кошумча>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Бардыгын көрсөтүү үчүн тийип коюңуз"</string>
diff --git a/sip/res/values-lo-rLA/strings.xml b/sip/res/values-lo-rLA/strings.xml
index e5921be..f163f0a 100644
--- a/sip/res/values-lo-rLA/strings.xml
+++ b/sip/res/values-lo-rLA/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"ການຕັ້ງຄ່າທາງເລືອກເສີມ"</string>
<string name="auth_username_title" msgid="8262491689004708265">"ຊື່ຜູ່ໃຊ້ສຳລັບການພິສູດຢືນຢັນໂຕ"</string>
<string name="auth_username_summary" msgid="941160241371436473">"ຊື່ຜູ່ໃຊ້ເພື່ອການພິສູດຢືນຢັນໂຕ"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<ຍັງບໍ່ໄດ້ຕັ້ງ>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<ບໍ່ໄດ້ຕັ້ງ>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<ບໍ່ໄດ້ຕັ້ງ>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<ບໍ່ໄດ້ຕັ້ງ>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<ອັນດຽວກັບຊື່ຜູ່ໃຊ້>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<ໂຕເລືອກເສີມ>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ ແຕະເພື່ອສະແດງທັງໝົດ"</string>
diff --git a/sip/res/values-lt/strings.xml b/sip/res/values-lt/strings.xml
index da52cd5..2d3f53f 100644
--- a/sip/res/values-lt/strings.xml
+++ b/sip/res/values-lt/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Pasirenkami nustatymai"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Tapatybės nustatymo naudotojo vardas"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Tapatybei nustatyti naudotas naudotojo vardas"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nenustatyta>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nenustatyta>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nenustatyta>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nenustatyta>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Kaip naudotojo vardas>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Pasirenkama>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Jei norite viską parodyti, palieskite"</string>
diff --git a/sip/res/values-lv/strings.xml b/sip/res/values-lv/strings.xml
index 48d6eb0..345c5b2 100644
--- a/sip/res/values-lv/strings.xml
+++ b/sip/res/values-lv/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Neobligāti iestatījumi"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Autentifikācijai izmantotais lietotājvārds"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Autentifikācijai izmantotais lietotājvārds"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nav iestatīts>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nav iestatīts>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nav iestatīts>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nav iestatīts>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Tāds pats kā lietotājvārds>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Neobligāti>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Pieskarieties, lai rādītu visu"</string>
diff --git a/sip/res/values-mk-rMK/strings.xml b/sip/res/values-mk-rMK/strings.xml
index 0f843c4..ea8107b 100644
--- a/sip/res/values-mk-rMK/strings.xml
+++ b/sip/res/values-mk-rMK/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Изборни поставки"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Корисничко име за автентикација"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Корисничко име што се користи за автентикација"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Нема поставка>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Не е поставено>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Не е поставено>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Не е поставено>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Исто како корисничкото име>"</string>
<string name="optional_summary" msgid="2363105560396317624">"Изборно"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Допрете за да се прикажат сите"</string>
diff --git a/sip/res/values-ml-rIN/strings.xml b/sip/res/values-ml-rIN/strings.xml
index 18a8ed1..071152d 100644
--- a/sip/res/values-ml-rIN/strings.xml
+++ b/sip/res/values-ml-rIN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"ഓപ്ഷണൽ ക്രമീകരണങ്ങൾ"</string>
<string name="auth_username_title" msgid="8262491689004708265">"പ്രാമാണീകരണ ഉപയോക്തൃനാമം"</string>
<string name="auth_username_summary" msgid="941160241371436473">"പ്രാമാണീകരണത്തിന് ഉപയോഗിച്ച ഉപയോക്തൃനാമം"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<സജ്ജീകരിച്ചിട്ടില്ല>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<ക്രമീകരിച്ചിട്ടില്ല>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<ക്രമീകരിച്ചിട്ടില്ല>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<ക്രമീകരിച്ചിട്ടില്ല>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<ഉപയോക്തൃനാമത്തിന് സമാനം>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<ഓപ്ഷണൽ>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ എല്ലാം കാണിക്കാൻ സ്പർശിക്കുക"</string>
diff --git a/sip/res/values-mn-rMN/strings.xml b/sip/res/values-mn-rMN/strings.xml
index 2fa0955..1dc5c64 100644
--- a/sip/res/values-mn-rMN/strings.xml
+++ b/sip/res/values-mn-rMN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Сонголтын тохиргоо"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Гэрчлэлийн хэрэглэгчийн нэр"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Гэрчлэлд ашигласан хэрэглэгчийн нэр"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Тохируулаагүй>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Тохируулаагүй>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Тохируулаагүй>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Тохируулаагүй>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Хэрэглэгчийн нэртэй адил>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Сонголтын>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Бүгдийг харуулахын тулд хүрнэ үү"</string>
diff --git a/sip/res/values-mr-rIN/strings.xml b/sip/res/values-mr-rIN/strings.xml
index 9148071..49f158c 100644
--- a/sip/res/values-mr-rIN/strings.xml
+++ b/sip/res/values-mr-rIN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"पर्यायी सेटिंग्ज"</string>
<string name="auth_username_title" msgid="8262491689004708265">"प्रमाणीकरण वापरकर्तानाव"</string>
<string name="auth_username_summary" msgid="941160241371436473">"प्रमाणीकरणासाठी वापरकर्तानाव वापरले"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<सेट नाही>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<सेट नाही>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<सेट नाही>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<सेट नाही>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<वापरकर्तानावासमान>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<पर्यायी>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ सर्व दर्शविण्यासाठी स्पर्श करा"</string>
diff --git a/sip/res/values-ms-rMY/strings.xml b/sip/res/values-ms-rMY/strings.xml
index 2ac1040..e147623 100644
--- a/sip/res/values-ms-rMY/strings.xml
+++ b/sip/res/values-ms-rMY/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Tetapan pilihan"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nama pengguna pengesahan"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nama pengguna yang digunakan untuk pengesahan"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Tidak ditetapkan>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Tidak ditetapkan>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Tidak ditetapkan>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Tidak ditetapkan>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Sama dengan nama pengguna>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Pilihan>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Sentuh untuk menunjukkan semua"</string>
diff --git a/sip/res/values-my-rMM/strings.xml b/sip/res/values-my-rMM/strings.xml
index 03d6257..e893b90 100644
--- a/sip/res/values-my-rMM/strings.xml
+++ b/sip/res/values-my-rMM/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"ရွေးနိုင်သော ဆက်တင်များ"</string>
<string name="auth_username_title" msgid="8262491689004708265">"အသုံးပြုသူ အမည် အထောက်အထားကို စိစစ်ခြင်း"</string>
<string name="auth_username_summary" msgid="941160241371436473">"အသုံးပြုသူ အမည်ကို အထောက်အထား စိစစ်ရန် သုံးခဲ့"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<သတ်မှတ်မထားပါ>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<သတ်မှတ်မထားပါ>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<သတ်မှတ်မထားပါ>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<သတ်မှတ်မထားပါ>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<အသုံးပြုသူ အမည်နှင့် တူညီသော>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<လိုချင်မှ လုပ်ရန်>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ အားလုံးပြရန် ထိပါ"</string>
diff --git a/sip/res/values-nb/strings.xml b/sip/res/values-nb/strings.xml
index 57bff86..160fbb1 100644
--- a/sip/res/values-nb/strings.xml
+++ b/sip/res/values-nb/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Valgfrie innstillinger"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Brukernavn for autentisering"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Brukernavn som brukes til autentisering"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ikke angitt>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ikke angitt>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ikke angitt>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ikke angitt>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Samme som brukernavn>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Valgfritt>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Trykk for å vise alle"</string>
diff --git a/sip/res/values-ne-rNP/strings.xml b/sip/res/values-ne-rNP/strings.xml
index d2c2223..727ba5a 100644
--- a/sip/res/values-ne-rNP/strings.xml
+++ b/sip/res/values-ne-rNP/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"वैकल्पिक सेटिङहरू"</string>
<string name="auth_username_title" msgid="8262491689004708265">"प्रमाणीकरणको एक-पटके पाठ सन्देश"</string>
<string name="auth_username_summary" msgid="941160241371436473">"प्रमाणीकरणको लागि एक-पटके पाठ सन्देश प्रयोग भएको"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<सेट गरिएको छैन>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<सेट गरिएको छैन>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<सेट गरिएको छैन>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<सेट गरिएको छैन>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<एक-पटके पाठ सन्देश जस्तै>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<वैकल्पिकgt;"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ छोएर सबै देखाउनुहोस्"</string>
diff --git a/sip/res/values-nl/strings.xml b/sip/res/values-nl/strings.xml
index 7375c4b..1c24e0e 100644
--- a/sip/res/values-nl/strings.xml
+++ b/sip/res/values-nl/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Optionele instellingen"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Gebruikersnaam voor verificatie"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Gebruikersnaam die voor de verificatie wordt gebruikt"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Niet ingesteld>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Niet ingesteld>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Niet ingesteld>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Niet ingesteld>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Gelijk aan gebruikersnaam>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Optioneel>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Tikken om alles weer te geven"</string>
diff --git a/sip/res/values-pa-rIN/strings.xml b/sip/res/values-pa-rIN/strings.xml
index 3a9755d..8426a72 100644
--- a/sip/res/values-pa-rIN/strings.xml
+++ b/sip/res/values-pa-rIN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"ਵਿਕਲਪਕ ਸੈਟਿੰਗਾਂ"</string>
<string name="auth_username_title" msgid="8262491689004708265">"ਪ੍ਰਮਾਣੀਕਰਨ ਵਰਤੋਂਕਾਰ ਨਾਮ"</string>
<string name="auth_username_summary" msgid="941160241371436473">"ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਵਰਤਿਆ ਗਿਆ ਵਰਤੋਂਕਾਰ ਨਾਮ"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<ਸੈੱਟ ਨਹੀਂ ਕੀਤਾ>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<ਸੈੱਟ ਨਹੀਂ>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<ਸੈੱਟ ਨਹੀਂ>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<ਸੈੱਟ ਨਹੀਂ>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<ਉਹੀ ਹੈ ਜੋ ਵਰਤੋਂਕਾਰ ਨਾਮ ਹੈ>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<ਵਿਕਲਪਕ>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ ਸਾਰੇ ਦਿਖਾਉਣ ਲਈ ਸਪੱਰਸ਼ ਕਰੋ"</string>
diff --git a/sip/res/values-pl/strings.xml b/sip/res/values-pl/strings.xml
index 651af45..d41a95e 100644
--- a/sip/res/values-pl/strings.xml
+++ b/sip/res/values-pl/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Ustawienia opcjonalne"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nazwa do uwierzytelniania"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nazwa użytkownika używana do uwierzytelniania"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nie ustawiono>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nie ustawiono>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nie ustawiono>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nie ustawiono>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Taka sama jak nazwa użytkownika>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opcjonalny>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Dotknij, by wyświetlić wszystkie ustawienia"</string>
diff --git a/sip/res/values-pt-rPT/strings.xml b/sip/res/values-pt-rPT/strings.xml
index 81652de..912941d 100644
--- a/sip/res/values-pt-rPT/strings.xml
+++ b/sip/res/values-pt-rPT/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Definições opcionais"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nome de utilizador para autenticação"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nome de utilizador usado para autenticação"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Não definido>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Não definido>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Não definido>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Não definido>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Igual ao nome de utilizador>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opcional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Toque para mostrar tudo"</string>
diff --git a/sip/res/values-pt/strings.xml b/sip/res/values-pt/strings.xml
index 21c89a9..29f0d9f 100644
--- a/sip/res/values-pt/strings.xml
+++ b/sip/res/values-pt/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Configurações opcionais"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nome de usuário da autenticação"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Nome de usuário utilizado para autenticação"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Não definido>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Não definido>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Não definido>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Não definido>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Igual ao nome de usuário>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opcional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Toque para mostrar todas"</string>
diff --git a/sip/res/values-ro/strings.xml b/sip/res/values-ro/strings.xml
index 158be24..2a92257 100644
--- a/sip/res/values-ro/strings.xml
+++ b/sip/res/values-ro/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Setări opționale"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Nume de utilizator pentru autentificare"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Numele de utilizator folosit pentru autentificare"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nesetat>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nesetat>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nesetat>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nesetat>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Identic cu numele de utilizator>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opțional>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Atingeți pentru a afișa tot"</string>
diff --git a/sip/res/values-ru/strings.xml b/sip/res/values-ru/strings.xml
index ea678c8..a950823 100644
--- a/sip/res/values-ru/strings.xml
+++ b/sip/res/values-ru/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Расширенные настройки"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Имя пользователя"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Имя пользователя для аутентификации"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Не задано>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Не задано>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Не задано>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Не задано>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Совпадает с именем пользователя>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Необязательно>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Нажмите, чтобы показать все"</string>
diff --git a/sip/res/values-si-rLK/strings.xml b/sip/res/values-si-rLK/strings.xml
index c710b8b..541c196 100644
--- a/sip/res/values-si-rLK/strings.xml
+++ b/sip/res/values-si-rLK/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"වෛකල්පිත සැකසුම්"</string>
<string name="auth_username_title" msgid="8262491689004708265">"සත්යාපන පරිශීලක නාමය"</string>
<string name="auth_username_summary" msgid="941160241371436473">"සත්යාපනය සඳහා භාවිතා වන පරිශීලක නාමය"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<පිහිටුවා නැත>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<පිහිටුවා නැත>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<පිහිටුවා නැත>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<පිහිටුවා නැත>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<පරිශීලක නාමය වාගේම>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<වෛකල්පිත>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ සියල්ල පෙන්වීමට ස්පර්ශ කරන්න"</string>
diff --git a/sip/res/values-sk/strings.xml b/sip/res/values-sk/strings.xml
index a278b55..96cf144 100644
--- a/sip/res/values-sk/strings.xml
+++ b/sip/res/values-sk/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Voliteľné nastavenia"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Používateľské meno na overenie"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Používateľské meno použité na overenie"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Nenastavené>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Nenastavené>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Nenastavené>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Nenastavené>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Rovnaké ako používateľské meno>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Voliteľné>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Klepnutím všetko zobrazíte"</string>
diff --git a/sip/res/values-sl/strings.xml b/sip/res/values-sl/strings.xml
index ae994e3..c9c6d57 100644
--- a/sip/res/values-sl/strings.xml
+++ b/sip/res/values-sl/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Izbirne nastavitve"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Uporabniško ime za preverjanje pristnosti"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Uporabniško ime za preverjanje pristnosti"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ni nastavljeno>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ni nastavljeno>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ni nastavljeno>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ni nastavljeno>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Enako kot uporabniško ime>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Izbirno>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Dotaknite se, da prikažete vse"</string>
diff --git a/sip/res/values-sq-rAL/strings.xml b/sip/res/values-sq-rAL/strings.xml
index 3e42c58..8118e61 100644
--- a/sip/res/values-sq-rAL/strings.xml
+++ b/sip/res/values-sq-rAL/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Cilësimet opsionale"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Emri i përdoruesit për vërtetim"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Emri i përdoruesit i përdorur për vërtetim"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<I pavendosur>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<I pavendosur>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<I pavendosur>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<I pavendosur>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Njësoj si emri i përdoruesit>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Jo e detyrueshme>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Prek për t\'i shfaqur të gjitha"</string>
diff --git a/sip/res/values-sr/strings.xml b/sip/res/values-sr/strings.xml
index 0c6b48a..2ac09e3 100644
--- a/sip/res/values-sr/strings.xml
+++ b/sip/res/values-sr/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Опционална подешавања"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Корисничко име за потврду идентитета"</string>
<string name="auth_username_summary" msgid="941160241371436473">"За потврду идентитета користи се корисничко име"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Није подешено>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Није подешено>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Није подешенa>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Није подешенa>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Исто као корисничко име>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Опционално>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Додирните да бисте приказали све"</string>
diff --git a/sip/res/values-sv/strings.xml b/sip/res/values-sv/strings.xml
index f08ebbc..78947b1 100644
--- a/sip/res/values-sv/strings.xml
+++ b/sip/res/values-sv/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Valfria inställningar"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Användarnamn vid autentisering"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Användarnamn som används vid autentisering"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Har inte angetts>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Inte inställd>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Inte inställd>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Inte inställd>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Samma som användarnamn>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Valfritt>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Tryck om du vill visa alla"</string>
diff --git a/sip/res/values-sw/strings.xml b/sip/res/values-sw/strings.xml
index 64f2101..d18833b 100644
--- a/sip/res/values-sw/strings.xml
+++ b/sip/res/values-sw/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Mipangilio ya hiari"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Jina la mtumiaji la uthibitishaji"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Jina la mtumiaji hutumika kwa uthibitishaji"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Haijawekwa>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Haijawekwa>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Haijawekwa>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Haijawekwa>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Sawa na jina la mtumiaji>"</string>
<string name="optional_summary" msgid="2363105560396317624">"&lt Ni hiari >"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Gusa ili uonyeshe yote"</string>
diff --git a/sip/res/values-ta-rIN/strings.xml b/sip/res/values-ta-rIN/strings.xml
index b31891e..9ba7cfc 100644
--- a/sip/res/values-ta-rIN/strings.xml
+++ b/sip/res/values-ta-rIN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"விருப்ப அமைப்பு"</string>
<string name="auth_username_title" msgid="8262491689004708265">"அங்கீகாரப் பயனர்பெயர்"</string>
<string name="auth_username_summary" msgid="941160241371436473">"அங்கீகரிப்பிற்குப் பயன்படுத்தப்படும் பயனர்பெயர்"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<அமைக்கப்படவில்லை>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<அமைக்கப்படவில்லை>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<அமைக்கப்படவில்லை>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<அமைக்கப்படவில்லை>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<பயனர்பெயர் போன்றது>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<விரும்பினால்>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ எல்லாவற்றையும் காட்ட தொடவும்"</string>
diff --git a/sip/res/values-te-rIN/strings.xml b/sip/res/values-te-rIN/strings.xml
index 4f5cef3..80a745b 100644
--- a/sip/res/values-te-rIN/strings.xml
+++ b/sip/res/values-te-rIN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"ఐచ్ఛిక సెట్టింగ్లు"</string>
<string name="auth_username_title" msgid="8262491689004708265">"ప్రామాణీకరణ వినియోగదారు పేరు"</string>
<string name="auth_username_summary" msgid="941160241371436473">"ప్రామాణీకరణ కోసం వినియోగదారు పేరు ఉపయోగించబడింది"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<సెట్ చేయలేదు>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<సెట్ చేయలేదు>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<సెట్ చేయలేదు>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<సెట్ చేయలేదు>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<వినియోగదారు పేరు మాదిరే>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<ఐచ్ఛికం>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ అన్నీ చూపడానికి తాకండి"</string>
diff --git a/sip/res/values-th/strings.xml b/sip/res/values-th/strings.xml
index 92e1a3f..1616cec 100644
--- a/sip/res/values-th/strings.xml
+++ b/sip/res/values-th/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"การตั้งค่าที่ไม่บังคับ"</string>
<string name="auth_username_title" msgid="8262491689004708265">"ชื่อผู้ใช้สำหรับตรวจสอบสิทธิ์"</string>
<string name="auth_username_summary" msgid="941160241371436473">"ชื่อผู้ใช้ที่ใช้ในการตรวจสอบสิทธิ์"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<ไม่ได้ตั้งค่า>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<ไม่ได้ตั้งค่า>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<ไม่ได้ตั้งค่า>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<ไม่ได้ตั้งค่า>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<เหมือนกับชื่อผู้ใช้>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<ไม่บังคับ>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ แตะเพื่อแสดงทั้งหมด"</string>
diff --git a/sip/res/values-tl/strings.xml b/sip/res/values-tl/strings.xml
index a2a9e82..7b7060d 100644
--- a/sip/res/values-tl/strings.xml
+++ b/sip/res/values-tl/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Mga opsyonal na setting"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Username sa pagpapatunay"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Ginamit ang username para sa pagpapatunay"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Hindi nakatakda>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Hindi nakatakda>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Hindi nakatakda>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Hindi nakatakda>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Katulad ng username>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Opsyonal>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Pindutin upang ipakita lahat"</string>
diff --git a/sip/res/values-tr/strings.xml b/sip/res/values-tr/strings.xml
index 168eb79..ff52b4e 100644
--- a/sip/res/values-tr/strings.xml
+++ b/sip/res/values-tr/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"İsteğe bağlı ayarlar"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Kimlik doğrulama kullanıcı adı"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Kimlik doğrulama için kullanılan kullanıcı adı"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ayarlanmadı>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ayarlanmadı>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ayarlanmadı>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ayarlanmadı>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Kullanıcı adıyla aynı>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<İsteğe bağlı>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Tümünü görmek için dokunun"</string>
diff --git a/sip/res/values-uk/strings.xml b/sip/res/values-uk/strings.xml
index be20a10..b9d9e77 100644
--- a/sip/res/values-uk/strings.xml
+++ b/sip/res/values-uk/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Додаткові налаштування"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Ім’я користувача для автентифікації"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Ім’я користувача, використане для автентифікації"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Не встановлено>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Не встановлено>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Не встановлено>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Не встановлено>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Те саме, що й ім’я користувача>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Додатково>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Торкніться, щоб показати все"</string>
diff --git a/sip/res/values-ur-rPK/strings.xml b/sip/res/values-ur-rPK/strings.xml
index ccd53c6..8c070e2 100644
--- a/sip/res/values-ur-rPK/strings.xml
+++ b/sip/res/values-ur-rPK/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"اختیاری ترتیبات"</string>
<string name="auth_username_title" msgid="8262491689004708265">"توثیق کیلئے صارف نام"</string>
<string name="auth_username_summary" msgid="941160241371436473">"توثیق کیلئے استعمال کردہ صارف نام"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<سیٹ نہیں ہے>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<سیٹ نہیں ہے>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<سیٹ نہیں ہے>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<سیٹ نہیں ہے>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<بالکل وہی جو صارف نام ہے>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<اختیاری>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"◁ سبھی کو دکھانے کیلئے ٹچ کریں"</string>
diff --git a/sip/res/values-uz-rUZ/strings.xml b/sip/res/values-uz-rUZ/strings.xml
index e777336..3fb9145 100644
--- a/sip/res/values-uz-rUZ/strings.xml
+++ b/sip/res/values-uz-rUZ/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Kengaytirilgan sozlamalar"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Foydalanuvchi nomi"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Haqiqiylikni tekshirish uchun foydalanuvchi nomi"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ko‘rsatilmagan>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ko‘rsatilmagan>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ko‘rsatilmagan>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ko‘rsatilmagan>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Foydalanuvchi nomi bilan bir xil>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Ixtiyoriy>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Hammasini ko‘rsatish uchun bosing"</string>
diff --git a/sip/res/values-vi/strings.xml b/sip/res/values-vi/strings.xml
index df6cfde..0c545f2 100644
--- a/sip/res/values-vi/strings.xml
+++ b/sip/res/values-vi/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Cài đặt tùy chọn"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Tên người dùng xác thực"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Tên người dùng để xác thực"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Chưa đặt>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Chưa được đặt>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Chưa được đặt>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Chưa được đặt>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Giống như tên người dùng>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Tùy chọn>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Chạm để hiển thị tất cả"</string>
diff --git a/sip/res/values-zh-rCN/strings.xml b/sip/res/values-zh-rCN/strings.xml
index 625c4af..5ba209f 100644
--- a/sip/res/values-zh-rCN/strings.xml
+++ b/sip/res/values-zh-rCN/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"可选设置"</string>
<string name="auth_username_title" msgid="8262491689004708265">"身份验证用户名"</string>
<string name="auth_username_summary" msgid="941160241371436473">"用于验证身份的用户名"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<未设置>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<未设置>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<未设置>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<未设置>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<与用户名相同>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<可选>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ 触摸可全部显示"</string>
diff --git a/sip/res/values-zh-rHK/strings.xml b/sip/res/values-zh-rHK/strings.xml
index a62745b..49de353 100644
--- a/sip/res/values-zh-rHK/strings.xml
+++ b/sip/res/values-zh-rHK/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"可選設定"</string>
<string name="auth_username_title" msgid="8262491689004708265">"驗證使用者名稱"</string>
<string name="auth_username_summary" msgid="941160241371436473">"用於驗證的使用者名稱"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<未設定>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<未設定>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<未設定>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<未設定>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<與使用者名稱相同>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<非必填>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ 輕觸即可全部顯示"</string>
diff --git a/sip/res/values-zh-rTW/strings.xml b/sip/res/values-zh-rTW/strings.xml
index 7f25be7..bdc3961 100644
--- a/sip/res/values-zh-rTW/strings.xml
+++ b/sip/res/values-zh-rTW/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"選用設定"</string>
<string name="auth_username_title" msgid="8262491689004708265">"驗證使用者名稱"</string>
<string name="auth_username_summary" msgid="941160241371436473">"用於進行驗證的使用者名稱"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<未設定>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<未設定>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<未設定>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<未設定>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<與使用者名稱相同>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<選擇性>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ 輕觸即可全部顯示"</string>
diff --git a/sip/res/values-zu/strings.xml b/sip/res/values-zu/strings.xml
index 3a6b00a..dc9bbc0 100644
--- a/sip/res/values-zu/strings.xml
+++ b/sip/res/values-zu/strings.xml
@@ -61,7 +61,9 @@
<string name="advanced_settings" msgid="6622996380747040711">"Izilungiselelo ongazikhetha"</string>
<string name="auth_username_title" msgid="8262491689004708265">"Igama lomsebenzisi lokufakazela ubuqiniso"</string>
<string name="auth_username_summary" msgid="941160241371436473">"Igama lomsebenzisi elisetshenziselwa ukufakazela ubuqiniso"</string>
- <string name="default_preference_summary" msgid="1979249643719483249">"<Ayisethiwe>"</string>
+ <string name="default_preference_summary_username" msgid="8404717434312826082">"<Ayisethiwe>"</string>
+ <string name="default_preference_summary_password" msgid="4464464672997027904">"<Ayisethiwe>"</string>
+ <string name="default_preference_summary_domain_address" msgid="4871971710197441673">"<Ayisethiwe>"</string>
<string name="display_name_summary" msgid="7155076491675565407">"<Ifana negama lomsebenzisi>"</string>
<string name="optional_summary" msgid="2363105560396317624">"<Ongakukhetha>"</string>
<string name="advanced_settings_show" msgid="7838761602853998622">"▷ Thinta ukuze ubonise konke"</string>
diff --git a/sip/res/values/strings.xml b/sip/res/values/strings.xml
index 6ac7c8d..d515736 100644
--- a/sip/res/values/strings.xml
+++ b/sip/res/values/strings.xml
@@ -115,8 +115,12 @@
<!-- Help text of the auth_username field. [CHAR LIMIT=NONE] -->
<string name="auth_username_summary">Username used for authentication</string>
- <!-- Initial status of the preferences is '<Not set>'. [CHAR LIMIT=NONE] -->
- <string name="default_preference_summary"><Not set></string>
+ <!-- Initial status of the username preference is '<Not set>'. [CHAR LIMIT=NONE] -->
+ <string name="default_preference_summary_username"><Not set></string>
+ <!-- Initial status of the password preference is '<Not set>'. [CHAR LIMIT=NONE] -->
+ <string name="default_preference_summary_password"><Not set></string>
+ <!-- Initial status of the domain address preference is '<Not set>'. [CHAR LIMIT=NONE] -->
+ <string name="default_preference_summary_domain_address"><Not set></string>
<!-- Default value for the display-name preference summary. [CHAR LIMIT=NONE] -->
<string name="display_name_summary"><Same as username></string>
<!-- Default value for the outbound-proxy-address preference summary. [CHAR LIMIT=NONE] -->
diff --git a/sip/res/xml/sip_edit.xml b/sip/res/xml/sip_edit.xml
index 15e5ce1..58a8a92 100644
--- a/sip/res/xml/sip_edit.xml
+++ b/sip/res/xml/sip_edit.xml
@@ -22,7 +22,7 @@
android:key="@string/username"
android:title="@string/username_title"
android:dialogTitle="@string/username_title"
- android:summary="@string/default_preference_summary"
+ android:summary="@string/default_preference_summary_username"
android:persistent="false"
android:singleLine="true"
android:inputType="textNoSuggestions"/>
@@ -32,7 +32,7 @@
android:title="@string/password_title"
android:dialogTitle="@string/password_title"
android:password="true"
- android:summary="@string/default_preference_summary"
+ android:summary="@string/default_preference_summary_password"
android:persistent="false"
android:singleLine="true"/>
@@ -40,7 +40,7 @@
android:key="@string/domain_address"
android:title="@string/domain_address_title"
android:dialogTitle="@string/domain_address_title"
- android:summary="@string/default_preference_summary"
+ android:summary="@string/default_preference_summary_domain_address"
android:persistent="false"
android:singleLine="true"
android:inputType="textNoSuggestions"/>
diff --git a/sip/src/com/android/services/telephony/sip/SipEditor.java b/sip/src/com/android/services/telephony/sip/SipEditor.java
index fa07647..27941c3 100644
--- a/sip/src/com/android/services/telephony/sip/SipEditor.java
+++ b/sip/src/com/android/services/telephony/sip/SipEditor.java
@@ -103,9 +103,10 @@
}
enum PreferenceKey {
- Username(R.string.username, 0, R.string.default_preference_summary),
- Password(R.string.password, 0, R.string.default_preference_summary),
- DomainAddress(R.string.domain_address, 0, R.string.default_preference_summary),
+ Username(R.string.username, 0, R.string.default_preference_summary_username),
+ Password(R.string.password, 0, R.string.default_preference_summary_password),
+ DomainAddress(R.string.domain_address, 0,
+ R.string.default_preference_summary_domain_address),
DisplayName(R.string.display_name, 0, R.string.display_name_summary),
ProxyAddress(R.string.proxy_address, 0, R.string.optional_summary),
Port(R.string.port, R.string.default_port, R.string.default_port),
@@ -293,7 +294,7 @@
*
* @param p The {@link SipProfile} to delete.
*/
- private void deleteAndUnregisterProfile(SipProfile p) {
+ private void deleteAndUnregisterProfile(SipProfile p) throws IOException {
if (p == null) return;
mProfileDb.deleteProfile(p);
mSipAccountRegistry.stopSipService(this, p.getProfileName());
diff --git a/sip/src/com/android/services/telephony/sip/SipProfileDb.java b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
index e7b201b..bb1c7ec 100644
--- a/sip/src/com/android/services/telephony/sip/SipProfileDb.java
+++ b/sip/src/com/android/services/telephony/sip/SipProfileDb.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.net.sip.SipProfile;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.Log;
import java.io.File;
@@ -66,9 +67,13 @@
mSipPreferences = new SipPreferences(mContext);
}
- public void deleteProfile(SipProfile p) {
+ public void deleteProfile(SipProfile p) throws IOException {
synchronized(SipProfileDb.class) {
- deleteProfile(new File(mProfilesDirectory + p.getProfileName()));
+ File profileFile = new File(mProfilesDirectory, p.getProfileName());
+ if (!isChild(new File(mProfilesDirectory), profileFile)) {
+ throw new IOException("Invalid Profile Credentials!");
+ }
+ deleteProfile(profileFile);
if (mProfilesCount < 0) retrieveSipProfileListInternal();
}
}
@@ -93,7 +98,10 @@
public void saveProfile(SipProfile p) throws IOException {
synchronized(SipProfileDb.class) {
if (mProfilesCount < 0) retrieveSipProfileListInternal();
- File f = new File(mProfilesDirectory + p.getProfileName());
+ File f = new File(mProfilesDirectory, p.getProfileName());
+ if (!isChild(new File(mProfilesDirectory), f)) {
+ throw new IOException("Invalid Profile Credentials!");
+ }
if (!f.exists()) f.mkdirs();
AtomicFile atomicFile = new AtomicFile(new File(f, PROFILE_OBJ_FILE));
FileOutputStream fos = null;
@@ -173,4 +181,19 @@
private static void log(String msg) {
Log.d(SipUtil.LOG_TAG, PREFIX + msg);
}
+
+ /**
+ * Verifies that the file is a direct child of the base directory.
+ */
+ private boolean isChild(File base, File file) {
+ if (base == null || file == null) {
+ return false;
+ }
+ if (!base.equals(file.getAbsoluteFile().getParentFile())) {
+ Log.w(SipUtil.LOG_TAG, "isChild, file is not a child of the base dir.");
+ EventLog.writeEvent(0x534e4554, "31530456", -1, "");
+ return false;
+ }
+ return true;
+ }
}
diff --git a/sip/src/com/android/services/telephony/sip/SipUtil.java b/sip/src/com/android/services/telephony/sip/SipUtil.java
index 3678c46..cf03dd3 100644
--- a/sip/src/com/android/services/telephony/sip/SipUtil.java
+++ b/sip/src/com/android/services/telephony/sip/SipUtil.java
@@ -164,7 +164,12 @@
}
Log.i(LOG_TAG, "(Migration) Deleting SIP profile: " +
profileToMove.getProfileName());
- dbDeStorage.deleteProfile(profileToMove);
+ try {
+ dbDeStorage.deleteProfile(profileToMove);
+ } catch (IOException e) {
+ Log.w(LOG_TAG, "Error Deleting file: " +
+ profileToMove.getProfileName(), e);
+ }
}
}
// Delete supporting structures if they exist
diff --git a/src/com/android/phone/Assert.java b/src/com/android/phone/Assert.java
new file mode 100644
index 0000000..143e66f
--- /dev/null
+++ b/src/com/android/phone/Assert.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.os.Looper;
+
+/**
+ * Assertions which will result in program termination.
+ */
+public class Assert {
+
+ private static Boolean sIsMainThreadForTest;
+
+ public static void isTrue(boolean condition) {
+ if (!condition) {
+ throw new AssertionError("Expected condition to be true");
+ }
+ }
+
+ public static void isMainThread() {
+ if (sIsMainThreadForTest != null) {
+ isTrue(sIsMainThreadForTest);
+ return;
+ }
+ isTrue(Looper.getMainLooper().equals(Looper.myLooper()));
+ }
+
+ public static void isNotMainThread() {
+ if (sIsMainThreadForTest != null) {
+ isTrue(!sIsMainThreadForTest);
+ return;
+ }
+ isTrue(!Looper.getMainLooper().equals(Looper.myLooper()));
+ }
+
+ public static void fail() {
+ throw new AssertionError("Fail");
+ }
+
+ /**
+ * Override the main thread status for tests. Set to null to revert to normal behavior
+ */
+ @NeededForTesting
+ public static void setIsMainThreadForTesting(Boolean isMainThread) {
+ sIsMainThreadForTest = isMainThread;
+ }
+}
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index d74558f..111e263 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -40,6 +40,7 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
+import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -185,6 +186,24 @@
mTelecomManager = TelecomManager.from(this);
}
+ private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (DBG) log("PhoneStateListener onCallStateChanged: state is " + state);
+ if (mEnableVideoCalling != null) {
+ mEnableVideoCalling.setEnabled(state == TelephonyManager.CALL_STATE_IDLE);
+ }
+ }
+ };
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ TelephonyManager telephonyManager =
+ (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE);
+ }
+
@Override
protected void onResume() {
super.onResume();
@@ -198,6 +217,7 @@
TelephonyManager telephonyManager =
(TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
+ telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
Preference phoneAccountSettingsPreference = findPreference(PHONE_ACCOUNT_SETTINGS_KEY);
if (telephonyManager.isMultiSimEnabled() || !SipUtil.isVoipSupported(mPhone.getContext())) {
@@ -262,7 +282,9 @@
}
}
- if (ImsManager.isVtEnabledByPlatform(mPhone.getContext())) {
+ if (ImsManager.isVtEnabledByPlatform(mPhone.getContext()) &&
+ ImsManager.isVtProvisionedOnDevice(mPhone.getContext()) &&
+ mPhone.mDcTracker.isDataEnabled(true)) {
boolean currentValue =
ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mPhone.getContext())
? PhoneGlobals.getInstance().phoneMgr.isVideoCallingEnabled(
@@ -300,7 +322,8 @@
} else {
prefSet.removePreference(wifiCallingSettings);
}
- } else if (!ImsManager.isWfcEnabledByPlatform(mPhone.getContext())) {
+ } else if (!ImsManager.isWfcEnabledByPlatform(mPhone.getContext()) ||
+ !ImsManager.isWfcProvisionedOnDevice(mPhone.getContext())) {
prefSet.removePreference(wifiCallingSettings);
} else {
int resId = com.android.internal.R.string.wifi_calling_off_summary;
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index df1a127..5a40322 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -665,9 +665,11 @@
// TODO: Check that the calling packages is privileged for subId specifically.
int privilegeStatus = TelephonyManager.from(mContext).checkCarrierPrivilegesForPackage(
callingPackageName);
+ // Requires the calling app to be either a carrier privileged app or
+ // system privileged app with MODIFY_PHONE_STATE permission.
if (privilegeStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
- throw new SecurityException(
- "Package is not privileged for subId=" + subId + ": " + callingPackageName);
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE,
+ "Require carrier privileges or MODIFY_PHONE_STATE permission.");
}
// This method should block until deleting has completed, so that an error which prevents us
@@ -689,6 +691,7 @@
switch (simState) {
case IccCardConstants.INTENT_VALUE_ICC_ABSENT:
case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR:
+ case IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED:
case IccCardConstants.INTENT_VALUE_ICC_UNKNOWN:
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CLEAR_CONFIG, phoneId, -1));
break;
diff --git a/src/com/android/phone/CellBroadcastSms.java b/src/com/android/phone/CellBroadcastSms.java
deleted file mode 100644
index 7428321..0000000
--- a/src/com/android/phone/CellBroadcastSms.java
+++ /dev/null
@@ -1,669 +0,0 @@
-/*
- * Copyright (C) 2009 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;
-
-import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.PreferenceScreen;
-import android.preference.PreferenceActivity;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.RILConstants;
-
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Message;
-import android.util.Log;
-
-
-/**
- * List of Phone-specific settings screens.
- */
-public class CellBroadcastSms extends PreferenceActivity
- implements Preference.OnPreferenceChangeListener{
- // debug data
- private static final String LOG_TAG = "CellBroadcastSms";
- private static final boolean DBG = false;
-
- //String keys for preference lookup
- private static final String BUTTON_ENABLE_DISABLE_BC_SMS_KEY =
- "button_enable_disable_cell_bc_sms";
- private static final String LIST_LANGUAGE_KEY =
- "list_language";
- private static final String BUTTON_EMERGENCY_BROADCAST_KEY =
- "button_emergency_broadcast";
- private static final String BUTTON_ADMINISTRATIVE_KEY =
- "button_administrative";
- private static final String BUTTON_MAINTENANCE_KEY =
- "button_maintenance";
- private static final String BUTTON_LOCAL_WEATHER_KEY =
- "button_local_weather";
- private static final String BUTTON_ATR_KEY =
- "button_atr";
- private static final String BUTTON_LAFS_KEY =
- "button_lafs";
- private static final String BUTTON_RESTAURANTS_KEY =
- "button_restaurants";
- private static final String BUTTON_LODGINGS_KEY =
- "button_lodgings";
- private static final String BUTTON_RETAIL_DIRECTORY_KEY =
- "button_retail_directory";
- private static final String BUTTON_ADVERTISEMENTS_KEY =
- "button_advertisements";
- private static final String BUTTON_STOCK_QUOTES_KEY =
- "button_stock_quotes";
- private static final String BUTTON_EO_KEY =
- "button_eo";
- private static final String BUTTON_MHH_KEY =
- "button_mhh";
- private static final String BUTTON_TECHNOLOGY_NEWS_KEY =
- "button_technology_news";
- private static final String BUTTON_MULTI_CATEGORY_KEY =
- "button_multi_category";
-
- private static final String BUTTON_LOCAL_GENERAL_NEWS_KEY =
- "button_local_general_news";
- private static final String BUTTON_REGIONAL_GENERAL_NEWS_KEY =
- "button_regional_general_news";
- private static final String BUTTON_NATIONAL_GENERAL_NEWS_KEY =
- "button_national_general_news";
- private static final String BUTTON_INTERNATIONAL_GENERAL_NEWS_KEY =
- "button_international_general_news";
-
- private static final String BUTTON_LOCAL_BF_NEWS_KEY =
- "button_local_bf_news";
- private static final String BUTTON_REGIONAL_BF_NEWS_KEY =
- "button_regional_bf_news";
- private static final String BUTTON_NATIONAL_BF_NEWS_KEY =
- "button_national_bf_news";
- private static final String BUTTON_INTERNATIONAL_BF_NEWS_KEY =
- "button_international_bf_news";
-
- private static final String BUTTON_LOCAL_SPORTS_NEWS_KEY =
- "button_local_sports_news";
- private static final String BUTTON_REGIONAL_SPORTS_NEWS_KEY =
- "button_regional_sports_news";
- private static final String BUTTON_NATIONAL_SPORTS_NEWS_KEY =
- "button_national_sports_news";
- private static final String BUTTON_INTERNATIONAL_SPORTS_NEWS_KEY =
- "button_international_sports_news";
-
- private static final String BUTTON_LOCAL_ENTERTAINMENT_NEWS_KEY =
- "button_local_entertainment_news";
- private static final String BUTTON_REGIONAL_ENTERTAINMENT_NEWS_KEY =
- "button_regional_entertainment_news";
- private static final String BUTTON_NATIONAL_ENTERTAINMENT_NEWS_KEY =
- "button_national_entertainment_news";
- private static final String BUTTON_INTERNATIONAL_ENTERTAINMENT_NEWS_KEY =
- "button_international_entertainment_news";
-
- //Class constants
- //These values are related to the C structs. See the comments in method
- //setCbSmsConfig for more information.
- private static final int NO_OF_SERVICE_CATEGORIES = 31;
- private static final int NO_OF_INTS_STRUCT_1 = 3;
- private static final int MAX_LENGTH_RESULT = NO_OF_SERVICE_CATEGORIES * NO_OF_INTS_STRUCT_1 + 1;
- //Handler keys
- private static final int MESSAGE_ACTIVATE_CB_SMS = 1;
- private static final int MESSAGE_GET_CB_SMS_CONFIG = 2;
- private static final int MESSAGE_SET_CB_SMS_CONFIG = 3;
-
- //UI objects
- private CheckBoxPreference mButtonBcSms;
-
- private ListPreference mListLanguage;
-
- private CheckBoxPreference mButtonEmergencyBroadcast;
- private CheckBoxPreference mButtonAdministrative;
- private CheckBoxPreference mButtonMaintenance;
- private CheckBoxPreference mButtonLocalWeather;
- private CheckBoxPreference mButtonAtr;
- private CheckBoxPreference mButtonLafs;
- private CheckBoxPreference mButtonRestaurants;
- private CheckBoxPreference mButtonLodgings;
- private CheckBoxPreference mButtonRetailDirectory;
- private CheckBoxPreference mButtonAdvertisements;
- private CheckBoxPreference mButtonStockQuotes;
- private CheckBoxPreference mButtonEo;
- private CheckBoxPreference mButtonMhh;
- private CheckBoxPreference mButtonTechnologyNews;
- private CheckBoxPreference mButtonMultiCategory;
-
- private CheckBoxPreference mButtonLocal1;
- private CheckBoxPreference mButtonRegional1;
- private CheckBoxPreference mButtonNational1;
- private CheckBoxPreference mButtonInternational1;
-
- private CheckBoxPreference mButtonLocal2;
- private CheckBoxPreference mButtonRegional2;
- private CheckBoxPreference mButtonNational2;
- private CheckBoxPreference mButtonInternational2;
-
- private CheckBoxPreference mButtonLocal3;
- private CheckBoxPreference mButtonRegional3;
- private CheckBoxPreference mButtonNational3;
- private CheckBoxPreference mButtonInternational3;
-
- private CheckBoxPreference mButtonLocal4;
- private CheckBoxPreference mButtonRegional4;
- private CheckBoxPreference mButtonNational4;
- private CheckBoxPreference mButtonInternational4;
-
-
- //Member variables
- private Phone mPhone;
- private MyHandler mHandler;
-
- /**
- * Invoked on each preference click in this hierarchy, overrides
- * PreferenceActivity's implementation. Used to make sure we track the
- * preference click events.
- */
- @Override
- public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
- Preference preference) {
- if (preference == mButtonBcSms) {
- if (DBG) Log.d(LOG_TAG, "onPreferenceTreeClick: preference == mButtonBcSms.");
- if(mButtonBcSms.isChecked()) {
- mPhone.activateCellBroadcastSms(RILConstants.CDMA_CELL_BROADCAST_SMS_ENABLED,
- Message.obtain(mHandler, MESSAGE_ACTIVATE_CB_SMS));
- android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(),
- android.provider.Settings.Global.CDMA_CELL_BROADCAST_SMS,
- RILConstants.CDMA_CELL_BROADCAST_SMS_ENABLED);
- enableDisableAllCbConfigButtons(true);
- } else {
- mPhone.activateCellBroadcastSms(RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED,
- Message.obtain(mHandler, MESSAGE_ACTIVATE_CB_SMS));
- android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(),
- android.provider.Settings.Global.CDMA_CELL_BROADCAST_SMS,
- RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
- enableDisableAllCbConfigButtons(false);
- }
- } else if (preference == mListLanguage) {
- //Do nothing here, because this click will be handled in onPreferenceChange
- } else if (preference == mButtonEmergencyBroadcast) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonEmergencyBroadcast.isChecked(), 1);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(
- mButtonEmergencyBroadcast.isChecked(), 1);
- } else if (preference == mButtonAdministrative) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonAdministrative.isChecked(), 2);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonAdministrative.isChecked(), 2);
- } else if (preference == mButtonMaintenance) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonMaintenance.isChecked(), 3);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonMaintenance.isChecked(), 3);
- } else if (preference == mButtonLocalWeather) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonLocalWeather.isChecked(), 20);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonLocalWeather.isChecked(), 20);
- } else if (preference == mButtonAtr) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonAtr.isChecked(), 21);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonAtr.isChecked(), 21);
- } else if (preference == mButtonLafs) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonLafs.isChecked(), 22);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonLafs.isChecked(), 22);
- } else if (preference == mButtonRestaurants) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonRestaurants.isChecked(), 23);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonRestaurants.isChecked(), 23);
- } else if (preference == mButtonLodgings) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonLodgings.isChecked(), 24);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonLodgings.isChecked(), 24);
- } else if (preference == mButtonRetailDirectory) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonRetailDirectory.isChecked(), 25);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonRetailDirectory.isChecked(), 25);
- } else if (preference == mButtonAdvertisements) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonAdvertisements.isChecked(), 26);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonAdvertisements.isChecked(), 26);
- } else if (preference == mButtonStockQuotes) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonStockQuotes.isChecked(), 27);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonStockQuotes.isChecked(), 27);
- } else if (preference == mButtonEo) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonEo.isChecked(), 28);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonEo.isChecked(), 28);
- } else if (preference == mButtonMhh) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonMhh.isChecked(), 29);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonMhh.isChecked(), 29);
- } else if (preference == mButtonTechnologyNews) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonTechnologyNews.isChecked(), 30);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonTechnologyNews.isChecked(), 30);
- } else if (preference == mButtonMultiCategory) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonMultiCategory.isChecked(), 31);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonMultiCategory.isChecked(), 31);
- } else if (preference == mButtonLocal1) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonLocal1.isChecked(), 4);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonLocal1.isChecked(), 4);
- } else if (preference == mButtonRegional1) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonRegional1.isChecked(), 5);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonRegional1.isChecked(), 5);
- } else if (preference == mButtonNational1) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonNational1.isChecked(), 6);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonNational1.isChecked(), 6);
- } else if (preference == mButtonInternational1) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonInternational1.isChecked(), 7);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonInternational1.isChecked(), 7);
- } else if (preference == mButtonLocal2) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonLocal2.isChecked(), 8);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonLocal2.isChecked(), 8);
- } else if (preference == mButtonRegional2) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonRegional2.isChecked(), 9);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonRegional2.isChecked(), 9);
- } else if (preference == mButtonNational2) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonNational2.isChecked(), 10);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonNational2.isChecked(), 10);
- } else if (preference == mButtonInternational2) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonInternational2.isChecked(), 11);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonInternational2.isChecked(), 11);
- } else if (preference == mButtonLocal3) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonLocal3.isChecked(), 12);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonLocal3.isChecked(), 12);
- } else if (preference == mButtonRegional3) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonRegional3.isChecked(), 13);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonRegional3.isChecked(), 13);
- } else if (preference == mButtonNational3) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonNational3.isChecked(), 14);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonNational3.isChecked(), 14);
- } else if (preference == mButtonInternational3) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonInternational3.isChecked(), 15);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonInternational3.isChecked(), 15);
- } else if (preference == mButtonLocal4) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(mButtonLocal4.isChecked(), 16);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonLocal4.isChecked(), 16);
- } else if (preference == mButtonRegional4) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonRegional4.isChecked(), 17);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonRegional4.isChecked(), 17);
- } else if (preference == mButtonNational4) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonNational4.isChecked(), 18);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonNational4.isChecked(), 18);
- } else if (preference == mButtonInternational4) {
- CellBroadcastSmsConfig.setConfigDataCompleteBSelected(
- mButtonInternational4.isChecked(), 19);
- CellBroadcastSmsConfig.setCbSmsBSelectedValue(mButtonInternational4.isChecked(), 19);
- } else {
- preferenceScreen.setEnabled(false);
- return false;
- }
-
- return true;
- }
-
- public boolean onPreferenceChange(Preference preference, Object objValue) {
- if (preference == mListLanguage) {
- // set the new language to the array which will be transmitted later
- CellBroadcastSmsConfig.setConfigDataCompleteLanguage(
- mListLanguage.findIndexOfValue((String) objValue) + 1);
- }
-
- // always let the preference setting proceed.
- return true;
- }
-
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- addPreferencesFromResource(R.xml.cell_broadcast_sms);
-
- mPhone = PhoneGlobals.getPhone();
- mHandler = new MyHandler();
-
- PreferenceScreen prefSet = getPreferenceScreen();
-
- mButtonBcSms = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_ENABLE_DISABLE_BC_SMS_KEY);
- mListLanguage = (ListPreference) prefSet.findPreference(
- LIST_LANGUAGE_KEY);
- // set the listener for the language list preference
- mListLanguage.setOnPreferenceChangeListener(this);
- mButtonEmergencyBroadcast = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_EMERGENCY_BROADCAST_KEY);
- mButtonAdministrative = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_ADMINISTRATIVE_KEY);
- mButtonMaintenance = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_MAINTENANCE_KEY);
- mButtonLocalWeather = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_LOCAL_WEATHER_KEY);
- mButtonAtr = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_ATR_KEY);
- mButtonLafs = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_LAFS_KEY);
- mButtonRestaurants = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_RESTAURANTS_KEY);
- mButtonLodgings = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_LODGINGS_KEY);
- mButtonRetailDirectory = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_RETAIL_DIRECTORY_KEY);
- mButtonAdvertisements = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_ADVERTISEMENTS_KEY);
- mButtonStockQuotes = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_STOCK_QUOTES_KEY);
- mButtonEo = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_EO_KEY);
- mButtonMhh = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_MHH_KEY);
- mButtonTechnologyNews = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_TECHNOLOGY_NEWS_KEY);
- mButtonMultiCategory = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_MULTI_CATEGORY_KEY);
-
- mButtonLocal1 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_LOCAL_GENERAL_NEWS_KEY);
- mButtonRegional1 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_REGIONAL_GENERAL_NEWS_KEY);
- mButtonNational1 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_NATIONAL_GENERAL_NEWS_KEY);
- mButtonInternational1 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_INTERNATIONAL_GENERAL_NEWS_KEY);
-
- mButtonLocal2 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_LOCAL_BF_NEWS_KEY);
- mButtonRegional2 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_REGIONAL_BF_NEWS_KEY);
- mButtonNational2 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_NATIONAL_BF_NEWS_KEY);
- mButtonInternational2 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_INTERNATIONAL_BF_NEWS_KEY);
-
- mButtonLocal3 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_LOCAL_SPORTS_NEWS_KEY);
- mButtonRegional3 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_REGIONAL_SPORTS_NEWS_KEY);
- mButtonNational3 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_NATIONAL_SPORTS_NEWS_KEY);
- mButtonInternational3 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_INTERNATIONAL_SPORTS_NEWS_KEY);
-
- mButtonLocal4 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_LOCAL_ENTERTAINMENT_NEWS_KEY);
- mButtonRegional4 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_REGIONAL_ENTERTAINMENT_NEWS_KEY);
- mButtonNational4 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_NATIONAL_ENTERTAINMENT_NEWS_KEY);
- mButtonInternational4 = (CheckBoxPreference) prefSet.findPreference(
- BUTTON_INTERNATIONAL_ENTERTAINMENT_NEWS_KEY);
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- getPreferenceScreen().setEnabled(true);
-
- int settingCbSms = android.provider.Settings.Global.getInt(
- mPhone.getContext().getContentResolver(),
- android.provider.Settings.Global.CDMA_CELL_BROADCAST_SMS,
- RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
- mButtonBcSms.setChecked(settingCbSms == RILConstants.CDMA_CELL_BROADCAST_SMS_ENABLED);
-
- if(mButtonBcSms.isChecked()) {
- enableDisableAllCbConfigButtons(true);
- } else {
- enableDisableAllCbConfigButtons(false);
- }
-
- mPhone.getCellBroadcastSmsConfig(Message.obtain(mHandler, MESSAGE_GET_CB_SMS_CONFIG));
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- CellBroadcastSmsConfig.setCbSmsNoOfStructs(NO_OF_SERVICE_CATEGORIES);
-
- mPhone.setCellBroadcastSmsConfig(CellBroadcastSmsConfig.getCbSmsAllValues(),
- Message.obtain(mHandler, MESSAGE_SET_CB_SMS_CONFIG));
- }
-
- private void enableDisableAllCbConfigButtons(boolean enable) {
- mButtonEmergencyBroadcast.setEnabled(enable);
- mListLanguage.setEnabled(enable);
- mButtonAdministrative.setEnabled(enable);
- mButtonMaintenance.setEnabled(enable);
- mButtonLocalWeather.setEnabled(enable);
- mButtonAtr.setEnabled(enable);
- mButtonLafs.setEnabled(enable);
- mButtonRestaurants.setEnabled(enable);
- mButtonLodgings.setEnabled(enable);
- mButtonRetailDirectory.setEnabled(enable);
- mButtonAdvertisements.setEnabled(enable);
- mButtonStockQuotes.setEnabled(enable);
- mButtonEo.setEnabled(enable);
- mButtonMhh.setEnabled(enable);
- mButtonTechnologyNews.setEnabled(enable);
- mButtonMultiCategory.setEnabled(enable);
-
- mButtonLocal1.setEnabled(enable);
- mButtonRegional1.setEnabled(enable);
- mButtonNational1.setEnabled(enable);
- mButtonInternational1.setEnabled(enable);
-
- mButtonLocal2.setEnabled(enable);
- mButtonRegional2.setEnabled(enable);
- mButtonNational2.setEnabled(enable);
- mButtonInternational2.setEnabled(enable);
-
- mButtonLocal3.setEnabled(enable);
- mButtonRegional3.setEnabled(enable);
- mButtonNational3.setEnabled(enable);
- mButtonInternational3.setEnabled(enable);
-
- mButtonLocal4.setEnabled(enable);
- mButtonRegional4.setEnabled(enable);
- mButtonNational4.setEnabled(enable);
- mButtonInternational4.setEnabled(enable);
- }
-
- private void setAllCbConfigButtons(int[] configArray) {
- //These buttons are in a well defined sequence. If you want to change it,
- //be sure to map the buttons to their corresponding slot in the configArray !
- mButtonEmergencyBroadcast.setChecked(configArray[1] != 0);
- //subtract 1, because the values are handled in an array which starts with 0 and not with 1
- mListLanguage.setValueIndex(CellBroadcastSmsConfig.getConfigDataLanguage() - 1);
- mButtonAdministrative.setChecked(configArray[2] != 0);
- mButtonMaintenance.setChecked(configArray[3] != 0);
- mButtonLocalWeather.setChecked(configArray[20] != 0);
- mButtonAtr.setChecked(configArray[21] != 0);
- mButtonLafs.setChecked(configArray[22] != 0);
- mButtonRestaurants.setChecked(configArray[23] != 0);
- mButtonLodgings.setChecked(configArray[24] != 0);
- mButtonRetailDirectory.setChecked(configArray[25] != 0);
- mButtonAdvertisements.setChecked(configArray[26] != 0);
- mButtonStockQuotes.setChecked(configArray[27] != 0);
- mButtonEo.setChecked(configArray[28] != 0);
- mButtonMhh.setChecked(configArray[29] != 0);
- mButtonTechnologyNews.setChecked(configArray[30] != 0);
- mButtonMultiCategory.setChecked(configArray[31] != 0);
-
- mButtonLocal1.setChecked(configArray[4] != 0);
- mButtonRegional1.setChecked(configArray[5] != 0);
- mButtonNational1.setChecked(configArray[6] != 0);
- mButtonInternational1.setChecked(configArray[7] != 0);
-
- mButtonLocal2.setChecked(configArray[8] != 0);
- mButtonRegional2.setChecked(configArray[9] != 0);
- mButtonNational2.setChecked(configArray[10] != 0);
- mButtonInternational2.setChecked(configArray[11] != 0);
-
- mButtonLocal3.setChecked(configArray[12] != 0);
- mButtonRegional3.setChecked(configArray[13] != 0);
- mButtonNational3.setChecked(configArray[14] != 0);
- mButtonInternational3.setChecked(configArray[15] != 0);
-
- mButtonLocal4.setChecked(configArray[16] != 0);
- mButtonRegional4.setChecked(configArray[17] != 0);
- mButtonNational4.setChecked(configArray[18] != 0);
- mButtonInternational4.setChecked(configArray[19] != 0);
- }
-
- private class MyHandler extends Handler {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_ACTIVATE_CB_SMS:
- //Only a log message here, because the received response is always null
- if (DBG) Log.d(LOG_TAG, "Cell Broadcast SMS enabled/disabled.");
- break;
- case MESSAGE_GET_CB_SMS_CONFIG:
- int result[] = (int[])((AsyncResult)msg.obj).result;
-
- // check if the actual service categoties table size on the NV is '0'
- if (result[0] == 0) {
- result[0] = NO_OF_SERVICE_CATEGORIES;
-
- mButtonBcSms.setChecked(false);
- mPhone.activateCellBroadcastSms(RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED,
- Message.obtain(mHandler, MESSAGE_ACTIVATE_CB_SMS));
- android.provider.Settings.Global.putInt(mPhone.getContext().getContentResolver(),
- android.provider.Settings.Global.CDMA_CELL_BROADCAST_SMS,
- RILConstants.CDMA_CELL_BROADCAST_SMS_DISABLED);
- enableDisableAllCbConfigButtons(false);
- }
-
- CellBroadcastSmsConfig.setCbSmsConfig(result);
- setAllCbConfigButtons(CellBroadcastSmsConfig.getCbSmsBselectedValues());
-
- break;
- case MESSAGE_SET_CB_SMS_CONFIG:
- //Only a log message here, because the received response is always null
- if (DBG) Log.d(LOG_TAG, "Set Cell Broadcast SMS values.");
- break;
- default:
- Log.e(LOG_TAG, "Error! Unhandled message in CellBroadcastSms.java. Message: "
- + msg.what);
- break;
- }
- }
- }
-
- private static final class CellBroadcastSmsConfig {
-
- //The values in this array are stored in a particular order. This order
- //is calculated in the setCbSmsConfig method of this class.
- //For more information see comments below...
- //NO_OF_SERVICE_CATEGORIES +1 is used, because we will leave the first array entry 0
- private static int mBSelected[] = new int[NO_OF_SERVICE_CATEGORIES + 1];
- private static int mConfigDataComplete[] = new int[MAX_LENGTH_RESULT];
-
- private static void setCbSmsConfig(int[] configData) {
- if(configData == null) {
- Log.e(LOG_TAG, "Error! No cell broadcast service categories returned.");
- return;
- }
-
- if(configData[0] > MAX_LENGTH_RESULT) {
- Log.e(LOG_TAG, "Error! Wrong number of service categories returned from RIL");
- return;
- }
-
- //The required config values for broadcast SMS are stored in a C struct:
- //
- // typedef struct {
- // int size;
- // RIL_CDMA_BcServiceInfo *entries;
- // } RIL_CDMA_BcSMSConfig;
- //
- // typedef struct {
- // int uServiceCategory;
- // int uLanguage;
- // unsigned char bSelected;
- // } RIL_CDMA_BcServiceInfo;
- //
- // This means, that we have to ignore the first value and check every
- // 3rd value starting with the 2nd of all. This value indicates, where we
- // will store the appropriate bSelected value, which is 2 values behind it.
- for(int i = 1; i < configData.length; i += NO_OF_INTS_STRUCT_1) {
- mBSelected[configData[i]] = configData[i +2];
- }
-
- //Store all values in an extra array
- mConfigDataComplete = configData;
- }
-
- private static void setCbSmsBSelectedValue(boolean value, int pos) {
- if(pos < mBSelected.length) {
- mBSelected[pos] = (value == true ? 1 : 0);
- } else {
- Log.e(LOG_TAG,"Error! Invalid value position.");
- }
- }
-
- private static int[] getCbSmsBselectedValues() {
- return(mBSelected);
- }
-
- // TODO: Change the return value to a RIL_BroadcastSMSConfig
- private static int[] getCbSmsAllValues() {
- return(mConfigDataComplete);
- }
-
- private static void setCbSmsNoOfStructs(int value) {
- //Sets the size parameter, which contains the number of structs
- //that will be transmitted
- mConfigDataComplete[0] = value;
- }
-
- private static void setConfigDataCompleteBSelected(boolean value, int serviceCategory) {
- //Sets the bSelected value for a specific serviceCategory
- for(int i = 1; i < mConfigDataComplete.length; i += NO_OF_INTS_STRUCT_1) {
- if(mConfigDataComplete[i] == serviceCategory) {
- mConfigDataComplete[i + 2] = value == true ? 1 : 0;
- break;
- }
- }
- }
-
- private static void setConfigDataCompleteLanguage(int language) {
- //It is only possible to set the same language for all entries
- for(int i = 2; i < mConfigDataComplete.length; i += NO_OF_INTS_STRUCT_1) {
- mConfigDataComplete[i] = language;
- }
- }
-
- private static int getConfigDataLanguage() {
- int language = mConfigDataComplete[2];
- //2 is the language value of the first entry
- //It is only possible to set the same language for all entries
- if (language < 1 || language > 7) {
- Log.e(LOG_TAG, "Error! Wrong language returned from RIL...defaulting to 1, english");
- return 1;
- }
- else {
- return language;
- }
- }
- }
-}
diff --git a/src/com/android/phone/DumpsysHandler.java b/src/com/android/phone/DumpsysHandler.java
new file mode 100644
index 0000000..d2ae38f
--- /dev/null
+++ b/src/com/android/phone/DumpsysHandler.java
@@ -0,0 +1,21 @@
+
+package com.android.phone;
+
+import android.content.Context;
+
+import com.android.phone.vvm.omtp.utils.VvmDumpHandler;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Handles "adb shell dumpsys phone" and bug report dump.
+ */
+public class DumpsysHandler {
+
+ public static void dump(Context context, FileDescriptor fd, PrintWriter writer,
+ String[] args) {
+ // Dump OMTP visual voicemail log.
+ VvmDumpHandler.dump(context, fd, writer, args);
+ }
+}
diff --git a/src/com/android/phone/EmergencyCallbackModeService.java b/src/com/android/phone/EmergencyCallbackModeService.java
index ca25653..9ed38ae 100644
--- a/src/com/android/phone/EmergencyCallbackModeService.java
+++ b/src/com/android/phone/EmergencyCallbackModeService.java
@@ -171,8 +171,8 @@
* Shows notification for Emergency Callback Mode
*/
private void showNotification(long millisUntilFinished) {
- final boolean isInEcm = Boolean.parseBoolean(
- SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
+ Phone imsPhone = mPhone.getImsPhone();
+ boolean isInEcm = mPhone.isInEcm() || (imsPhone != null && imsPhone.isInEcm());
if (!isInEcm) {
Log.i(LOG_TAG, "Asked to show notification but not in ECM mode");
if (mTimer != null) {
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index c402148..53f6f7e 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -513,6 +513,11 @@
*/
private void placeCall() {
mLastNumber = mDigits.getText().toString();
+ // Convert into emergency number if necessary
+ // This is required in some regions (e.g. Taiwan).
+ if (PhoneNumberUtils.isConvertToEmergencyNumberEnabled()) {
+ mLastNumber = PhoneNumberUtils.convertToEmergencyNumber(mLastNumber);
+ }
if (PhoneNumberUtils.isLocalEmergencyNumber(this, mLastNumber)) {
if (DBG) Log.d(LOG_TAG, "placing call to " + mLastNumber);
diff --git a/src/com/android/phone/ImsUtil.java b/src/com/android/phone/ImsUtil.java
index 868a0f1..4c9089f 100644
--- a/src/com/android/phone/ImsUtil.java
+++ b/src/com/android/phone/ImsUtil.java
@@ -17,6 +17,9 @@
package com.android.phone;
import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.telephony.CarrierConfigManager;
import android.util.Log;
import com.android.ims.ImsConfig;
@@ -66,4 +69,31 @@
if (DBG) Log.d(LOG_TAG, "isWfcModeWifiOnly :: isWifiOnlyMode" + isWifiOnlyMode);
return isWfcEnabled(context) && isWifiOnlyMode;
}
+
+ /**
+ * When a call cannot be placed, determines if the use of WFC should be promoted, per the
+ * carrier config. Use of WFC is promoted to the user if the device is connected to a WIFI
+ * network, WFC is disabled, and the carrier config indicates that the features should be
+ * promoted.
+ *
+ * @return {@code true} if use of WFC should be promoted, {@code false} otherwise.
+ */
+ public static boolean shouldPromoteWfc(Context context) {
+ CarrierConfigManager cfgManager = (CarrierConfigManager) context
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (cfgManager == null || !cfgManager.getConfig()
+ .getBoolean(CarrierConfigManager.KEY_CARRIER_PROMOTE_WFC_ON_CALL_FAIL_BOOL)) {
+ return false;
+ }
+
+ ConnectivityManager cm =
+ (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (cm != null) {
+ NetworkInfo ni = cm.getActiveNetworkInfo();
+ if (ni != null && ni.isConnected()) {
+ return ni.getType() == ConnectivityManager.TYPE_WIFI && !isWfcEnabled(context);
+ }
+ }
+ return false;
+ }
}
diff --git a/src/com/android/phone/MobileNetworkSettings.java b/src/com/android/phone/MobileNetworkSettings.java
index 404c976..56b6390 100644
--- a/src/com/android/phone/MobileNetworkSettings.java
+++ b/src/com/android/phone/MobileNetworkSettings.java
@@ -421,7 +421,6 @@
@Override
protected void onCreate(Bundle icicle) {
if (DBG) log("onCreate:+");
- setTheme(R.style.Theme_Material_Settings);
super.onCreate(icicle);
mHandler = new MyHandler();
@@ -745,6 +744,11 @@
boolean canChange4glte = (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) &&
ImsManager.isNonTtyOrTtyOnVolteEnabled(getApplicationContext()) &&
carrierConfig.getBoolean(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL);
+ boolean useVariant4glteTitle = carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_ENHANCED_4G_LTE_TITLE_VARIANT_BOOL);
+ int enhanced4glteModeTitleId = useVariant4glteTitle ?
+ R.string.enhanced_4g_lte_mode_title_variant :
+ R.string.enhanced_4g_lte_mode_title;
mButtonDataRoam.setDisabledByAdmin(false);
mButtonDataRoam.setEnabled(hasActiveSubscriptions);
if (mButtonDataRoam.isEnabled()) {
@@ -757,6 +761,7 @@
}
mButtonPreferredNetworkMode.setEnabled(hasActiveSubscriptions);
mButtonEnabledNetworks.setEnabled(hasActiveSubscriptions);
+ mButton4glte.setTitle(enhanced4glteModeTitleId);
mButton4glte.setEnabled(hasActiveSubscriptions && canChange4glte);
mLteDataServicePref.setEnabled(hasActiveSubscriptions);
Preference ps;
diff --git a/src/com/android/phone/NeededForTesting.java b/src/com/android/phone/NeededForTesting.java
new file mode 100644
index 0000000..576598b
--- /dev/null
+++ b/src/com/android/phone/NeededForTesting.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 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;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.SOURCE)
+public @interface NeededForTesting {
+
+}
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index f0ca86b..abe5397 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -54,9 +54,9 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyCapabilities;
+import com.android.phone.settings.VoicemailNotificationSettingsUtil;
import com.android.phone.settings.VoicemailSettingsActivity;
import com.android.phone.vvm.omtp.sync.VoicemailStatusQueryHelper;
-import com.android.phone.settings.VoicemailNotificationSettingsUtil;
import java.util.Iterator;
import java.util.List;
@@ -78,6 +78,9 @@
// Do not check in with VDBG = true, since that may write PII to the system log.
private static final boolean VDBG = false;
+ private static final String MWI_SHOULD_CHECK_VVM_CONFIGURATION_KEY_PREFIX =
+ "mwi_should_check_vvm_configuration_state_";
+
// notification types
static final int MMI_NOTIFICATION = 1;
static final int NETWORK_SELECTION_NOTIFICATION = 2;
@@ -200,6 +203,27 @@
}
}
+ public void setShouldCheckVisualVoicemailConfigurationForMwi(int subId, boolean enabled) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ Log.e(LOG_TAG, "setShouldCheckVisualVoicemailConfigurationForMwi: invalid subId"
+ + subId);
+ return;
+ }
+
+ PreferenceManager.getDefaultSharedPreferences(mContext).edit()
+ .putBoolean(MWI_SHOULD_CHECK_VVM_CONFIGURATION_KEY_PREFIX + subId, enabled)
+ .apply();
+ }
+
+ private boolean shouldCheckVisualVoicemailConfigurationForMwi(int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ Log.e(LOG_TAG, "shouldCheckVisualVoicemailConfigurationForMwi: invalid subId" + subId);
+ return true;
+ }
+ return PreferenceManager
+ .getDefaultSharedPreferences(mContext)
+ .getBoolean(MWI_SHOULD_CHECK_VVM_CONFIGURATION_KEY_PREFIX + subId, true);
+ }
/**
* Updates the message waiting indicator (voicemail) notification.
*
@@ -225,11 +249,16 @@
}
Phone phone = PhoneGlobals.getPhone(subId);
- if (visible && phone != null) {
+ if (visible && phone != null && shouldCheckVisualVoicemailConfigurationForMwi(subId)) {
VoicemailStatusQueryHelper queryHelper = new VoicemailStatusQueryHelper(mContext);
PhoneAccountHandle phoneAccount = PhoneUtils.makePstnPhoneAccountHandle(phone);
- if (queryHelper.isNotificationsChannelActive(phoneAccount)) {
- Log.v(LOG_TAG, "Notifications channel active for visual voicemail, hiding mwi.");
+ if (queryHelper.isVoicemailSourceConfigured(phoneAccount)) {
+ Log.v(LOG_TAG, "Source configured for visual voicemail, hiding mwi.");
+ // MWI may not be suppressed if the PIN is not set on VVM3 because it is also a
+ // "Not OK" configuration state. But VVM3 never send a MWI after the service is
+ // activated so this should be fine.
+ // TODO(twyen): once unbundled the client should be able to set a flag to suppress
+ // MWI, instead of letting the NotificationMgr try to interpret the states.
visible = false;
}
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index ba7251f..f45fb94 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -34,10 +34,8 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
-import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
-import android.os.SystemService;
import android.os.UpdateLock;
import android.os.UserManager;
import android.preference.PreferenceManager;
@@ -59,7 +57,6 @@
import com.android.internal.telephony.TelephonyIntents;
import com.android.phone.common.CallLogAsync;
import com.android.phone.settings.SettingsConstants;
-import com.android.server.sip.SipService;
import com.android.services.telephony.activation.SimActivationManager;
import com.android.services.telephony.sip.SipUtil;
@@ -637,8 +634,53 @@
notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange();
}
- private void handleAirplaneModeChange(int newMode) {
- if (newMode == AIRPLANE_ON) {
+ private void handleAirplaneModeChange(Context context, int newMode) {
+ int cellState = Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.CELL_ON, PhoneConstants.CELL_ON_FLAG);
+ boolean isAirplaneNewlyOn = (newMode == 1);
+ switch (cellState) {
+ case PhoneConstants.CELL_OFF_FLAG:
+ // Airplane mode does not affect the cell radio if user
+ // has turned it off.
+ break;
+ case PhoneConstants.CELL_ON_FLAG:
+ maybeTurnCellOff(context, isAirplaneNewlyOn);
+ break;
+ case PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG:
+ maybeTurnCellOn(context, isAirplaneNewlyOn);
+ break;
+ }
+ }
+
+ /*
+ * Returns true if the radio must be turned off when entering airplane mode.
+ */
+ private boolean isCellOffInAirplaneMode(Context context) {
+ String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_RADIOS);
+ return airplaneModeRadios == null
+ || airplaneModeRadios.contains(Settings.Global.RADIO_CELL);
+ }
+
+ private void setRadioPowerOff(Context context) {
+ Log.i(LOG_TAG, "Turning radio off - airplane");
+ Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON,
+ PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG);
+ Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT, 0);
+ PhoneUtils.setRadioPower(false);
+ }
+
+ private void setRadioPowerOn(Context context) {
+ Log.i(LOG_TAG, "Turning radio on - airplane");
+ Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON,
+ PhoneConstants.CELL_ON_FLAG);
+ Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT,
+ 1);
+ PhoneUtils.setRadioPower(true);
+ }
+
+ private void maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn) {
+ if (isAirplaneNewlyOn) {
// If we are trying to turn off the radio, make sure there are no active
// emergency calls. If there are, switch airplane mode back to off.
if (PhoneUtils.isInEmergencyCall(mCM)) {
@@ -647,13 +689,17 @@
Toast.makeText(this, R.string.radio_off_during_emergency_call, Toast.LENGTH_LONG)
.show();
Log.i(LOG_TAG, "Ignoring airplane mode: emergency call. Turning airplane off");
+ } else if (isCellOffInAirplaneMode(context)) {
+ setRadioPowerOff(context);
} else {
- Log.i(LOG_TAG, "Turning radio off - airplane");
- PhoneUtils.setRadioPower(false);
+ Log.i(LOG_TAG, "Ignoring airplane mode: settings prevent cell radio power off");
}
- } else {
- Log.i(LOG_TAG, "Turning radio on - airplane");
- PhoneUtils.setRadioPower(true);
+ }
+ }
+
+ private void maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn) {
+ if (!isAirplaneNewlyOn) {
+ setRadioPowerOn(context);
}
}
@@ -671,7 +717,7 @@
if (airplaneMode != AIRPLANE_OFF) {
airplaneMode = AIRPLANE_ON;
}
- handleAirplaneModeChange(airplaneMode);
+ handleAirplaneModeChange(context, airplaneMode);
} else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
@@ -807,6 +853,32 @@
* @param subId the subscription id we should dismiss the notification for.
*/
public void clearMwiIndicator(int subId) {
- notificationMgr.updateMwi(subId, false);
+ // Setting voiceMessageCount to 0 will remove the current notification and clear the system
+ // cached value.
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ Log.w(LOG_TAG, "clearMwiIndicator on null phone, subId:" + subId);
+ } else {
+ phone.setVoiceMessageCount(0);
+ }
+ }
+
+ /**
+ * Enables or disables the visual voicemail check for message waiting indicator. Default value
+ * is true. MWI is the traditional voicemail notification which should be suppressed if visual
+ * voicemail is active. {@link NotificationMgr#updateMwi(int, boolean, boolean)} currently
+ * checks the {@link android.provider.VoicemailContract.Status#CONFIGURATION_STATE} to suppress
+ * the MWI, but there are several issues. b/31229016 is a bug that when the device boots the
+ * configuration state will be cleared and the MWI for voicemail that arrives when the device
+ * is offline will be cleared, even if the account cannot be activated. A full solution will be
+ * adding a setMwiEnabled() method and stop checking the configuration state, but that is too
+ * risky at this moment. This is a temporary workaround to shut down the configuration state
+ * check if visual voicemail cannot be activated.
+ * <p>TODO(twyen): implement the setMwiEnabled() mentioned above.
+ *
+ * @param subId the account to set the enabled state
+ */
+ public void setShouldCheckVisualVoicemailConfigurationForMwi(int subId, boolean enabled) {
+ notificationMgr.setShouldCheckVisualVoicemailConfigurationForMwi(subId, enabled);
}
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index fb075b4..38e40d7 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -16,6 +16,8 @@
package com.android.phone;
+import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
+
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.content.ComponentName;
@@ -38,25 +40,27 @@
import android.os.UserManager;
import android.preference.PreferenceManager;
import android.provider.Settings;
+import android.service.carrier.CarrierIdentifier;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.telephony.CellInfo;
import android.telephony.IccOpenLogicalChannelResponse;
+import android.telephony.ModemActivityInfo;
import android.telephony.NeighboringCellInfo;
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyHistogram;
import android.telephony.TelephonyManager;
-import android.telephony.ModemActivityInfo;
+import android.telephony.VisualVoicemailSmsFilterSettings;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
-
import com.android.ims.ImsManager;
import com.android.internal.telephony.CallManager;
import com.android.internal.telephony.CellNetworkScanResult;
@@ -67,9 +71,10 @@
import com.android.internal.telephony.MccTable;
import com.android.internal.telephony.OperatorInfo;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ProxyController;
-import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.RIL;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.uicc.IccIoResult;
@@ -77,10 +82,10 @@
import com.android.internal.telephony.uicc.UiccCard;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.util.HexDump;
+import com.android.phone.settings.VisualVoicemailSettingsUtil;
import com.android.phone.settings.VoicemailNotificationSettingsUtil;
-
-import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
-
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -138,6 +143,10 @@
private static final int EVENT_PERFORM_NETWORK_SCAN_DONE = 40;
private static final int CMD_SET_NETWORK_SELECTION_MODE_MANUAL = 41;
private static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_DONE = 42;
+ private static final int CMD_SET_ALLOWED_CARRIERS = 43;
+ private static final int EVENT_SET_ALLOWED_CARRIERS_DONE = 44;
+ private static final int CMD_GET_ALLOWED_CARRIERS = 45;
+ private static final int EVENT_GET_ALLOWED_CARRIERS_DONE = 46;
/** The singleton instance. */
private static PhoneInterfaceManager sInstance;
@@ -760,6 +769,68 @@
}
break;
+ case CMD_SET_ALLOWED_CARRIERS:
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_SET_ALLOWED_CARRIERS_DONE, request);
+ mPhone.setAllowedCarriers(
+ (List<CarrierIdentifier>) request.argument,
+ onCompleted);
+ break;
+
+ case EVENT_SET_ALLOWED_CARRIERS_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = ar.result;
+ } else {
+ if (ar.result == null) {
+ loge("setAllowedCarriers: Empty response");
+ } else if (ar.exception instanceof CommandException) {
+ loge("setAllowedCarriers: CommandException: " +
+ ar.exception);
+ } else {
+ loge("setAllowedCarriers: Unknown exception");
+ }
+ }
+ // Result cannot be null. Return -1 on error.
+ if (request.result == null) {
+ request.result = new int[]{-1};
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
+ case CMD_GET_ALLOWED_CARRIERS:
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_GET_ALLOWED_CARRIERS_DONE, request);
+ mPhone.getAllowedCarriers(onCompleted);
+ break;
+
+ case EVENT_GET_ALLOWED_CARRIERS_DONE:
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ if (ar.exception == null && ar.result != null) {
+ request.result = ar.result;
+ } else {
+ if (ar.result == null) {
+ loge("getAllowedCarriers: Empty response");
+ } else if (ar.exception instanceof CommandException) {
+ loge("getAllowedCarriers: CommandException: " +
+ ar.exception);
+ } else {
+ loge("getAllowedCarriers: Unknown exception");
+ }
+ }
+ // Result cannot be null. Return empty list of CarrierIdentifier.
+ if (request.result == null) {
+ request.result = new ArrayList<CarrierIdentifier>(0);
+ }
+ synchronized (request) {
+ request.notifyAll();
+ }
+ break;
+
default:
Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
break;
@@ -1331,7 +1402,14 @@
}
public boolean setRadioPower(boolean turnOn) {
- return setRadioPowerForSubscriber(getDefaultSubscription(), turnOn);
+ final Phone defaultPhone = PhoneFactory.getDefaultPhone();
+ if (defaultPhone != null) {
+ defaultPhone.setRadioPower(turnOn);
+ return true;
+ } else {
+ loge("There's no default phone.");
+ return false;
+ }
}
public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
@@ -1827,6 +1905,58 @@
return success;
}
+ @Override
+ public void setVisualVoicemailEnabled(String callingPackage,
+ PhoneAccountHandle phoneAccountHandle, boolean enabled) {
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ if (!TextUtils.equals(callingPackage,
+ TelecomManager.from(mPhone.getContext()).getDefaultDialerPackage())) {
+ enforceModifyPermissionOrCarrierPrivilege(
+ PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle));
+ }
+ VisualVoicemailSettingsUtil.setEnabled(mPhone.getContext(), phoneAccountHandle, enabled);
+ }
+
+ @Override
+ public boolean isVisualVoicemailEnabled(String callingPackage,
+ PhoneAccountHandle phoneAccountHandle) {
+ if (!canReadPhoneState(callingPackage, "isVisualVoicemailEnabled")) {
+ return false;
+ }
+ return VisualVoicemailSettingsUtil.isEnabled(mPhone.getContext(), phoneAccountHandle);
+ }
+
+ @Override
+ public void enableVisualVoicemailSmsFilter(String callingPackage, int subId,
+ VisualVoicemailSmsFilterSettings settings) {
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ VisualVoicemailSmsFilterConfig
+ .enableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId,
+ settings);
+ }
+
+ @Override
+ public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ VisualVoicemailSmsFilterConfig
+ .disableVisualVoicemailSmsFilter(mPhone.getContext(), callingPackage, subId);
+ }
+
+ @Override
+ public VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
+ String callingPackage, int subId) {
+ mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ return VisualVoicemailSmsFilterConfig
+ .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), callingPackage, subId);
+ }
+
+ @Override
+ public VisualVoicemailSmsFilterSettings getSystemVisualVoicemailSmsFilterSettings(
+ String packageName, int subId) {
+ enforceReadPrivilegedPermission();
+ return VisualVoicemailSmsFilterConfig
+ .getVisualVoicemailSmsFilterSettings(mPhone.getContext(), packageName, subId);
+ }
/**
* Returns the unread count of voicemails
*/
@@ -2756,7 +2886,7 @@
TelecomManager telecomManager = TelecomManager.from(mPhone.getContext());
TelephonyManager telephonyManager =
(TelephonyManager) mPhone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
- return !telephonyManager.isMultiSimEnabled() && telecomManager.isTtySupported();
+ return telecomManager.isTtySupported();
}
@Override
@@ -3046,4 +3176,221 @@
return VoicemailNotificationSettingsUtil.isVibrationEnabled(phone);
}
+ /**
+ * Make sure either called from same process as self (phone) or IPC caller has read privilege.
+ *
+ * @throws SecurityException if the caller does not have the required permission
+ */
+ private void enforceReadPrivilegedPermission() {
+ mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ null);
+ }
+
+ /**
+ * Return the application ID for the app type.
+ *
+ * @param subId the subscription ID that this request applies to.
+ * @param appType the uicc app type.
+ * @return Application ID for specificied app type, or null if no uicc.
+ */
+ @Override
+ public String getAidForAppType(int subId, int appType) {
+ enforceReadPrivilegedPermission();
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ return null;
+ }
+ String aid = null;
+ try {
+ aid = UiccController.getInstance().getUiccCard(phone.getPhoneId())
+ .getApplicationByType(appType).getAid();
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Not getting aid. Exception ex=" + e);
+ }
+ return aid;
+ }
+
+ /**
+ * Return the Electronic Serial Number.
+ *
+ * @param subId the subscription ID that this request applies to.
+ * @return ESN or null if error.
+ */
+ @Override
+ public String getEsn(int subId) {
+ enforceReadPrivilegedPermission();
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ return null;
+ }
+ String esn = null;
+ try {
+ esn = phone.getEsn();
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Not getting ESN. Exception ex=" + e);
+ }
+ return esn;
+ }
+
+ /**
+ * Return the Preferred Roaming List Version.
+ *
+ * @param subId the subscription ID that this request applies to.
+ * @return PRLVersion or null if error.
+ */
+ @Override
+ public String getCdmaPrlVersion(int subId) {
+ enforceReadPrivilegedPermission();
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ return null;
+ }
+ String cdmaPrlVersion = null;
+ try {
+ cdmaPrlVersion = phone.getCdmaPrlVersion();
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Not getting PRLVersion", e);
+ }
+ return cdmaPrlVersion;
+ }
+
+ /**
+ * Get snapshot of Telephony histograms
+ * @return List of Telephony histograms
+ * @hide
+ */
+ @Override
+ public List<TelephonyHistogram> getTelephonyHistograms() {
+ enforceModifyPermissionOrCarrierPrivilege(getDefaultSubscription());
+ return RIL.getTelephonyRILTimingHistograms();
+ }
+
+ /**
+ * {@hide}
+ * Set the allowed carrier list for slotId
+ * Require system privileges. In the future we may add this to carrier APIs.
+ *
+ * @return The number of carriers set successfully, should match length of carriers
+ */
+ @Override
+ public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) {
+ enforceModifyPermission();
+ int subId = SubscriptionManager.getSubId(slotId)[0];
+ int[] retVal = (int[]) sendRequest(CMD_SET_ALLOWED_CARRIERS, carriers, subId);
+ return retVal[0];
+ }
+
+ /**
+ * {@hide}
+ * Get the allowed carrier list for slotId.
+ * Require system privileges. In the future we may add this to carrier APIs.
+ *
+ * @return List of {@link android.service.telephony.CarrierIdentifier}; empty list
+ * means all carriers are allowed.
+ */
+ @Override
+ public List<CarrierIdentifier> getAllowedCarriers(int slotId) {
+ enforceReadPrivilegedPermission();
+ int subId = SubscriptionManager.getSubId(slotId)[0];
+ return (List<CarrierIdentifier>) sendRequest(CMD_GET_ALLOWED_CARRIERS, null, subId);
+ }
+
+ /**
+ * 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);
+ 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);
+ }
+ }
+
+ /**
+ * 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.
+ * {@hide}
+ */
+ @Override
+ public void carrierActionSetRadioEnabled(int subId, boolean enabled) {
+ enforceModifyPermission();
+ final Phone phone = getPhone(subId);
+ if (phone == null) {
+ loge("carrierAction: SetRadioEnabled fails with invalid sibId: " + subId);
+ return;
+ }
+ try {
+ phone.carrierActionSetRadioEnabled(enabled);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "carrierAction: SetRadioEnabled fails. Exception ex=" + e);
+ }
+ }
+
+ /**
+ * Called when "adb shell dumpsys phone" is invoked. Dump is also automatically invoked when a
+ * bug report is being generated.
+ */
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+ if (mPhone.getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ writer.println("Permission Denial: can't dump Phone from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + "without permission "
+ + android.Manifest.permission.DUMP);
+ return;
+ }
+ DumpsysHandler.dump(mPhone.getContext(), fd, writer, args);
+ }
+
+ /**
+ * Get aggregated video call data usage from all subscriptions since boot.
+ * @return total data usage in bytes
+ * {@hide}
+ */
+ @Override
+ public long getVtDataUsage() {
+ mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_NETWORK_USAGE_HISTORY,
+ null);
+
+ // NetworkStatsService keeps tracking the active network interface and identity. It will
+ // record the delta with the corresponding network identity. What we need to do here is
+ // returning total video call data usage from all subscriptions since boot.
+
+ // TODO: Add sub id support in the future. We'll need it when we support DSDA and
+ // simultaneous VT calls.
+ final Phone[] phones = PhoneFactory.getPhones();
+ long total = 0;
+ for (Phone phone : phones) {
+ total += phone.getVtDataUsage();
+ }
+ return total;
+ }
+
+ /**
+ * Policy control of data connection. Usually used when data limit is passed.
+ * @param enabled True if enabling the data, otherwise disabling.
+ * @param subId Subscription index
+ * {@hide}
+ */
+ @Override
+ public void setPolicyDataEnabled(boolean enabled, int subId) {
+ enforceModifyPermission();
+ Phone phone = getPhone(subId);
+ if (phone != null) {
+ phone.setPolicyDataEnabled(enabled);
+ }
+ }
}
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index 4dd7d0b..9f70349 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -64,7 +64,6 @@
import com.android.internal.telephony.TelephonyProperties;
import com.android.internal.telephony.sip.SipPhone;
import com.android.phone.CallGatewayManager.RawGatewayInfo;
-import com.android.services.telephony.TelephonyConnectionService;
import java.util.Arrays;
import java.util.List;
@@ -2442,7 +2441,7 @@
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
- static Phone getPhoneForPhoneAccountHandle(PhoneAccountHandle handle) {
+ public static Phone getPhoneForPhoneAccountHandle(PhoneAccountHandle handle) {
if (handle != null && handle.getComponentName().equals(getPstnConnectionServiceName())) {
return getPhoneFromIccId(handle.getId());
}
diff --git a/src/com/android/phone/VisualVoicemailSmsFilterConfig.java b/src/com/android/phone/VisualVoicemailSmsFilterConfig.java
new file mode 100644
index 0000000..2b2e2f5
--- /dev/null
+++ b/src/com/android/phone/VisualVoicemailSmsFilterConfig.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.telephony.VisualVoicemailSmsFilterSettings;
+import android.util.ArraySet;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Stores the config values needed for visual voicemail sms filtering. The values from
+ * OmtpVvmCarrierConfigHelper are stored here during activation instead. These values are read and
+ * written through TelephonyManager.
+ */
+public class VisualVoicemailSmsFilterConfig {
+
+ private static final String VVM_SMS_FILTER_COFIG_SHARED_PREFS_KEY_PREFIX =
+ "vvm_sms_filter_config_";
+ private static final String ENABLED_KEY = "_enabled";
+ private static final String PREFIX_KEY = "_prefix";
+ private static final String ORIGINATING_NUMBERS_KEY = "_originating_numbers";
+ private static final String DESTINATION_PORT_KEY = "_destination_port";
+
+ public static void enableVisualVoicemailSmsFilter(Context context, String callingPackage,
+ int subId,
+ VisualVoicemailSmsFilterSettings settings) {
+ new Editor(context, callingPackage, subId)
+ .setBoolean(ENABLED_KEY, true)
+ .setString(PREFIX_KEY, settings.clientPrefix)
+ .setStringList(ORIGINATING_NUMBERS_KEY, settings.originatingNumbers)
+ .setInt(DESTINATION_PORT_KEY, settings.destinationPort)
+ .apply();
+ }
+
+ public static void disableVisualVoicemailSmsFilter(Context context, String callingPackage,
+ int subId) {
+ new Editor(context, callingPackage, subId)
+ .setBoolean(ENABLED_KEY, false)
+ .apply();
+ }
+
+ @Nullable
+ public static VisualVoicemailSmsFilterSettings getVisualVoicemailSmsFilterSettings(
+ Context context,
+ String packageName, int subId) {
+ Reader reader = new Reader(context, packageName, subId);
+ if (!reader.getBoolean(ENABLED_KEY, false)) {
+ return null;
+ }
+ return new VisualVoicemailSmsFilterSettings.Builder()
+ .setClientPrefix(reader.getString(PREFIX_KEY,
+ VisualVoicemailSmsFilterSettings.DEFAULT_CLIENT_PREFIX))
+ .setOriginatingNumbers(reader.getStringSet(ORIGINATING_NUMBERS_KEY,
+ VisualVoicemailSmsFilterSettings.DEFAULT_ORIGINATING_NUMBERS))
+ .setDestinationPort(reader.getInt(DESTINATION_PORT_KEY,
+ VisualVoicemailSmsFilterSettings.DEFAULT_DESTINATION_PORT))
+ .build();
+ }
+ private static SharedPreferences getSharedPreferences(Context context) {
+ return PreferenceManager
+ .getDefaultSharedPreferences(context.createDeviceProtectedStorageContext());
+ }
+
+ private static String makePerPhoneAccountKeyPrefix(String packageName, int subId) {
+ // subId is persistent across reboot and upgrade, but not across devices.
+ // ICC id is better as a key but it involves more trouble to get one as subId is more
+ // commonly passed around.
+ return VVM_SMS_FILTER_COFIG_SHARED_PREFS_KEY_PREFIX + packageName + "_"
+ + subId;
+ }
+
+ private static class Editor {
+
+ private final SharedPreferences.Editor mPrefsEditor;
+ private final String mKeyPrefix;
+
+ public Editor(Context context, String packageName, int subId) {
+ mPrefsEditor = getSharedPreferences(context).edit();
+ mKeyPrefix = makePerPhoneAccountKeyPrefix(packageName, subId);
+ }
+
+ private Editor setInt(String key, int value) {
+ mPrefsEditor.putInt(makeKey(key), value);
+ return this;
+ }
+
+ private Editor setString(String key, String value) {
+ mPrefsEditor.putString(makeKey(key), value);
+ return this;
+ }
+
+ private Editor setBoolean(String key, boolean value) {
+ mPrefsEditor.putBoolean(makeKey(key), value);
+ return this;
+ }
+
+ private Editor setStringList(String key, List<String> value) {
+ mPrefsEditor.putStringSet(makeKey(key), new ArraySet(value));
+ return this;
+ }
+
+ public void apply() {
+ mPrefsEditor.apply();
+ }
+
+ private String makeKey(String key) {
+ return mKeyPrefix + key;
+ }
+ }
+
+
+ private static class Reader {
+
+ private final SharedPreferences mPrefs;
+ private final String mKeyPrefix;
+
+ public Reader(Context context, String packageName, int subId) {
+ mPrefs = getSharedPreferences(context);
+ mKeyPrefix = makePerPhoneAccountKeyPrefix(packageName, subId);
+ }
+
+ private int getInt(String key, int defaultValue) {
+ return mPrefs.getInt(makeKey(key), defaultValue);
+ }
+
+ private String getString(String key, String defaultValue) {
+ return mPrefs.getString(makeKey(key), defaultValue);
+ }
+
+ private boolean getBoolean(String key, boolean defaultValue) {
+ return mPrefs.getBoolean(makeKey(key), defaultValue);
+ }
+
+ private List<String> getStringSet(String key, List<String> defaultValue) {
+ Set<String> result = mPrefs.getStringSet(makeKey(key), null);
+ if (result == null) {
+ return defaultValue;
+ }
+ return new ArrayList<>(result);
+ }
+
+ private String makeKey(String key) {
+ return mKeyPrefix + key;
+ }
+ }
+}
diff --git a/src/com/android/phone/VoicemailStatus.java b/src/com/android/phone/VoicemailStatus.java
new file mode 100644
index 0000000..00130f1
--- /dev/null
+++ b/src/com/android/phone/VoicemailStatus.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2016 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;
+
+import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
+import android.net.Uri;
+import android.provider.VoicemailContract;
+import android.provider.VoicemailContract.Status;
+import android.telecom.PhoneAccountHandle;
+import com.android.phone.vvm.omtp.VvmLog;
+
+public class VoicemailStatus {
+
+ private static final String TAG = "VvmStatus";
+
+ public static class Editor {
+
+ private final Context mContext;
+ @Nullable
+ private final PhoneAccountHandle mPhoneAccountHandle;
+
+ private ContentValues mValues = new ContentValues();
+
+ private Editor(Context context, PhoneAccountHandle phoneAccountHandle) {
+ mContext = context;
+ mPhoneAccountHandle = phoneAccountHandle;
+ if (mPhoneAccountHandle == null) {
+ VvmLog.w(TAG, "VoicemailStatus.Editor created with null phone account, status will"
+ + " not be written");
+ }
+ }
+
+ @Nullable
+ public PhoneAccountHandle getPhoneAccountHandle() {
+ return mPhoneAccountHandle;
+ }
+
+ public Editor setType(String type) {
+ mValues.put(Status.SOURCE_TYPE, type);
+ return this;
+ }
+
+ public Editor setConfigurationState(int configurationState) {
+ mValues.put(Status.CONFIGURATION_STATE, configurationState);
+ return this;
+ }
+
+ public Editor setDataChannelState(int dataChannelState) {
+ mValues.put(Status.DATA_CHANNEL_STATE, dataChannelState);
+ return this;
+ }
+
+ public Editor setNotificationChannelState(int notificationChannelState) {
+ mValues.put(Status.NOTIFICATION_CHANNEL_STATE, notificationChannelState);
+ return this;
+ }
+
+ public Editor setQuota(int occupied, int total) {
+ if (occupied == VoicemailContract.Status.QUOTA_UNAVAILABLE
+ && total == VoicemailContract.Status.QUOTA_UNAVAILABLE) {
+ return this;
+ }
+
+ mValues.put(Status.QUOTA_OCCUPIED, occupied);
+ mValues.put(Status.QUOTA_TOTAL, total);
+ return this;
+ }
+
+ /**
+ * Apply the changes to the {@link VoicemailStatus} {@link #Editor}.
+ *
+ * @return {@code true} if the changes were successfully applied, {@code false} otherwise.
+ */
+ public boolean apply() {
+ if (mPhoneAccountHandle == null) {
+ return false;
+ }
+ mValues.put(Status.PHONE_ACCOUNT_COMPONENT_NAME,
+ mPhoneAccountHandle.getComponentName().flattenToString());
+ mValues.put(Status.PHONE_ACCOUNT_ID, mPhoneAccountHandle.getId());
+ ContentResolver contentResolver = mContext.getContentResolver();
+ Uri statusUri = VoicemailContract.Status.buildSourceUri(mContext.getPackageName());
+ try {
+ contentResolver.insert(statusUri, mValues);
+ } catch (IllegalArgumentException iae) {
+ VvmLog.e(TAG, "apply :: failed to insert content resolver ", iae);
+ mValues.clear();
+ return false;
+ }
+ mValues.clear();
+ return true;
+ }
+
+ public ContentValues getValues() {
+ return mValues;
+ }
+ }
+
+ /**
+ * A voicemail status editor that the decision of whether to actually write to the database can
+ * be deferred. This object will be passed around as a usual {@link Editor}, but {@link
+ * #apply()} doesn't do anything. If later the creator of this object decides any status changes
+ * written to it should be committed, {@link #deferredApply()} should be called.
+ */
+ public static class DeferredEditor extends Editor {
+
+ private DeferredEditor(Context context, PhoneAccountHandle phoneAccountHandle) {
+ super(context, phoneAccountHandle);
+ }
+
+ @Override
+ public boolean apply() {
+ // Do nothing
+ return true;
+ }
+
+ public void deferredApply() {
+ super.apply();
+ }
+ }
+
+ public static Editor edit(Context context, PhoneAccountHandle phoneAccountHandle) {
+ return new Editor(context, phoneAccountHandle);
+ }
+
+ /**
+ * Reset the status to the "disabled" state, which the UI should not show anything for this
+ * subId.
+ */
+ public static void disable(Context context, PhoneAccountHandle phoneAccountHandle) {
+ edit(context, phoneAccountHandle)
+ .setConfigurationState(Status.CONFIGURATION_STATE_NOT_CONFIGURED)
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_NO_CONNECTION)
+ .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION)
+ .apply();
+ }
+
+ public static DeferredEditor deferredEdit(Context context,
+ PhoneAccountHandle phoneAccountHandle) {
+ return new DeferredEditor(context, phoneAccountHandle);
+ }
+}
diff --git a/src/com/android/phone/VoicemailUtils.java b/src/com/android/phone/VoicemailUtils.java
deleted file mode 100644
index f67c64b..0000000
--- a/src/com/android/phone/VoicemailUtils.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import android.content.Context;
-import android.provider.VoicemailContract;
-import android.provider.VoicemailContract.Status;
-import android.telecom.PhoneAccountHandle;
-
-public class VoicemailUtils {
-
- public static void setConfigurationState(Context context, PhoneAccountHandle accountHandle,
- int configurationState) {
- VoicemailContract.Status.setStatus(context, accountHandle,
- configurationState,
- Status.DATA_CHANNEL_STATE_IGNORE,
- Status.NOTIFICATION_CHANNEL_STATE_IGNORE);
- }
-
- public static void setDataChannelState(Context context, PhoneAccountHandle accountHandle,
- int dataChannelState) {
- VoicemailContract.Status.setStatus(context, accountHandle,
- Status.CONFIGURATION_STATE_IGNORE,
- dataChannelState,
- Status.NOTIFICATION_CHANNEL_STATE_IGNORE);
- }
-
- public static void setNotificationChannelState(Context context,
- PhoneAccountHandle accountHandle, int notificationChannelState) {
- VoicemailContract.Status.setStatus(context, accountHandle,
- Status.CONFIGURATION_STATE_IGNORE,
- Status.DATA_CHANNEL_STATE_IGNORE,
- notificationChannelState);
- }
-}
diff --git a/src/com/android/phone/common/mail/MailTransport.java b/src/com/android/phone/common/mail/MailTransport.java
index f452bab..47b273c 100644
--- a/src/com/android/phone/common/mail/MailTransport.java
+++ b/src/com/android/phone/common/mail/MailTransport.java
@@ -17,11 +17,11 @@
import android.content.Context;
import android.net.Network;
-import android.provider.VoicemailContract.Status;
import com.android.internal.annotations.VisibleForTesting;
import com.android.phone.common.mail.store.ImapStore;
import com.android.phone.common.mail.utils.LogUtils;
+import com.android.phone.vvm.omtp.OmtpEvents;
import com.android.phone.vvm.omtp.imap.ImapHelper;
import java.io.BufferedInputStream;
@@ -32,7 +32,6 @@
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
-import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
@@ -66,6 +65,7 @@
private BufferedOutputStream mOut;
private final int mFlags;
private SocketCreator mSocketCreator;
+ private InetSocketAddress mAddress;
public MailTransport(Context context, ImapHelper imapHelper, Network network, String address,
int port, int flags) {
@@ -117,7 +117,7 @@
}
} catch (IOException ioe) {
LogUtils.d(TAG, ioe.toString());
- mImapHelper.setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR);
+ mImapHelper.handleEvent(OmtpEvents.DATA_CANNOT_RESOLVE_HOST_ON_NETWORK);
throw new MessagingException(MessagingException.IOERROR, ioe.toString());
}
}
@@ -126,37 +126,28 @@
while (socketAddresses.size() > 0) {
mSocket = createSocket();
try {
- InetSocketAddress address = socketAddresses.remove(0);
- mSocket.connect(address, SOCKET_CONNECT_TIMEOUT);
+ mAddress = socketAddresses.remove(0);
+ mSocket.connect(mAddress, SOCKET_CONNECT_TIMEOUT);
if (canTrySslSecurity()) {
- /**
- * {@link SSLSocket} must connect in its constructor, or create through a
- * already connected socket. Since we need to use
- * {@link Socket#connect(SocketAddress, int) } to set timeout, we can only
- * create it here.
+ /*
+ SSLSocket cannot be created with a connection timeout, so instead of doing a
+ direct SSL connection, we connect with a normal connection and upgrade it into
+ SSL
*/
- LogUtils.d(TAG, "open: converting to SSL socket");
- mSocket = HttpsURLConnection.getDefaultSSLSocketFactory()
- .createSocket(mSocket, address.getHostName(), address.getPort(), true);
- // After the socket connects to an SSL server, confirm that the hostname is as
- // expected
- if (!canTrustAllCertificates()) {
- verifyHostname(mSocket, mHost);
- }
+ reopenTls();
+ } else {
+ mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
+ mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
+ mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
}
-
- mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
- mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
- mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
success = true;
return;
} catch (IOException ioe) {
LogUtils.d(TAG, ioe.toString());
if (socketAddresses.size() == 0) {
// Only throw an error when there are no more sockets to try.
- mImapHelper
- .setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR);
+ mImapHelper.handleEvent(OmtpEvents.DATA_ALL_SOCKET_CONNECTION_FAILED);
throw new MessagingException(MessagingException.IOERROR, ioe.toString());
}
} finally {
@@ -205,6 +196,32 @@
}
/**
+ * Attempts to reopen a normal connection into a TLS connection.
+ */
+ public void reopenTls() throws MessagingException {
+ try {
+ LogUtils.d(TAG, "open: converting to TLS socket");
+ mSocket = HttpsURLConnection.getDefaultSSLSocketFactory()
+ .createSocket(mSocket, mAddress.getHostName(), mAddress.getPort(), true);
+ // After the socket connects to an SSL server, confirm that the hostname is as
+ // expected
+ if (!canTrustAllCertificates()) {
+ verifyHostname(mSocket, mHost);
+ }
+ mSocket.setSoTimeout(SOCKET_READ_TIMEOUT);
+ mIn = new BufferedInputStream(mSocket.getInputStream(), 1024);
+ mOut = new BufferedOutputStream(mSocket.getOutputStream(), 512);
+
+ } catch (SSLException e) {
+ LogUtils.d(TAG, e.toString());
+ throw new CertificateValidationException(e.getMessage(), e);
+ } catch (IOException ioe) {
+ LogUtils.d(TAG, ioe.toString());
+ throw new MessagingException(MessagingException.IOERROR, ioe.toString());
+ }
+ }
+
+ /**
* Lightweight version of SSLCertificateSocketFactory.verifyHostname, which provides this
* service but is not in the public API.
*
@@ -229,7 +246,7 @@
SSLSession session = ssl.getSession();
if (session == null) {
- mImapHelper.setDataChannelState(Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR);
+ mImapHelper.handleEvent(OmtpEvents.DATA_CANNOT_ESTABLISH_SSL_SESSION);
throw new SSLException("Cannot verify SSL socket without session");
}
// TODO: Instead of reporting the name of the server we think we're connecting to,
@@ -237,7 +254,7 @@
// in the verifier code and is not available in the verifier API, and extracting the
// CN & alts is beyond the scope of this patch.
if (!HOSTNAME_VERIFIER.verify(hostname, session)) {
- mImapHelper.setDataChannelState(Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR);
+ mImapHelper.handleEvent(OmtpEvents.DATA_SSL_INVALID_HOST_NAME);
throw new SSLPeerUnverifiedException("Certificate hostname not useable for server: "
+ session.getPeerPrincipal());
}
@@ -272,6 +289,10 @@
mSocket = null;
}
+ public String getHost() {
+ return mHost;
+ }
+
public InputStream getInputStream() {
return mIn;
}
diff --git a/src/com/android/phone/common/mail/internet/MimeUtility.java b/src/com/android/phone/common/mail/internet/MimeUtility.java
index ba5036f..7402a4c 100644
--- a/src/com/android/phone/common/mail/internet/MimeUtility.java
+++ b/src/com/android/phone/common/mail/internet/MimeUtility.java
@@ -19,7 +19,6 @@
import android.util.Base64;
import android.util.Base64DataException;
import android.util.Base64InputStream;
-import android.util.Log;
import com.android.phone.common.mail.Body;
import com.android.phone.common.mail.BodyPart;
@@ -27,6 +26,7 @@
import com.android.phone.common.mail.MessagingException;
import com.android.phone.common.mail.Multipart;
import com.android.phone.common.mail.Part;
+import com.android.phone.vvm.omtp.VvmLog;
import org.apache.commons.io.IOUtils;
import org.apache.james.mime4j.codec.EncoderUtil;
@@ -267,14 +267,14 @@
* If we are not able to process the body there's nothing we can do about it. Return
* null and let the upper layers handle the missing content.
*/
- Log.e(LOG_TAG, "Unable to getTextFromPart " + oom.toString());
+ VvmLog.e(LOG_TAG, "Unable to getTextFromPart " + oom.toString());
}
catch (Exception e) {
/*
* If we are not able to process the body there's nothing we can do about it. Return
* null and let the upper layers handle the missing content.
*/
- Log.e(LOG_TAG, "Unable to getTextFromPart " + e.toString());
+ VvmLog.e(LOG_TAG, "Unable to getTextFromPart " + e.toString());
}
return null;
}
diff --git a/src/com/android/phone/common/mail/store/ImapConnection.java b/src/com/android/phone/common/mail/store/ImapConnection.java
index 9207aa9..af8773b 100644
--- a/src/com/android/phone/common/mail/store/ImapConnection.java
+++ b/src/com/android/phone/common/mail/store/ImapConnection.java
@@ -15,25 +15,27 @@
*/
package com.android.phone.common.mail.store;
-import android.provider.VoicemailContract.Status;
-import android.text.TextUtils;
-
+import android.util.ArraySet;
+import android.util.Base64;
import com.android.phone.common.mail.AuthenticationFailedException;
import com.android.phone.common.mail.CertificateValidationException;
import com.android.phone.common.mail.MailTransport;
import com.android.phone.common.mail.MessagingException;
+import com.android.phone.common.mail.store.ImapStore.ImapException;
+import com.android.phone.common.mail.store.imap.DigestMd5Utils;
import com.android.phone.common.mail.store.imap.ImapConstants;
import com.android.phone.common.mail.store.imap.ImapResponse;
import com.android.phone.common.mail.store.imap.ImapResponseParser;
import com.android.phone.common.mail.store.imap.ImapUtility;
import com.android.phone.common.mail.utils.LogUtils;
-import com.android.phone.common.mail.store.ImapStore.ImapException;
-
+import com.android.phone.vvm.omtp.OmtpEvents;
+import com.android.phone.vvm.omtp.VvmLog;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
-
import javax.net.ssl.SSLException;
/**
@@ -46,6 +48,7 @@
private ImapStore mImapStore;
private MailTransport mTransport;
private ImapResponseParser mParser;
+ private Set<String> mCapabilities = new ArraySet<>();
static final String IMAP_REDACTED_LOG = "[IMAP command redacted]";
@@ -87,7 +90,7 @@
return mLoginPhrase;
}
- void open() throws IOException, MessagingException {
+ public void open() throws IOException, MessagingException {
if (mTransport != null && mTransport.isOpen()) {
return;
}
@@ -102,28 +105,58 @@
createParser();
+ // The server should greet us with something like
+ // * OK IMAP4rev1 Server
+ // consume the response before doing anything else.
+ ImapResponse response = mParser.readResponse(false);
+ if (!response.isOk()) {
+ mImapStore.getImapHelper()
+ .handleEvent(OmtpEvents.DATA_INVALID_INITIAL_SERVER_RESPONSE);
+ throw new MessagingException(
+ MessagingException.AUTHENTICATION_FAILED_OR_SERVER_ERROR,
+ "Invalid server initial response");
+ }
+
+ queryCapability();
+
+ maybeDoStartTls();
+
// LOGIN
doLogin();
} catch (SSLException e) {
LogUtils.d(TAG, "SSLException ", e);
- mImapStore.getImapHelper().setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_ERROR);
+ mImapStore.getImapHelper().handleEvent(OmtpEvents.DATA_SSL_EXCEPTION);
throw new CertificateValidationException(e.getMessage(), e);
} catch (IOException ioe) {
LogUtils.d(TAG, "IOException", ioe);
- mImapStore.getImapHelper()
- .setDataChannelState(Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR);
+ mImapStore.getImapHelper().handleEvent(OmtpEvents.DATA_IOE_ON_OPEN);
throw ioe;
} finally {
destroyResponses();
}
}
+ void logout() {
+ try {
+ sendCommand(ImapConstants.LOGOUT, false);
+ if (!mParser.readResponse(true).is(0, ImapConstants.BYE)) {
+ VvmLog.e(TAG, "Server did not respond LOGOUT with BYE");
+ }
+ if (!mParser.readResponse(false).isOk()) {
+ VvmLog.e(TAG, "Server did not respond OK after LOGOUT");
+ }
+ } catch (IOException | MessagingException e) {
+ VvmLog.e(TAG, "Error while logging out:" + e);
+ }
+ }
+
/**
* Closes the connection and releases all resources. This connection can not be used again
* until {@link #setStore(ImapStore)} is called.
*/
void close() {
if (mTransport != null) {
+ logout();
mTransport.close();
mTransport = null;
}
@@ -133,30 +166,156 @@
}
/**
+ * Attempts to convert the connection into secure connection.
+ */
+ private void maybeDoStartTls() throws IOException, MessagingException {
+ // STARTTLS is required in the OMTP standard but not every implementation support it.
+ // Make sure the server does have this capability
+ if (hasCapability(ImapConstants.CAPABILITY_STARTTLS)) {
+ executeSimpleCommand(ImapConstants.STARTTLS);
+ mTransport.reopenTls();
+ createParser();
+ // The cached capabilities should be refreshed after TLS is established.
+ queryCapability();
+ }
+ }
+
+ /**
* Logs into the IMAP server
*/
private void doLogin() throws IOException, MessagingException, AuthenticationFailedException {
try {
- executeSimpleCommand(getLoginPhrase(), true);
+ if (mCapabilities.contains(ImapConstants.CAPABILITY_AUTH_DIGEST_MD5)) {
+ doDigestMd5Auth();
+ } else {
+ executeSimpleCommand(getLoginPhrase(), true);
+ }
} catch (ImapException ie) {
LogUtils.d(TAG, "ImapException", ie);
- final String status = ie.getStatus();
- final String code = ie.getResponseCode();
- final String alertText = ie.getAlertText();
+ String status = ie.getStatus();
+ String statusMessage = ie.getStatusMessage();
+ String alertText = ie.getAlertText();
- // if the response code indicates expired or bad credentials, throw a special exception
- if (ImapConstants.AUTHENTICATIONFAILED.equals(code) ||
- ImapConstants.EXPIRED.equals(code) ||
- (ImapConstants.NO.equals(status) && TextUtils.isEmpty(code))) {
- mImapStore.getImapHelper()
- .setDataChannelState(Status.DATA_CHANNEL_STATE_BAD_CONFIGURATION);
+ if (ImapConstants.NO.equals(status)) {
+ switch (statusMessage) {
+ case ImapConstants.NO_UNKNOWN_USER:
+ mImapStore.getImapHelper().handleEvent(OmtpEvents.DATA_AUTH_UNKNOWN_USER);
+ break;
+ case ImapConstants.NO_UNKNOWN_CLIENT:
+ mImapStore.getImapHelper().handleEvent(OmtpEvents.DATA_AUTH_UNKNOWN_DEVICE);
+ break;
+ case ImapConstants.NO_INVALID_PASSWORD:
+ mImapStore.getImapHelper()
+ .handleEvent(OmtpEvents.DATA_AUTH_INVALID_PASSWORD);
+ break;
+ case ImapConstants.NO_MAILBOX_NOT_INITIALIZED:
+ mImapStore.getImapHelper()
+ .handleEvent(OmtpEvents.DATA_AUTH_MAILBOX_NOT_INITIALIZED);
+ break;
+ case ImapConstants.NO_SERVICE_IS_NOT_PROVISIONED:
+ mImapStore.getImapHelper()
+ .handleEvent(OmtpEvents.DATA_AUTH_SERVICE_NOT_PROVISIONED);
+ break;
+ case ImapConstants.NO_SERVICE_IS_NOT_ACTIVATED:
+ mImapStore.getImapHelper()
+ .handleEvent(OmtpEvents.DATA_AUTH_SERVICE_NOT_ACTIVATED);
+ break;
+ case ImapConstants.NO_USER_IS_BLOCKED:
+ mImapStore.getImapHelper()
+ .handleEvent(OmtpEvents.DATA_AUTH_USER_IS_BLOCKED);
+ break;
+ case ImapConstants.NO_APPLICATION_ERROR:
+ mImapStore.getImapHelper()
+ .handleEvent(OmtpEvents.DATA_REJECTED_SERVER_RESPONSE);
+ default:
+ mImapStore.getImapHelper().handleEvent(OmtpEvents.DATA_BAD_IMAP_CREDENTIAL);
+ }
throw new AuthenticationFailedException(alertText, ie);
}
+ mImapStore.getImapHelper().handleEvent(OmtpEvents.DATA_REJECTED_SERVER_RESPONSE);
throw new MessagingException(alertText, ie);
}
}
+ private void doDigestMd5Auth() throws IOException, MessagingException {
+
+ // Initiate the authentication.
+ // The server will issue us a challenge, asking to run MD5 on the nonce with our password
+ // and other data, including the cnonce we randomly generated.
+ //
+ // C: a AUTHENTICATE DIGEST-MD5
+ // S: (BASE64) realm="elwood.innosoft.com",nonce="OA6MG9tEQGm2hh",qop="auth",
+ // algorithm=md5-sess,charset=utf-8
+ List<ImapResponse> responses = executeSimpleCommand(
+ ImapConstants.AUTHENTICATE + " " + ImapConstants.AUTH_DIGEST_MD5);
+ String decodedChallenge = decodeBase64(responses.get(0).getStringOrEmpty(0).getString());
+
+ Map<String, String> challenge = DigestMd5Utils.parseDigestMessage(decodedChallenge);
+ DigestMd5Utils.Data data = new DigestMd5Utils.Data(mImapStore, mTransport, challenge);
+
+ String response = data.createResponse();
+ // Respond to the challenge. If the server accepts it, it will reply a response-auth which
+ // is the MD5 of our password and the cnonce we've provided, to prove the server does know
+ // the password.
+ //
+ // C: (BASE64) charset=utf-8,username="chris",realm="elwood.innosoft.com",
+ // nonce="OA6MG9tEQGm2hh",nc=00000001,cnonce="OA6MHXh6VqTrRk",
+ // digest-uri="imap/elwood.innosoft.com",
+ // response=d388dad90d4bbd760a152321f2143af7,qop=auth
+ // S: (BASE64) rspauth=ea40f60335c427b5527b84dbabcdfffd
+
+ responses = executeContinuationResponse(encodeBase64(response), true);
+
+ // Verify response-auth.
+ // If failed verifyResponseAuth() will throw a MessagingException, terminating the
+ // connection
+ String decodedResponseAuth = decodeBase64(responses.get(0).getStringOrEmpty(0).getString());
+ data.verifyResponseAuth(decodedResponseAuth);
+
+ // Send a empty response to indicate we've accepted the response-auth
+ //
+ // C: (empty)
+ // S: a OK User logged in
+ executeContinuationResponse("", false);
+
+ }
+
+ private static String decodeBase64(String string) {
+ return new String(Base64.decode(string, Base64.DEFAULT));
+ }
+
+ private static String encodeBase64(String string) {
+ return Base64.encodeToString(string.getBytes(), Base64.NO_WRAP);
+ }
+
+ private void queryCapability() throws IOException, MessagingException {
+ List<ImapResponse> responses = executeSimpleCommand(ImapConstants.CAPABILITY);
+ mCapabilities.clear();
+ Set<String> disabledCapabilities = mImapStore.getImapHelper().getConfig()
+ .getDisabledCapabilities();
+ for (ImapResponse response : responses) {
+ if (response.isTagged()) {
+ continue;
+ }
+ for (int i = 0; i < response.size(); i++) {
+ String capability = response.getStringOrEmpty(i).getString();
+ if (disabledCapabilities != null) {
+ if (!disabledCapabilities.contains(capability)) {
+ mCapabilities.add(capability);
+ }
+ } else {
+ mCapabilities.add(capability);
+ }
+ }
+ }
+
+ LogUtils.d(TAG, "Capabilities: " + mCapabilities.toString());
+ }
+
+ private boolean hasCapability(String capability) {
+ return mCapabilities.contains(capability);
+ }
/**
* Create an {@link ImapResponseParser} from {@code mTransport.getInputStream()} and
* set it to {@link #mParser}.
@@ -170,17 +329,17 @@
}
- void destroyResponses() {
+ public void destroyResponses() {
if (mParser != null) {
mParser.destroyResponses();
}
}
- ImapResponse readResponse() throws IOException, MessagingException {
- return mParser.readResponse();
+ public ImapResponse readResponse() throws IOException, MessagingException {
+ return mParser.readResponse(false);
}
- List<ImapResponse> executeSimpleCommand(String command)
+ public List<ImapResponse> executeSimpleCommand(String command)
throws IOException, MessagingException{
return executeSimpleCommand(command, false);
}
@@ -197,7 +356,7 @@
* @throws IOException
* @throws MessagingException
*/
- List<ImapResponse> executeSimpleCommand(String command, boolean sensitive)
+ public List<ImapResponse> executeSimpleCommand(String command, boolean sensitive)
throws IOException, MessagingException {
// TODO: It may be nice to catch IOExceptions and close the connection here.
// Currently, we expect callers to do that, but if they fail to we'll be in a broken state.
@@ -205,7 +364,8 @@
return getCommandResponses();
}
- String sendCommand(String command, boolean sensitive) throws IOException, MessagingException {
+ public String sendCommand(String command, boolean sensitive)
+ throws IOException, MessagingException {
open();
if (mTransport == null) {
@@ -214,10 +374,15 @@
String tag = Integer.toString(mNextCommandTag.incrementAndGet());
String commandToSend = tag + " " + command;
mTransport.writeLine(commandToSend, (sensitive ? IMAP_REDACTED_LOG : command));
-
return tag;
}
+ List<ImapResponse> executeContinuationResponse(String response, boolean sensitive)
+ throws IOException, MessagingException {
+ mTransport.writeLine(response, (sensitive ? IMAP_REDACTED_LOG : response));
+ return getCommandResponses();
+ }
+
/**
* Read and return all of the responses from the most recent command sent to the server
*
@@ -225,27 +390,23 @@
* @throws IOException
* @throws MessagingException
*/
- List<ImapResponse> getCommandResponses() throws IOException, MessagingException {
+ List<ImapResponse> getCommandResponses()
+ throws IOException, MessagingException {
final List<ImapResponse> responses = new ArrayList<ImapResponse>();
ImapResponse response;
do {
- response = mParser.readResponse();
+ response = mParser.readResponse(false);
responses.add(response);
- } while (!response.isTagged());
+ } while (!(response.isTagged() || response.isContinuationRequest()));
- if (!response.isOk()) {
+ if (!(response.isOk() || response.isContinuationRequest())) {
final String toString = response.toString();
final String status = response.getStatusOrEmpty().getString();
+ final String statusMessage = response.getStatusResponseTextOrEmpty().getString();
final String alert = response.getAlertTextOrEmpty().getString();
final String responseCode = response.getResponseCodeOrEmpty().getString();
destroyResponses();
- mImapStore.getImapHelper().setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_ERROR);
- // if the response code indicates an error occurred within the server, indicate that
- if (ImapConstants.UNAVAILABLE.equals(responseCode)) {
-
- throw new MessagingException(MessagingException.SERVER_ERROR, alert);
- }
- throw new ImapException(toString, status, alert, responseCode);
+ throw new ImapException(toString, status, statusMessage, alert, responseCode);
}
return responses;
}
diff --git a/src/com/android/phone/common/mail/store/ImapFolder.java b/src/com/android/phone/common/mail/store/ImapFolder.java
index 13c7424..4abb7f5 100644
--- a/src/com/android/phone/common/mail/store/ImapFolder.java
+++ b/src/com/android/phone/common/mail/store/ImapFolder.java
@@ -17,14 +17,8 @@
import android.annotation.Nullable;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.provider.VoicemailContract;
-import android.provider.VoicemailContract.Status;
-import android.telecom.Voicemail;
import android.text.TextUtils;
import android.util.Base64DataException;
-import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.phone.common.R;
@@ -49,6 +43,7 @@
import com.android.phone.common.mail.store.imap.ImapString;
import com.android.phone.common.mail.utils.LogUtils;
import com.android.phone.common.mail.utils.Utility;
+import com.android.phone.vvm.omtp.OmtpEvents;
import java.io.IOException;
import java.io.InputStream;
@@ -99,22 +94,7 @@
public void open(String mode) throws MessagingException {
try {
if (isOpen()) {
- if (mMode == mode) {
- // Make sure the connection is valid.
- // If it's not we'll close it down and continue on to get a new one.
- try {
- mConnection.executeSimpleCommand(ImapConstants.NOOP);
- return;
-
- } catch (IOException ioe) {
- ioExceptionHandler(mConnection, ioe);
- } finally {
- destroyResponses();
- }
- } else {
- // Return the connection to the pool, if exists.
- close(false);
- }
+ throw new AssertionError("Duplicated open on ImapFolder");
}
synchronized (this) {
mConnection = mStore.getConnection();
@@ -165,7 +145,6 @@
}
mMessageCount = -1;
synchronized (this) {
- mStore.closeConnection();
mConnection = null;
}
}
@@ -207,6 +186,7 @@
return Utility.EMPTY_STRINGS; // Not found
} catch (IOException ioe) {
LogUtils.d(TAG, "IOException in search: " + searchCriteria, ioe);
+ mStore.getImapHelper().handleEvent(OmtpEvents.DATA_GENERIC_IMAP_IOE);
throw ioExceptionHandler(mConnection, ioe);
}
} finally {
@@ -432,6 +412,7 @@
}
} while (!response.isTagged());
} catch (IOException ioe) {
+ mStore.getImapHelper().handleEvent(OmtpEvents.DATA_GENERIC_IMAP_IOE);
throw ioExceptionHandler(mConnection, ioe);
}
}
@@ -667,6 +648,7 @@
try {
handleUntaggedResponses(mConnection.executeSimpleCommand(ImapConstants.EXPUNGE));
} catch (IOException ioe) {
+ mStore.getImapHelper().handleEvent(OmtpEvents.DATA_GENERIC_IMAP_IOE);
throw ioExceptionHandler(mConnection, ioe);
} finally {
destroyResponses();
@@ -703,6 +685,7 @@
allFlags));
} catch (IOException ioe) {
+ mStore.getImapHelper().handleEvent(OmtpEvents.DATA_GENERIC_IMAP_IOE);
throw ioExceptionHandler(mConnection, ioe);
} finally {
destroyResponses();
@@ -731,7 +714,7 @@
mMode = MODE_READ_WRITE;
}
} else if (response.isTagged()) { // Not OK
- mStore.getImapHelper().setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_ERROR);
+ mStore.getImapHelper().handleEvent(OmtpEvents.DATA_MAILBOX_OPEN_FAILED);
throw new MessagingException("Can't open mailbox: "
+ response.getStatusResponseTextOrEmpty());
}
@@ -774,6 +757,7 @@
}
}
} catch (IOException ioe) {
+ mStore.getImapHelper().handleEvent(OmtpEvents.DATA_GENERIC_IMAP_IOE);
throw ioExceptionHandler(mConnection, ioe);
} finally {
destroyResponses();
@@ -794,7 +778,6 @@
mConnection = null; // To prevent close() from returning the connection to the pool.
close(false);
}
- mStore.getImapHelper().setDataChannelState(Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR);
return new MessagingException(MessagingException.IOERROR, "IO Error", ioe);
}
diff --git a/src/com/android/phone/common/mail/store/ImapStore.java b/src/com/android/phone/common/mail/store/ImapStore.java
index c8095e5..179d0f2 100644
--- a/src/com/android/phone/common/mail/store/ImapStore.java
+++ b/src/com/android/phone/common/mail/store/ImapStore.java
@@ -130,13 +130,15 @@
private static final long serialVersionUID = 1L;
private final String mStatus;
+ private final String mStatusMessage;
private final String mAlertText;
private final String mResponseCode;
- public ImapException(String message, String status, String alertText,
+ public ImapException(String message, String status, String statusMessage, String alertText,
String responseCode) {
super(message);
mStatus = status;
+ mStatusMessage = statusMessage;
mAlertText = alertText;
mResponseCode = responseCode;
}
@@ -145,6 +147,10 @@
return mStatus;
}
+ public String getStatusMessage() {
+ return mStatusMessage;
+ }
+
public String getAlertText() {
return mAlertText;
}
diff --git a/src/com/android/phone/common/mail/store/imap/DigestMd5Utils.java b/src/com/android/phone/common/mail/store/imap/DigestMd5Utils.java
new file mode 100644
index 0000000..f78dbdf
--- /dev/null
+++ b/src/com/android/phone/common/mail/store/imap/DigestMd5Utils.java
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2016 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.common.mail.store.imap;
+
+import android.annotation.Nullable;
+import android.util.ArrayMap;
+import android.util.Base64;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.common.mail.MailTransport;
+import com.android.phone.common.mail.MessagingException;
+import com.android.phone.common.mail.store.ImapStore;
+import com.android.phone.vvm.omtp.VvmLog;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Map;
+
+public class DigestMd5Utils {
+
+ private static final String TAG = "DigestMd5Utils";
+
+ private static final String DIGEST_CHARSET = "CHARSET";
+ private static final String DIGEST_USERNAME = "username";
+ private static final String DIGEST_REALM = "realm";
+ private static final String DIGEST_NONCE = "nonce";
+ private static final String DIGEST_NC = "nc";
+ private static final String DIGEST_CNONCE = "cnonce";
+ private static final String DIGEST_URI = "digest-uri";
+ private static final String DIGEST_RESPONSE = "response";
+ private static final String DIGEST_QOP = "qop";
+
+ private static final String RESPONSE_AUTH_HEADER = "rspauth=";
+ private static final String HEX_CHARS = "0123456789abcdef";
+
+ /**
+ * Represents the set of data we need to generate the DIGEST-MD5 response.
+ */
+ public static class Data {
+
+ private static final String CHARSET = "utf-8'";
+
+ public String username;
+ public String password;
+ public String realm;
+ public String nonce;
+ public String nc;
+ public String cnonce;
+ public String digestUri;
+ public String qop;
+
+ @VisibleForTesting
+ Data() {
+ // Do nothing
+ }
+
+ public Data(ImapStore imapStore, MailTransport transport, Map<String, String> challenge) {
+ username = imapStore.getUsername();
+ password = imapStore.getPassword();
+ realm = challenge.getOrDefault(DIGEST_REALM, "");
+ nonce = challenge.get(DIGEST_NONCE);
+ cnonce = createCnonce();
+ nc = "00000001"; // Subsequent Authentication not supported, nounce count always 1.
+ qop = "auth"; // Other config not supported
+ digestUri = "imap/" + transport.getHost();
+ }
+
+ private static String createCnonce() {
+ SecureRandom generator = new SecureRandom();
+
+ // At least 64 bits of entropy is required
+ byte[] rawBytes = new byte[8];
+ generator.nextBytes(rawBytes);
+
+ return Base64.encodeToString(rawBytes, Base64.NO_WRAP);
+ }
+
+ /**
+ * Verify the response-auth returned by the server is correct.
+ */
+ public void verifyResponseAuth(String response)
+ throws MessagingException {
+ if (!response.startsWith(RESPONSE_AUTH_HEADER)) {
+ throw new MessagingException("response-auth expected");
+ }
+ if (!response.substring(RESPONSE_AUTH_HEADER.length())
+ .equals(DigestMd5Utils.getResponse(this, true))) {
+ throw new MessagingException("invalid response-auth return from the server.");
+ }
+ }
+
+ public String createResponse() {
+ String response = getResponse(this, false);
+ ResponseBuilder builder = new ResponseBuilder();
+ builder
+ .append(DIGEST_CHARSET, CHARSET)
+ .appendQuoted(DIGEST_USERNAME, username)
+ .appendQuoted(DIGEST_REALM, realm)
+ .appendQuoted(DIGEST_NONCE, nonce)
+ .append(DIGEST_NC, nc)
+ .appendQuoted(DIGEST_CNONCE, cnonce)
+ .appendQuoted(DIGEST_URI, digestUri)
+ .append(DIGEST_RESPONSE, response)
+ .append(DIGEST_QOP, qop);
+ return builder.toString();
+ }
+
+ private static class ResponseBuilder {
+
+ private StringBuilder mBuilder = new StringBuilder();
+
+ public ResponseBuilder appendQuoted(String key, String value) {
+ if (mBuilder.length() != 0) {
+ mBuilder.append(",");
+ }
+ mBuilder.append(key).append("=\"").append(value).append("\"");
+ return this;
+ }
+
+ public ResponseBuilder append(String key, String value) {
+ if (mBuilder.length() != 0) {
+ mBuilder.append(",");
+ }
+ mBuilder.append(key).append("=").append(value);
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return mBuilder.toString();
+ }
+ }
+ }
+
+ /*
+ response-value =
+ toHex( getKeyDigest ( toHex(getMd5(a1)),
+ { nonce-value, ":" nc-value, ":",
+ cnonce-value, ":", qop-value, ":", toHex(getMd5(a2)) }))
+ * @param isResponseAuth is the response the one the server is returning us. response-auth has
+ * different a2 format.
+ */
+ @VisibleForTesting
+ static String getResponse(Data data, boolean isResponseAuth) {
+ StringBuilder a1 = new StringBuilder();
+ a1.append(new String(
+ getMd5(data.username + ":" + data.realm + ":" + data.password),
+ StandardCharsets.ISO_8859_1));
+ a1.append(":").append(data.nonce).append(":").append(data.cnonce);
+
+ StringBuilder a2 = new StringBuilder();
+ if (!isResponseAuth) {
+ a2.append("AUTHENTICATE");
+ }
+ a2.append(":").append(data.digestUri);
+
+ return toHex(getKeyDigest(
+ toHex(getMd5(a1.toString())),
+ data.nonce + ":" + data.nc + ":" + data.cnonce + ":" + data.qop + ":" + toHex(
+ getMd5(a2.toString()))
+ ));
+ }
+
+ /**
+ * Let getMd5(s) be the 16 octet MD5 hash [RFC 1321] of the octet string s.
+ */
+ private static byte[] getMd5(String s) {
+ try {
+ MessageDigest digester = MessageDigest.getInstance("MD5");
+ digester.update(s.getBytes(StandardCharsets.ISO_8859_1));
+ return digester.digest();
+ } catch (NoSuchAlgorithmException e) {
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
+ * Let getKeyDigest(k, s) be getMd5({k, ":", s}), i.e., the 16 octet hash of the string k, a colon and the
+ * string s.
+ */
+ private static byte[] getKeyDigest(String k, String s) {
+ StringBuilder builder = new StringBuilder(k).append(":").append(s);
+ return getMd5(builder.toString());
+ }
+
+ /**
+ * Let toHex(n) be the representation of the 16 octet MD5 hash n as a string of 32 hex digits
+ * (with alphabetic characters always in lower case, since MD5 is case sensitive).
+ */
+ private static String toHex(byte[] n) {
+ StringBuilder result = new StringBuilder();
+ for (byte b : n) {
+ int unsignedByte = b & 0xFF;
+ result.append(HEX_CHARS.charAt(unsignedByte / 16))
+ .append(HEX_CHARS.charAt(unsignedByte % 16));
+ }
+ return result.toString();
+ }
+
+ public static Map<String, String> parseDigestMessage(String message) throws MessagingException {
+ Map<String, String> result = new DigestMessageParser(message).parse();
+ if (!result.containsKey(DIGEST_NONCE)) {
+ throw new MessagingException("nonce missing from server DIGEST-MD5 challenge");
+ }
+ return result;
+ }
+
+ /**
+ * Parse the key-value pair returned by the server.
+ */
+ private static class DigestMessageParser {
+
+ private final String mMessage;
+ private int mPosition = 0;
+ private Map<String, String> mResult = new ArrayMap<>();
+
+ public DigestMessageParser(String message) {
+ mMessage = message;
+ }
+
+ @Nullable
+ public Map<String, String> parse() {
+ try {
+ while (mPosition < mMessage.length()) {
+ parsePair();
+ if (mPosition != mMessage.length()) {
+ expect(',');
+ }
+ }
+ } catch (IndexOutOfBoundsException e) {
+ VvmLog.e(TAG, e.toString());
+ return null;
+ }
+ return mResult;
+ }
+
+ private void parsePair() {
+ String key = parseKey();
+ expect('=');
+ String value = parseValue();
+ mResult.put(key, value);
+ }
+
+ private void expect(char c) {
+ if (pop() != c) {
+ throw new IllegalStateException(
+ "unexpected character " + mMessage.charAt(mPosition));
+ }
+ }
+
+ private char pop() {
+ char result = peek();
+ mPosition++;
+ return result;
+ }
+
+ private char peek() {
+ return mMessage.charAt(mPosition);
+ }
+
+ private void goToNext(char c) {
+ while (peek() != c) {
+ mPosition++;
+ }
+ }
+
+ private String parseKey() {
+ int start = mPosition;
+ goToNext('=');
+ return mMessage.substring(start, mPosition);
+ }
+
+ private String parseValue() {
+ if (peek() == '"') {
+ return parseQuotedValue();
+ } else {
+ return parseUnquotedValue();
+ }
+ }
+
+ private String parseQuotedValue() {
+ expect('"');
+ StringBuilder result = new StringBuilder();
+ while (true) {
+ char c = pop();
+ if (c == '\\') {
+ result.append(pop());
+ } else if (c == '"') {
+ break;
+ } else {
+ result.append(c);
+ }
+ }
+ return result.toString();
+ }
+
+ private String parseUnquotedValue() {
+ StringBuilder result = new StringBuilder();
+ while (true) {
+ char c = pop();
+ if (c == '\\') {
+ result.append(pop());
+ } else if (c == ',') {
+ mPosition--;
+ break;
+ } else {
+ result.append(c);
+ }
+
+ if (mPosition == mMessage.length()) {
+ break;
+ }
+ }
+ return result.toString();
+ }
+ }
+}
diff --git a/src/com/android/phone/common/mail/store/imap/ImapConstants.java b/src/com/android/phone/common/mail/store/imap/ImapConstants.java
index 63dda8c..a2eab13 100644
--- a/src/com/android/phone/common/mail/store/imap/ImapConstants.java
+++ b/src/com/android/phone/common/mail/store/imap/ImapConstants.java
@@ -98,6 +98,32 @@
public static final String NIL = "NIL";
/**
+ * NO responses
+ */
+ public static final String NO_COMMAND_NOT_ALLOWED = "command not allowed";
+ public static final String NO_RESERVATION_FAILED = "reservation failed";
+ public static final String NO_APPLICATION_ERROR = "application error";
+ public static final String NO_INVALID_PARAMETER = "invalid parameter";
+ public static final String NO_INVALID_COMMAND = "invalid command";
+ public static final String NO_UNKNOWN_COMMAND = "unknown command";
+ // AUTHENTICATE
+ // The subscriber can not be located in the system.
+ public static final String NO_UNKNOWN_USER = "unknown user";
+ // The Client Type or Protocol Version is unknown.
+ public static final String NO_UNKNOWN_CLIENT = "unknown client";
+ // The password received from the client does not match the password defined in the subscriber's profile.
+ public static final String NO_INVALID_PASSWORD = "invalid password";
+ // The subscriber's mailbox has not yet been initialised via the TUI
+ public static final String NO_MAILBOX_NOT_INITIALIZED = "mailbox not initialized";
+ // The subscriber has not been provisioned for the VVM service.
+ public static final String NO_SERVICE_IS_NOT_PROVISIONED =
+ "service is not provisioned";
+ // The subscriber is provisioned for the VVM service but the VVM service is currently not active
+ public static final String NO_SERVICE_IS_NOT_ACTIVATED = "service is not activated";
+ // The Voice Mail Blocked flag in the subscriber's profile is set to YES.
+ public static final String NO_USER_IS_BLOCKED = "user is blocked";
+
+ /**
* extensions
*/
public static final String GETQUOTA = "GETQUOTA";
@@ -105,8 +131,14 @@
public static final String QUOTAROOT = "QUOTAROOT";
public static final String QUOTA = "QUOTA";
- /** response codes within IMAP responses */
- public static final String EXPIRED = "EXPIRED";
- public static final String AUTHENTICATIONFAILED = "AUTHENTICATIONFAILED";
- public static final String UNAVAILABLE = "UNAVAILABLE";
+ /**
+ * capabilities
+ */
+ public static final String CAPABILITY_AUTH_DIGEST_MD5 = "AUTH=DIGEST-MD5";
+ public static final String CAPABILITY_STARTTLS = "STARTTLS";
+
+ /**
+ * authentication
+ */
+ public static final String AUTH_DIGEST_MD5 = "DIGEST-MD5";
}
\ No newline at end of file
diff --git a/src/com/android/phone/common/mail/store/imap/ImapMemoryLiteral.java b/src/com/android/phone/common/mail/store/imap/ImapMemoryLiteral.java
index aac66c2..4811590 100644
--- a/src/com/android/phone/common/mail/store/imap/ImapMemoryLiteral.java
+++ b/src/com/android/phone/common/mail/store/imap/ImapMemoryLiteral.java
@@ -16,9 +16,8 @@
package com.android.phone.common.mail.store.imap;
-import android.util.Log;
-
import com.android.phone.common.mail.FixedLengthInputStream;
+import com.android.phone.vvm.omtp.VvmLog;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -45,7 +44,7 @@
pos += read;
}
if (pos != mData.length) {
- Log.w(TAG, "");
+ VvmLog.w(TAG, "length mismatch");
}
}
@@ -60,7 +59,7 @@
try {
return new String(mData, "US-ASCII");
} catch (UnsupportedEncodingException e) {
- Log.e(TAG, "Unsupported encoding: ", e);
+ VvmLog.e(TAG, "Unsupported encoding: ", e);
}
return null;
}
diff --git a/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java b/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
index d0413df..6fc5abe 100644
--- a/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
+++ b/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
@@ -22,6 +22,7 @@
import com.android.phone.common.mail.FixedLengthInputStream;
import com.android.phone.common.mail.MessagingException;
import com.android.phone.common.mail.PeekableInputStream;
+import com.android.phone.vvm.omtp.VvmLog;
import java.io.IOException;
import java.io.InputStream;
@@ -83,9 +84,7 @@
private static IOException newEOSException() {
final String message = "End of stream reached";
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, message);
- }
+ VvmLog.d(TAG, message);
return new IOException(message);
}
@@ -137,16 +136,15 @@
* is stored in the internal storage. When the {@link ImapResponse} is no longer used
* {@link #destroyResponses} should be called to destroy all the responses in the array.
*
+ * @param byeExpected is a untagged BYE response expected? If not proper cleanup will be done
+ * and {@link ByeException} will be thrown.
* @return the parsed {@link ImapResponse} object.
- * @exception ByeException when detects BYE.
+ * @exception ByeException when detects BYE and <code>byeExpected</code> is false.
*/
- public ImapResponse readResponse() throws IOException, MessagingException {
+ public ImapResponse readResponse(boolean byeExpected) throws IOException, MessagingException {
ImapResponse response = null;
try {
response = parseResponse();
- if (Log.isLoggable(TAG, Log.DEBUG)) {
- Log.d(TAG, "<<< " + response.toString());
- }
} catch (RuntimeException e) {
// Parser crash -- log network activities.
onParseError(e);
@@ -158,7 +156,7 @@
}
// Handle this outside of try-catch. We don't have to dump protocol log when getting BYE.
- if (response.is(0, ImapConstants.BYE)) {
+ if (!byeExpected && response.is(0, ImapConstants.BYE)) {
Log.w(TAG, ByeException.MESSAGE);
response.destroy();
throw new ByeException();
@@ -183,7 +181,7 @@
}
} catch (IOException ignore) {
}
- Log.w(TAG, "Exception detected: " + e.getMessage());
+ VvmLog.w(TAG, "Exception detected: " + e.getMessage());
}
/**
diff --git a/src/com/android/phone/common/mail/store/imap/ImapSimpleString.java b/src/com/android/phone/common/mail/store/imap/ImapSimpleString.java
index 3d5263b..9d65236 100644
--- a/src/com/android/phone/common/mail/store/imap/ImapSimpleString.java
+++ b/src/com/android/phone/common/mail/store/imap/ImapSimpleString.java
@@ -16,7 +16,7 @@
package com.android.phone.common.mail.store.imap;
-import android.util.Log;
+import com.android.phone.vvm.omtp.VvmLog;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@@ -49,7 +49,7 @@
try {
return new ByteArrayInputStream(mString.getBytes("US-ASCII"));
} catch (UnsupportedEncodingException e) {
- Log.e(TAG, "Unsupported encoding: ", e);
+ VvmLog.e(TAG, "Unsupported encoding: ", e);
}
return null;
}
diff --git a/src/com/android/phone/common/mail/store/imap/ImapString.java b/src/com/android/phone/common/mail/store/imap/ImapString.java
index a33ba24..dd7133c 100644
--- a/src/com/android/phone/common/mail/store/imap/ImapString.java
+++ b/src/com/android/phone/common/mail/store/imap/ImapString.java
@@ -16,7 +16,7 @@
package com.android.phone.common.mail.store.imap;
-import android.util.Log;
+import com.android.phone.vvm.omtp.VvmLog;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@@ -137,7 +137,7 @@
mParsedDate = DATE_TIME_FORMAT.parse(getString());
return true;
} catch (ParseException e) {
- Log.w("ImapString", getString() + " can't be parsed as a date.");
+ VvmLog.w("ImapString", getString() + " can't be parsed as a date.");
return false;
}
}
diff --git a/src/com/android/phone/common/mail/utils/LogUtils.java b/src/com/android/phone/common/mail/utils/LogUtils.java
index 711af9b..6bd7be6 100644
--- a/src/com/android/phone/common/mail/utils/LogUtils.java
+++ b/src/com/android/phone/common/mail/utils/LogUtils.java
@@ -20,6 +20,7 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.vvm.omtp.VvmLog;
import java.util.List;
import java.util.regex.Pattern;
@@ -184,7 +185,7 @@
*/
public static int v(String tag, String format, Object... args) {
if (isLoggable(tag, VERBOSE)) {
- return Log.v(tag, String.format(format, args));
+ return VvmLog.v(tag, String.format(format, args));
}
return 0;
}
@@ -202,7 +203,7 @@
*/
public static int v(String tag, Throwable tr, String format, Object... args) {
if (isLoggable(tag, VERBOSE)) {
- return Log.v(tag, String.format(format, args), tr);
+ return VvmLog.v(tag, String.format(format, args), tr);
}
return 0;
}
@@ -219,7 +220,7 @@
*/
public static int d(String tag, String format, Object... args) {
if (isLoggable(tag, DEBUG)) {
- return Log.d(tag, String.format(format, args));
+ return VvmLog.d(tag, String.format(format, args));
}
return 0;
}
@@ -237,7 +238,7 @@
*/
public static int d(String tag, Throwable tr, String format, Object... args) {
if (isLoggable(tag, DEBUG)) {
- return Log.d(tag, String.format(format, args), tr);
+ return VvmLog.d(tag, String.format(format, args), tr);
}
return 0;
}
@@ -254,7 +255,7 @@
*/
public static int i(String tag, String format, Object... args) {
if (isLoggable(tag, INFO)) {
- return Log.i(tag, String.format(format, args));
+ return VvmLog.i(tag, String.format(format, args));
}
return 0;
}
@@ -272,7 +273,7 @@
*/
public static int i(String tag, Throwable tr, String format, Object... args) {
if (isLoggable(tag, INFO)) {
- return Log.i(tag, String.format(format, args), tr);
+ return VvmLog.i(tag, String.format(format, args), tr);
}
return 0;
}
@@ -289,7 +290,7 @@
*/
public static int w(String tag, String format, Object... args) {
if (isLoggable(tag, WARN)) {
- return Log.w(tag, String.format(format, args));
+ return VvmLog.w(tag, String.format(format, args));
}
return 0;
}
@@ -307,7 +308,7 @@
*/
public static int w(String tag, Throwable tr, String format, Object... args) {
if (isLoggable(tag, WARN)) {
- return Log.w(tag, String.format(format, args), tr);
+ return VvmLog.w(tag, String.format(format, args), tr);
}
return 0;
}
@@ -324,7 +325,7 @@
*/
public static int e(String tag, String format, Object... args) {
if (isLoggable(tag, ERROR)) {
- return Log.e(tag, String.format(format, args));
+ return VvmLog.e(tag, String.format(format, args));
}
return 0;
}
@@ -342,7 +343,7 @@
*/
public static int e(String tag, Throwable tr, String format, Object... args) {
if (isLoggable(tag, ERROR)) {
- return Log.e(tag, String.format(format, args), tr);
+ return VvmLog.e(tag, String.format(format, args), tr);
}
return 0;
}
@@ -362,7 +363,7 @@
* additional arguments are ignored.
*/
public static int wtf(String tag, String format, Object... args) {
- return Log.wtf(tag, String.format(format, args), new Error());
+ return VvmLog.wtf(tag, String.format(format, args), new Error());
}
/**
@@ -381,7 +382,7 @@
* additional arguments are ignored.
*/
public static int wtf(String tag, Throwable tr, String format, Object... args) {
- return Log.wtf(tag, String.format(format, args), tr);
+ return VvmLog.wtf(tag, String.format(format, args), tr);
}
diff --git a/src/com/android/phone/settings/VisualVoicemailSettingsUtil.java b/src/com/android/phone/settings/VisualVoicemailSettingsUtil.java
index 62abffd..22fb70e 100644
--- a/src/com/android/phone/settings/VisualVoicemailSettingsUtil.java
+++ b/src/com/android/phone/settings/VisualVoicemailSettingsUtil.java
@@ -16,156 +16,67 @@
package com.android.phone.settings;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
import android.telecom.PhoneAccountHandle;
-
-import com.android.internal.telephony.Phone;
-import com.android.phone.PhoneUtils;
-import com.android.phone.vvm.omtp.OmtpConstants;
-import com.android.phone.vvm.omtp.sms.StatusMessage;
+import com.android.phone.R;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VisualVoicemailPreferences;
+import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
/**
- * Save visual voicemail login values and whether or not a particular account is enabled in shared
- * preferences to be retrieved later.
- * Because a voicemail source is tied 1:1 to a phone account, the phone account handle is used in
- * the key for each voicemail source and the associated data.
+ * Save whether or not a particular account is enabled in shared to be retrieved later.
*/
public class VisualVoicemailSettingsUtil {
- private static final String VISUAL_VOICEMAIL_SHARED_PREFS_KEY_PREFIX =
- "visual_voicemail_";
private static final String IS_ENABLED_KEY = "is_enabled";
- // If a carrier vvm app is installed, Google visual voicemail is automatically switched off
- // however, the user can override this setting.
- private static final String IS_USER_SET = "is_user_set";
- // Record the timestamp of the last full sync so that duplicate syncs can be reduced.
- private static final String LAST_FULL_SYNC_TIMESTAMP = "last_full_sync_timestamp";
- // Constant indicating that there has never been a full sync.
- public static final long NO_PRIOR_FULL_SYNC = -1;
-
- // Setting for how often retries should be done.
- private static final String SYNC_RETRY_INTERVAL = "sync_retry_interval";
- private static final long MAX_SYNC_RETRY_INTERVAL_MS = 86400000; // 24 hours
- private static final long DEFAULT_SYNC_RETRY_INTERVAL_MS = 900000; // 15 minutes
- public static void setVisualVoicemailEnabled(Phone phone, boolean isEnabled,
- boolean isUserSet) {
- setVisualVoicemailEnabled(phone.getContext(), PhoneUtils.makePstnPhoneAccountHandle(phone),
- isEnabled, isUserSet);
+ public static void setEnabled(Context context, PhoneAccountHandle phoneAccount,
+ boolean isEnabled) {
+ new VisualVoicemailPreferences(context, phoneAccount).edit()
+ .putBoolean(IS_ENABLED_KEY, isEnabled)
+ .apply();
+ OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(context, phoneAccount);
+ if (isEnabled) {
+ OmtpVvmSourceManager.getInstance(context).addPhoneStateListener(phoneAccount);
+ config.startActivation();
+ } else {
+ OmtpVvmSourceManager.getInstance(context).removeSource(phoneAccount);
+ config.startDeactivation();
+ }
}
- public static void setVisualVoicemailEnabled(Context context, PhoneAccountHandle phoneAccount,
- boolean isEnabled, boolean isUserSet) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putBoolean(
- getVisualVoicemailSharedPrefsKey(IS_ENABLED_KEY, phoneAccount), isEnabled);
- editor.putBoolean(
- getVisualVoicemailSharedPrefsKey(IS_USER_SET, phoneAccount),
- isUserSet);
- editor.commit();
- }
-
- public static boolean isVisualVoicemailEnabled(Context context,
+ public static boolean isEnabled(Context context,
PhoneAccountHandle phoneAccount) {
if (phoneAccount == null) {
return false;
}
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- return prefs.getBoolean(getVisualVoicemailSharedPrefsKey(IS_ENABLED_KEY, phoneAccount),
- false);
- }
+ if (!context.getResources().getBoolean(R.bool.allow_visual_voicemail)) {
+ return false;
+ }
- public static boolean isVisualVoicemailEnabled(Phone phone) {
- return isVisualVoicemailEnabled(phone.getContext(),
- PhoneUtils.makePstnPhoneAccountHandle(phone));
+ VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
+ if (prefs.contains(IS_ENABLED_KEY)) {
+ // isEnableByDefault is a bit expensive, so don't use it as default value of
+ // getBoolean(). The "false" here should never be actually used.
+ return prefs.getBoolean(IS_ENABLED_KEY, false);
+ }
+ return new OmtpVvmCarrierConfigHelper(context,
+ PhoneAccountHandleConverter.toSubId(phoneAccount)).isEnabledByDefault();
}
/**
- * Differentiate user-enabled/disabled to know whether to ignore automatic enabling and
- * disabling by the system. This is relevant when a carrier vvm app is installed and the user
- * manually enables dialer visual voicemail. In that case we would want that setting to persist.
+ * Whether the client enabled status is explicitly set by user or by default(Whether carrier VVM
+ * app is installed). This is used to determine whether to disable the client when the carrier
+ * VVM app is installed. If the carrier VVM app is installed the client should give priority to
+ * it if the settings are not touched.
*/
- public static boolean isVisualVoicemailUserSet(Context context,
+ public static boolean isEnabledUserSet(Context context,
PhoneAccountHandle phoneAccount) {
if (phoneAccount == null) {
return false;
}
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- return prefs.getBoolean(
- getVisualVoicemailSharedPrefsKey(IS_USER_SET, phoneAccount),
- false);
- }
-
- public static void setVisualVoicemailCredentialsFromStatusMessage(Context context,
- PhoneAccountHandle phoneAccount, StatusMessage message) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- SharedPreferences.Editor editor = prefs.edit();
-
- editor.putString(
- getVisualVoicemailSharedPrefsKey(OmtpConstants.IMAP_PORT, phoneAccount),
- message.getImapPort());
- editor.putString(
- getVisualVoicemailSharedPrefsKey(OmtpConstants.SERVER_ADDRESS, phoneAccount),
- message.getServerAddress());
- editor.putString(
- getVisualVoicemailSharedPrefsKey(OmtpConstants.IMAP_USER_NAME, phoneAccount),
- message.getImapUserName());
- editor.putString(
- getVisualVoicemailSharedPrefsKey(OmtpConstants.IMAP_PASSWORD, phoneAccount),
- message.getImapPassword());
- editor.commit();
- }
-
- public static String getVisualVoicemailCredentials(Context context, String key,
- PhoneAccountHandle phoneAccount) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- return prefs.getString(getVisualVoicemailSharedPrefsKey(key, phoneAccount), null);
- }
-
- public static long getVisualVoicemailRetryInterval(Context context,
- PhoneAccountHandle phoneAccount) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- return prefs.getLong(getVisualVoicemailSharedPrefsKey(SYNC_RETRY_INTERVAL, phoneAccount),
- DEFAULT_SYNC_RETRY_INTERVAL_MS);
- }
-
- public static void resetVisualVoicemailRetryInterval(Context context,
- PhoneAccountHandle phoneAccount) {
- setVisualVoicemailRetryInterval(context, phoneAccount, DEFAULT_SYNC_RETRY_INTERVAL_MS);
- }
-
- public static void setVisualVoicemailRetryInterval(Context context,
- PhoneAccountHandle phoneAccount, long interval) {
- SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(context).edit();
- editor.putLong(getVisualVoicemailSharedPrefsKey(SYNC_RETRY_INTERVAL, phoneAccount),
- Math.min(interval, MAX_SYNC_RETRY_INTERVAL_MS));
- editor.commit();
- }
-
- public static void setVisualVoicemailLastFullSyncTime(Context context,
- PhoneAccountHandle phoneAccount, long timestamp) {
- SharedPreferences.Editor editor =
- PreferenceManager.getDefaultSharedPreferences(context).edit();
- editor.putLong(getVisualVoicemailSharedPrefsKey(LAST_FULL_SYNC_TIMESTAMP, phoneAccount),
- timestamp);
- editor.commit();
-
- }
-
- public static long getVisualVoicemailLastFullSyncTime(Context context,
- PhoneAccountHandle phoneAccount) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- return prefs.getLong(
- getVisualVoicemailSharedPrefsKey(LAST_FULL_SYNC_TIMESTAMP, phoneAccount),
- NO_PRIOR_FULL_SYNC);
- }
-
- public static String getVisualVoicemailSharedPrefsKey(String key,
- PhoneAccountHandle phoneAccount) {
- return VISUAL_VOICEMAIL_SHARED_PREFS_KEY_PREFIX + key + "_" + phoneAccount.getId();
+ VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phoneAccount);
+ return prefs.contains(IS_ENABLED_KEY);
}
}
diff --git a/src/com/android/phone/settings/VoicemailChangePinActivity.java b/src/com/android/phone/settings/VoicemailChangePinActivity.java
new file mode 100644
index 0000000..33da27a
--- /dev/null
+++ b/src/com/android/phone/settings/VoicemailChangePinActivity.java
@@ -0,0 +1,656 @@
+/*
+ * Copyright (C) 2016 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.settings;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnDismissListener;
+import android.content.SharedPreferences;
+import android.net.Network;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.preference.PreferenceManager;
+import android.telecom.PhoneAccountHandle;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.InputFilter.LengthFilter;
+import android.text.TextWatcher;
+import android.view.KeyEvent;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.WindowManager;
+import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+import android.widget.Toast;
+import com.android.phone.PhoneUtils;
+import com.android.phone.R;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.common.mail.MessagingException;
+import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.OmtpConstants.ChangePinResult;
+import com.android.phone.vvm.omtp.OmtpEvents;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VisualVoicemailPreferences;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.imap.ImapHelper;
+import com.android.phone.vvm.omtp.imap.ImapHelper.InitializingException;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequestCallback;
+
+/**
+ * Dialog to change the voicemail PIN. The TUI (Telephony User Interface) PIN is used when accessing
+ * traditional voicemail through phone call. The intent to launch this activity must contain {@link
+ * #EXTRA_PHONE_ACCOUNT_HANDLE}
+ */
+public class VoicemailChangePinActivity extends Activity implements OnClickListener,
+ OnEditorActionListener, TextWatcher {
+
+ private static final String TAG = "VmChangePinActivity";
+
+ public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "extra_phone_account_handle";
+
+ private static final String KEY_DEFAULT_OLD_PIN = "default_old_pin";
+
+ private static final int MESSAGE_HANDLE_RESULT = 1;
+
+ private PhoneAccountHandle mPhoneAccountHandle;
+ private OmtpVvmCarrierConfigHelper mConfig;
+
+ private int mPinMinLength;
+ private int mPinMaxLength;
+
+ private State mUiState = State.Initial;
+ private String mOldPin;
+ private String mFirstPin;
+
+ private ProgressDialog mProgressDialog;
+
+ private TextView mHeaderText;
+ private TextView mHintText;
+ private TextView mErrorText;
+ private EditText mPinEntry;
+ private Button mCancelButton;
+ private Button mNextButton;
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == MESSAGE_HANDLE_RESULT) {
+ mUiState.handleResult(VoicemailChangePinActivity.this, message.arg1);
+ }
+ }
+ };
+
+ private enum State {
+ /**
+ * Empty state to handle initial state transition. Will immediately switch into {@link
+ * #VerifyOldPin} if a default PIN has been set by the OMTP client, or {@link #EnterOldPin}
+ * if not.
+ */
+ Initial,
+ /**
+ * Prompt the user to enter old PIN. The PIN will be verified with the server before
+ * proceeding to {@link #EnterNewPin}.
+ */
+ EnterOldPin {
+ @Override
+ public void onEnter(VoicemailChangePinActivity activity) {
+ activity.setHeader(R.string.change_pin_enter_old_pin_header);
+ activity.mHintText.setText(R.string.change_pin_enter_old_pin_hint);
+ activity.mNextButton.setText(R.string.change_pin_continue_label);
+ activity.mErrorText.setText(null);
+ }
+
+ @Override
+ public void onInputChanged(VoicemailChangePinActivity activity) {
+ activity.setNextEnabled(activity.getCurrentPasswordInput().length() > 0);
+ }
+
+
+ @Override
+ public void handleNext(VoicemailChangePinActivity activity) {
+ activity.mOldPin = activity.getCurrentPasswordInput();
+ activity.verifyOldPin();
+ }
+
+ @Override
+ public void handleResult(VoicemailChangePinActivity activity,
+ @ChangePinResult int result) {
+ if (result == OmtpConstants.CHANGE_PIN_SUCCESS) {
+ activity.updateState(State.EnterNewPin);
+ } else {
+ CharSequence message = activity.getChangePinResultMessage(result);
+ activity.showError(message);
+ activity.mPinEntry.setText("");
+ }
+ }
+ },
+ /**
+ * The default old PIN is found. Show a blank screen while verifying with the server to make
+ * sure the PIN is still valid. If the PIN is still valid, proceed to {@link #EnterNewPin}.
+ * If not, the user probably changed the PIN through other means, proceed to {@link
+ * #EnterOldPin}. If any other issue caused the verifying to fail, show an error and exit.
+ */
+ VerifyOldPin {
+ @Override
+ public void onEnter(VoicemailChangePinActivity activity) {
+ activity.findViewById(android.R.id.content).setVisibility(View.INVISIBLE);
+ activity.verifyOldPin();
+ }
+
+ @Override
+ public void handleResult(VoicemailChangePinActivity activity,
+ @ChangePinResult int result) {
+ if (result == OmtpConstants.CHANGE_PIN_SUCCESS) {
+ activity.updateState(State.EnterNewPin);
+ } else if (result == OmtpConstants.CHANGE_PIN_SYSTEM_ERROR) {
+ activity.getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
+ activity.showError(activity.getString(R.string.change_pin_system_error),
+ new OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ activity.finish();
+ }
+ });
+ } else {
+ VvmLog.e(TAG, "invalid default old PIN: " + activity
+ .getChangePinResultMessage(result));
+ // If the default old PIN is rejected by the server, the PIN is probably changed
+ // through other means, or the generated pin is invalid
+ // Wipe the default old PIN so the old PIN input box will be shown to the user
+ // on the next time.
+ setDefaultOldPIN(activity, activity.mPhoneAccountHandle, null);
+ activity.handleOmtpEvent(OmtpEvents.CONFIG_PIN_SET);
+ activity.updateState(State.EnterOldPin);
+ }
+ }
+
+ @Override
+ public void onLeave(VoicemailChangePinActivity activity) {
+ activity.findViewById(android.R.id.content).setVisibility(View.VISIBLE);
+ }
+ },
+ /**
+ * Let the user enter the new PIN and validate the format. Only length is enforced, PIN
+ * strength check relies on the server. After a valid PIN is entered, proceed to {@link
+ * #ConfirmNewPin}
+ */
+ EnterNewPin {
+ @Override
+ public void onEnter(VoicemailChangePinActivity activity) {
+ activity.mHeaderText.setText(R.string.change_pin_enter_new_pin_header);
+ activity.mNextButton.setText(R.string.change_pin_continue_label);
+ activity.mHintText.setText(
+ activity.getString(R.string.change_pin_enter_new_pin_hint,
+ activity.mPinMinLength, activity.mPinMaxLength));
+ }
+
+ @Override
+ public void onInputChanged(VoicemailChangePinActivity activity) {
+ String password = activity.getCurrentPasswordInput();
+ if (password.length() == 0) {
+ activity.setNextEnabled(false);
+ return;
+ }
+ CharSequence error = activity.validatePassword(password);
+ if (error != null) {
+ activity.mErrorText.setText(error);
+ activity.setNextEnabled(false);
+ } else {
+ activity.mErrorText.setText(null);
+ activity.setNextEnabled(true);
+ }
+ }
+
+ @Override
+ public void handleNext(VoicemailChangePinActivity activity) {
+ CharSequence errorMsg;
+ errorMsg = activity.validatePassword(activity.getCurrentPasswordInput());
+ if (errorMsg != null) {
+ activity.showError(errorMsg);
+ return;
+ }
+ activity.mFirstPin = activity.getCurrentPasswordInput();
+ activity.updateState(State.ConfirmNewPin);
+ }
+ },
+ /**
+ * Let the user type in the same PIN again to avoid typos. If the PIN matches then perform a
+ * PIN change to the server. Finish the activity if succeeded. Return to {@link
+ * #EnterOldPin} if the old PIN is rejected, {@link #EnterNewPin} for other failure.
+ */
+ ConfirmNewPin {
+ @Override
+ public void onEnter(VoicemailChangePinActivity activity) {
+ activity.mHeaderText.setText(R.string.change_pin_confirm_pin_header);
+ activity.mHintText.setText(null);
+ activity.mNextButton.setText(R.string.change_pin_ok_label);
+ }
+
+ @Override
+ public void onInputChanged(VoicemailChangePinActivity activity) {
+ if (activity.getCurrentPasswordInput().length() == 0) {
+ activity.setNextEnabled(false);
+ return;
+ }
+ if (activity.getCurrentPasswordInput().equals(activity.mFirstPin)) {
+ activity.setNextEnabled(true);
+ activity.mErrorText.setText(null);
+ } else {
+ activity.setNextEnabled(false);
+ activity.mErrorText.setText(R.string.change_pin_confirm_pins_dont_match);
+ }
+ }
+
+ @Override
+ public void handleResult(VoicemailChangePinActivity activity,
+ @ChangePinResult int result) {
+ if (result == OmtpConstants.CHANGE_PIN_SUCCESS) {
+ // If the PIN change succeeded we no longer know what the old (current) PIN is.
+ // Wipe the default old PIN so the old PIN input box will be shown to the user
+ // on the next time.
+ setDefaultOldPIN(activity, activity.mPhoneAccountHandle, null);
+ activity.handleOmtpEvent(OmtpEvents.CONFIG_PIN_SET);
+
+ activity.finish();
+
+ Toast.makeText(activity, activity.getString(R.string.change_pin_succeeded),
+ Toast.LENGTH_SHORT).show();
+ } else {
+ CharSequence message = activity.getChangePinResultMessage(result);
+ VvmLog.i(TAG, "Change PIN failed: " + message);
+ activity.showError(message);
+ if (result == OmtpConstants.CHANGE_PIN_MISMATCH) {
+ // Somehow the PIN has changed, prompt to enter the old PIN again.
+ activity.updateState(State.EnterOldPin);
+ } else {
+ // The new PIN failed to fulfil other restrictions imposed by the server.
+ activity.updateState(State.EnterNewPin);
+ }
+
+ }
+
+ }
+
+ @Override
+ public void handleNext(VoicemailChangePinActivity activity) {
+ activity.processPinChange(activity.mOldPin, activity.mFirstPin);
+ }
+ };
+
+ /**
+ * The activity has switched from another state to this one.
+ */
+ public void onEnter(VoicemailChangePinActivity activity) {
+ // Do nothing
+ }
+
+ /**
+ * The user has typed something into the PIN input field. Also called after {@link
+ * #onEnter(VoicemailChangePinActivity)}
+ */
+ public void onInputChanged(VoicemailChangePinActivity activity) {
+ // Do nothing
+ }
+
+ /**
+ * The asynchronous call to change the PIN on the server has returned.
+ */
+ public void handleResult(VoicemailChangePinActivity activity, @ChangePinResult int result) {
+ // Do nothing
+ }
+
+ /**
+ * The user has pressed the "next" button.
+ */
+ public void handleNext(VoicemailChangePinActivity activity) {
+ // Do nothing
+ }
+
+ /**
+ * The activity has switched from this state to another one.
+ */
+ public void onLeave(VoicemailChangePinActivity activity) {
+ // Do nothing
+ }
+
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mPhoneAccountHandle = getIntent().getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE);
+ mConfig = new OmtpVvmCarrierConfigHelper(this, mPhoneAccountHandle);
+ setContentView(R.layout.voicemail_change_pin);
+ setTitle(R.string.change_pin_title);
+
+ readPinLength();
+
+ View view = findViewById(android.R.id.content);
+
+ mCancelButton = (Button) view.findViewById(R.id.cancel_button);
+ mCancelButton.setOnClickListener(this);
+ mNextButton = (Button) view.findViewById(R.id.next_button);
+ mNextButton.setOnClickListener(this);
+
+ mPinEntry = (EditText) view.findViewById(R.id.pin_entry);
+ mPinEntry.setOnEditorActionListener(this);
+ mPinEntry.addTextChangedListener(this);
+ if (mPinMaxLength != 0) {
+ mPinEntry.setFilters(new InputFilter[]{new LengthFilter(mPinMaxLength)});
+ }
+
+
+ mHeaderText = (TextView) view.findViewById(R.id.headerText);
+ mHintText = (TextView) view.findViewById(R.id.hintText);
+ mErrorText = (TextView) view.findViewById(R.id.errorText);
+
+ migrateDefaultOldPin();
+
+ if (isDefaultOldPinSet(this, mPhoneAccountHandle)) {
+ mOldPin = getDefaultOldPin(this, mPhoneAccountHandle);
+ updateState(State.VerifyOldPin);
+ } else {
+ updateState(State.EnterOldPin);
+ }
+ }
+
+ private void handleOmtpEvent(OmtpEvents event) {
+ mConfig.handleEvent(getVoicemailStatusEditor(), event);
+ }
+
+ private VoicemailStatus.Editor getVoicemailStatusEditor() {
+ // This activity does not have any automatic retry mechanism, errors should be written right
+ // away.
+ return VoicemailStatus.edit(this, mPhoneAccountHandle);
+ }
+
+ /**
+ * Extracts the pin length requirement sent by the server with a STATUS SMS.
+ */
+ private void readPinLength() {
+ VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(this,
+ mPhoneAccountHandle);
+ // The OMTP pin length format is {min}-{max}
+ String[] lengths = preferences.getString(OmtpConstants.TUI_PASSWORD_LENGTH, "").split("-");
+ if (lengths.length == 2) {
+ try {
+ mPinMinLength = Integer.parseInt(lengths[0]);
+ mPinMaxLength = Integer.parseInt(lengths[1]);
+ } catch (NumberFormatException e) {
+ mPinMinLength = 0;
+ mPinMaxLength = 0;
+ }
+ } else {
+ mPinMinLength = 0;
+ mPinMaxLength = 0;
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateState(mUiState);
+
+ }
+
+ public void handleNext() {
+ if (mPinEntry.length() == 0) {
+ return;
+ }
+ mUiState.handleNext(this);
+ }
+
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.next_button:
+ handleNext();
+ break;
+
+ case R.id.cancel_button:
+ finish();
+ break;
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == android.R.id.home) {
+ onBackPressed();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (!mNextButton.isEnabled()) {
+ return true;
+ }
+ // Check if this was the result of hitting the enter or "done" key
+ if (actionId == EditorInfo.IME_NULL
+ || actionId == EditorInfo.IME_ACTION_DONE
+ || actionId == EditorInfo.IME_ACTION_NEXT) {
+ handleNext();
+ return true;
+ }
+ return false;
+ }
+
+ public void afterTextChanged(Editable s) {
+ mUiState.onInputChanged(this);
+ }
+
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ // Do nothing
+ }
+
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // Do nothing
+ }
+
+ /**
+ * After replacing the default PIN with a random PIN, call this to store the random PIN. The
+ * stored PIN will be automatically entered when the user attempts to change the PIN.
+ */
+ public static void setDefaultOldPIN(Context context, PhoneAccountHandle phoneAccountHandle,
+ String pin) {
+ new VisualVoicemailPreferences(context, phoneAccountHandle)
+ .edit().putString(KEY_DEFAULT_OLD_PIN, pin).apply();
+ }
+
+ public static boolean isDefaultOldPinSet(Context context,
+ PhoneAccountHandle phoneAccountHandle) {
+ return getDefaultOldPin(context, phoneAccountHandle) != null;
+ }
+
+ private static String getDefaultOldPin(Context context, PhoneAccountHandle phoneAccountHandle) {
+ return new VisualVoicemailPreferences(context, phoneAccountHandle)
+ .getString(KEY_DEFAULT_OLD_PIN);
+ }
+
+ /**
+ * Storage location has changed mid development. Migrate from the old location to avoid losing
+ * tester's default old pin.
+ */
+ private void migrateDefaultOldPin() {
+ String key = "voicemail_pin_dialog_preference_"
+ + PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccountHandle)
+ + "_default_old_pin";
+
+ SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
+ if (preferences.contains(key)) {
+ setDefaultOldPIN(this, mPhoneAccountHandle, preferences.getString(key, null));
+ preferences.edit().putString(key, null).apply();
+ }
+ }
+
+ private String getCurrentPasswordInput() {
+ return mPinEntry.getText().toString();
+ }
+
+ private void updateState(State state) {
+ State previousState = mUiState;
+ mUiState = state;
+ if (previousState != state) {
+ previousState.onLeave(this);
+ mPinEntry.setText("");
+ mUiState.onEnter(this);
+ }
+ mUiState.onInputChanged(this);
+ }
+
+ /**
+ * Validates PIN and returns a message to display if PIN fails test.
+ *
+ * @param password the raw password the user typed in
+ * @return error message to show to user or null if password is OK
+ */
+ private CharSequence validatePassword(String password) {
+ if (mPinMinLength == 0 && mPinMaxLength == 0) {
+ // Invalid length requirement is sent by the server, just accept anything and let the
+ // server decide.
+ return null;
+ }
+
+ if (password.length() < mPinMinLength) {
+ return getString(R.string.vm_change_pin_error_too_short);
+ }
+ return null;
+ }
+
+ private void setHeader(int text) {
+ mHeaderText.setText(text);
+ mPinEntry.setContentDescription(mHeaderText.getText());
+ }
+
+ /**
+ * Get the corresponding message for the {@link ChangePinResult}.<code>result</code> must not
+ * {@link OmtpConstants#CHANGE_PIN_SUCCESS}
+ */
+ private CharSequence getChangePinResultMessage(@ChangePinResult int result) {
+ switch (result) {
+ case OmtpConstants.CHANGE_PIN_TOO_SHORT:
+ return getString(R.string.vm_change_pin_error_too_short);
+ case OmtpConstants.CHANGE_PIN_TOO_LONG:
+ return getString(R.string.vm_change_pin_error_too_long);
+ case OmtpConstants.CHANGE_PIN_TOO_WEAK:
+ return getString(R.string.vm_change_pin_error_too_weak);
+ case OmtpConstants.CHANGE_PIN_INVALID_CHARACTER:
+ return getString(R.string.vm_change_pin_error_invalid);
+ case OmtpConstants.CHANGE_PIN_MISMATCH:
+ return getString(R.string.vm_change_pin_error_mismatch);
+ case OmtpConstants.CHANGE_PIN_SYSTEM_ERROR:
+ return getString(R.string.vm_change_pin_error_system_error);
+ default:
+ VvmLog.wtf(TAG, "Unexpected ChangePinResult " + result);
+ return null;
+ }
+ }
+
+ private void verifyOldPin() {
+ processPinChange(mOldPin, mOldPin);
+ }
+
+ private void setNextEnabled(boolean enabled) {
+ mNextButton.setEnabled(enabled);
+ }
+
+
+ private void showError(CharSequence message) {
+ showError(message, null);
+ }
+
+ private void showError(CharSequence message, @Nullable OnDismissListener callback) {
+ new AlertDialog.Builder(this)
+ .setMessage(message)
+ .setPositiveButton(android.R.string.ok, null)
+ .setOnDismissListener(callback)
+ .show();
+ }
+
+ /**
+ * Asynchronous call to change the PIN on the server.
+ */
+ private void processPinChange(String oldPin, String newPin) {
+ mProgressDialog = new ProgressDialog(this);
+ mProgressDialog.setCancelable(false);
+ mProgressDialog.setMessage(getString(R.string.vm_change_pin_progress_message));
+ mProgressDialog.show();
+
+ ChangePinNetworkRequestCallback callback = new ChangePinNetworkRequestCallback(oldPin,
+ newPin);
+ callback.requestNetwork();
+ }
+
+ private class ChangePinNetworkRequestCallback extends VvmNetworkRequestCallback {
+
+ private final String mOldPin;
+ private final String mNewPin;
+
+ public ChangePinNetworkRequestCallback(String oldPin, String newPin) {
+ super(mConfig, mPhoneAccountHandle,
+ VoicemailChangePinActivity.this.getVoicemailStatusEditor());
+ mOldPin = oldPin;
+ mNewPin = newPin;
+ }
+
+ @Override
+ public void onAvailable(Network network) {
+ super.onAvailable(network);
+ try (ImapHelper helper =
+ new ImapHelper(VoicemailChangePinActivity.this, mPhoneAccountHandle, network,
+ getVoicemailStatusEditor())) {
+
+ @ChangePinResult int result =
+ helper.changePin(mOldPin, mNewPin);
+ sendResult(result);
+ } catch (InitializingException | MessagingException e) {
+ VvmLog.e(TAG, "ChangePinNetworkRequestCallback: onAvailable: ", e);
+ sendResult(OmtpConstants.CHANGE_PIN_SYSTEM_ERROR);
+ }
+ }
+
+ @Override
+ public void onFailed(String reason) {
+ super.onFailed(reason);
+ sendResult(OmtpConstants.CHANGE_PIN_SYSTEM_ERROR);
+ }
+
+ private void sendResult(@ChangePinResult int result) {
+ VvmLog.i(TAG, "Change PIN result: " + result);
+ if (mProgressDialog.isShowing() && !VoicemailChangePinActivity.this.isDestroyed() &&
+ !VoicemailChangePinActivity.this.isFinishing()) {
+ mProgressDialog.dismiss();
+ } else {
+ VvmLog.i(TAG, "Dialog not visible, not dismissing");
+ }
+ mHandler.obtainMessage(MESSAGE_HANDLE_RESULT, result, 0).sendToTarget();
+ releaseNetwork();
+ }
+ }
+
+}
diff --git a/src/com/android/phone/settings/VoicemailRingtonePreference.java b/src/com/android/phone/settings/VoicemailRingtonePreference.java
index 4ee4e64..bb82d4f 100644
--- a/src/com/android/phone/settings/VoicemailRingtonePreference.java
+++ b/src/com/android/phone/settings/VoicemailRingtonePreference.java
@@ -17,8 +17,13 @@
* it is created or updated.
*/
public class VoicemailRingtonePreference extends RingtonePreference {
+ public interface VoicemailRingtoneNameChangeListener {
+ void onVoicemailRingtoneNameChanged(CharSequence name);
+ }
+
private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 1;
+ private VoicemailRingtoneNameChangeListener mVoicemailRingtoneNameChangeListener;
private Runnable mVoicemailRingtoneLookupRunnable;
private Handler mVoicemailRingtoneLookupComplete;
@@ -32,6 +37,10 @@
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY:
+ if (mVoicemailRingtoneNameChangeListener != null) {
+ mVoicemailRingtoneNameChangeListener.onVoicemailRingtoneNameChanged(
+ (CharSequence) msg.obj);
+ }
setSummary((CharSequence) msg.obj);
break;
}
@@ -39,7 +48,7 @@
};
}
- public void init(Phone phone) {
+ public void init(Phone phone, CharSequence oldRingtoneName) {
mPhone = phone;
// Requesting the ringtone will trigger migration if necessary.
@@ -48,6 +57,7 @@
final Preference preference = this;
final String preferenceKey =
VoicemailNotificationSettingsUtil.getVoicemailRingtoneSharedPrefsKey(mPhone);
+ setSummary(oldRingtoneName);
mVoicemailRingtoneLookupRunnable = new Runnable() {
@Override
public void run() {
@@ -63,6 +73,10 @@
updateRingtoneName();
}
+ public void setVoicemailRingtoneNameChangeListener(VoicemailRingtoneNameChangeListener l) {
+ mVoicemailRingtoneNameChangeListener = l;
+ }
+
@Override
protected Uri onRestoreRingtone() {
return VoicemailNotificationSettingsUtil.getRingtoneUri(mPhone);
diff --git a/src/com/android/phone/settings/VoicemailSettingsActivity.java b/src/com/android/phone/settings/VoicemailSettingsActivity.java
index ba52b6a..6bb481f 100644
--- a/src/com/android/phone/settings/VoicemailSettingsActivity.java
+++ b/src/com/android/phone/settings/VoicemailSettingsActivity.java
@@ -30,25 +30,24 @@
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.provider.ContactsContract.CommonDataKinds;
-import android.telephony.TelephonyManager;
+import android.telecom.PhoneAccountHandle;
import android.text.BidiFormatter;
import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import android.util.Log;
import android.view.MenuItem;
import android.widget.ListAdapter;
-
import com.android.internal.telephony.CallForwardInfo;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
-import com.android.phone.R;
import com.android.phone.EditPhoneNumberPreference;
import com.android.phone.PhoneGlobals;
import com.android.phone.PhoneUtils;
+import com.android.phone.R;
import com.android.phone.SubscriptionInfoHelper;
+import com.android.phone.vvm.omtp.OmtpConstants;
import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
-import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
-
+import com.android.phone.vvm.omtp.VisualVoicemailPreferences;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
@@ -59,7 +58,8 @@
implements DialogInterface.OnClickListener,
Preference.OnPreferenceChangeListener,
EditPhoneNumberPreference.OnDialogClosedListener,
- EditPhoneNumberPreference.GetDefaultNumberListener {
+ EditPhoneNumberPreference.GetDefaultNumberListener,
+ VoicemailRingtonePreference.VoicemailRingtoneNameChangeListener {
private static final String LOG_TAG = VoicemailSettingsActivity.class.getSimpleName();
private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2);
@@ -186,6 +186,8 @@
private CallForwardInfo[] mNewFwdSettings;
private String mNewVMNumber;
+ private CharSequence mOldVmRingtoneName = "";
+
/**
* Used to indicate that the voicemail preference should be shown.
*/
@@ -193,6 +195,7 @@
private boolean mForeground;
private Phone mPhone;
+ private PhoneAccountHandle mPhoneAccountHandle;
private SubscriptionInfoHelper mSubscriptionInfoHelper;
private OmtpVvmCarrierConfigHelper mOmtpVvmCarrierConfigHelper;
@@ -202,7 +205,7 @@
private VoicemailRingtonePreference mVoicemailNotificationRingtone;
private CheckBoxPreference mVoicemailNotificationVibrate;
private SwitchPreference mVoicemailVisualVoicemail;
-
+ private Preference mVoicemailChangePinPreference;
//*********************************************************************************************
// Preference Activity Methods
@@ -221,6 +224,7 @@
mSubscriptionInfoHelper.setActionBarTitle(
getActionBar(), getResources(), R.string.voicemail_settings_with_label);
mPhone = mSubscriptionInfoHelper.getPhone();
+ mPhoneAccountHandle = PhoneUtils.makePstnPhoneAccountHandle(mPhone);
mOmtpVvmCarrierConfigHelper = new OmtpVvmCarrierConfigHelper(
mPhone.getContext(), mPhone.getSubId());
}
@@ -253,7 +257,8 @@
mVoicemailNotificationRingtone = (VoicemailRingtonePreference) findPreference(
getResources().getString(R.string.voicemail_notification_ringtone_key));
- mVoicemailNotificationRingtone.init(mPhone);
+ mVoicemailNotificationRingtone.setVoicemailRingtoneNameChangeListener(this);
+ mVoicemailNotificationRingtone.init(mPhone, mOldVmRingtoneName);
mVoicemailNotificationVibrate = (CheckBoxPreference) findPreference(
getResources().getString(R.string.voicemail_notification_vibrate_key));
@@ -261,13 +266,30 @@
mVoicemailVisualVoicemail = (SwitchPreference) findPreference(
getResources().getString(R.string.voicemail_visual_voicemail_key));
- if (TelephonyManager.VVM_TYPE_OMTP.equals(mOmtpVvmCarrierConfigHelper.getVvmType()) ||
- TelephonyManager.VVM_TYPE_CVVM.equals(mOmtpVvmCarrierConfigHelper.getVvmType())) {
+
+ mVoicemailChangePinPreference = findPreference(
+ getResources().getString(R.string.voicemail_change_pin_key));
+ Intent changePinIntent = new Intent(new Intent(this, VoicemailChangePinActivity.class));
+ changePinIntent.putExtra(VoicemailChangePinActivity.EXTRA_PHONE_ACCOUNT_HANDLE,
+ mPhoneAccountHandle);
+
+ mVoicemailChangePinPreference.setIntent(changePinIntent);
+ if (VoicemailChangePinActivity.isDefaultOldPinSet(this, mPhoneAccountHandle)) {
+ mVoicemailChangePinPreference.setTitle(R.string.voicemail_set_pin_dialog_title);
+ } else {
+ mVoicemailChangePinPreference.setTitle(R.string.voicemail_change_pin_dialog_title);
+ }
+
+ if (mOmtpVvmCarrierConfigHelper.isValid()) {
mVoicemailVisualVoicemail.setOnPreferenceChangeListener(this);
mVoicemailVisualVoicemail.setChecked(
- VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(mPhone));
+ VisualVoicemailSettingsUtil.isEnabled(this, mPhoneAccountHandle));
+ if (!isVisualVoicemailActivated()) {
+ prefSet.removePreference(mVoicemailChangePinPreference);
+ }
} else {
prefSet.removePreference(mVoicemailVisualVoicemail);
+ prefSet.removePreference(mVoicemailChangePinPreference);
}
updateVMPreferenceWidgets(mVoicemailProviders.getValue());
@@ -389,14 +411,14 @@
VoicemailNotificationSettingsUtil.setVibrationEnabled(
mPhone, Boolean.TRUE.equals(objValue));
} else if (preference.getKey().equals(mVoicemailVisualVoicemail.getKey())) {
- boolean isEnabled = (Boolean) objValue;
- VisualVoicemailSettingsUtil.setVisualVoicemailEnabled(mPhone, isEnabled, true);
- if (isEnabled) {
- OmtpVvmSourceManager.getInstance(mPhone.getContext()).addPhoneStateListener(mPhone);
- mOmtpVvmCarrierConfigHelper.startActivation();
+ boolean isEnabled = (boolean) objValue;
+ VisualVoicemailSettingsUtil
+ .setEnabled(mPhone.getContext(), mPhoneAccountHandle, isEnabled);
+ PreferenceScreen prefSet = getPreferenceScreen();
+ if (isVisualVoicemailActivated()) {
+ prefSet.addPreference(mVoicemailChangePinPreference);
} else {
- OmtpVvmSourceManager.getInstance(mPhone.getContext()).removeSource(mPhone);
- mOmtpVvmCarrierConfigHelper.startDeactivation();
+ prefSet.removePreference(mVoicemailChangePinPreference);
}
}
@@ -531,6 +553,11 @@
super.onActivityResult(requestCode, resultCode, data);
}
+ @Override
+ public void onVoicemailRingtoneNameChanged(CharSequence name) {
+ mOldVmRingtoneName = name;
+ }
+
/**
* Simulates user clicking on a passed preference.
* Usually needed when the preference is a dialog preference and we want to invoke
@@ -1132,6 +1159,16 @@
return true;
}
+ private boolean isVisualVoicemailActivated() {
+ if (!VisualVoicemailSettingsUtil.isEnabled(this, mPhoneAccountHandle)) {
+ return false;
+ }
+ VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(this,
+ mPhoneAccountHandle);
+ return preferences.getString(OmtpConstants.SERVER_ADDRESS, null) != null;
+
+ }
+
private static void log(String msg) {
Log.d(LOG_TAG, msg);
}
diff --git a/src/com/android/phone/vvm/omtp/ActivationTask.java b/src/com/android/phone/vvm/omtp/ActivationTask.java
new file mode 100644
index 0000000..72f1f54
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/ActivationTask.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.content.Context;
+import android.content.Intent;
+import android.database.ContentObserver;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+
+import com.android.phone.Assert;
+import com.android.phone.PhoneGlobals;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.protocol.VisualVoicemailProtocol;
+import com.android.phone.vvm.omtp.scheduling.BaseTask;
+import com.android.phone.vvm.omtp.scheduling.RetryPolicy;
+import com.android.phone.vvm.omtp.sms.StatusMessage;
+import com.android.phone.vvm.omtp.sms.StatusSmsFetcher;
+import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
+import com.android.phone.vvm.omtp.sync.OmtpVvmSyncService;
+import com.android.phone.vvm.omtp.sync.SyncTask;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Task to activate the visual voicemail service. A request to activate VVM will be sent to the
+ * carrier, which will respond with a STATUS SMS. The credentials will be updated from the SMS. If
+ * the user is not provisioned provisioning will be attempted. Activation happens when the phone
+ * boots, the SIM is inserted, signal returned when VVM is not activated yet, and when the carrier
+ * spontaneously sent a STATUS SMS.
+ */
+public class ActivationTask extends BaseTask {
+
+ private static final String TAG = "VvmActivationTask";
+
+ private static final int RETRY_TIMES = 4;
+ private static final int RETRY_INTERVAL_MILLIS = 5_000;
+
+ private static final String EXTRA_MESSAGE_DATA_BUNDLE = "extra_message_data_bundle";
+
+ @Nullable
+ private static DeviceProvisionedObserver sDeviceProvisionedObserver;
+
+ private final RetryPolicy mRetryPolicy;
+
+ private Bundle mMessageData;
+
+ public ActivationTask() {
+ super(TASK_ACTIVATION);
+ mRetryPolicy = new RetryPolicy(RETRY_TIMES, RETRY_INTERVAL_MILLIS);
+ addPolicy(mRetryPolicy);
+ }
+
+ /**
+ * Has the user gone through the setup wizard yet.
+ */
+ private static boolean isDeviceProvisioned(Context context) {
+ return Settings.Global.getInt(
+ context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) == 1;
+ }
+
+ /**
+ * @param messageData The optional bundle from {@link android.provider.VoicemailContract#
+ * EXTRA_VOICEMAIL_SMS_FIELDS}, if the task is initiated by a status SMS. If null the task will
+ * request a status SMS itself.
+ */
+ public static void start(Context context, int subId, @Nullable Bundle messageData) {
+ if (!isDeviceProvisioned(context)) {
+ VvmLog.i(TAG, "Activation requested while device is not provisioned, postponing");
+ // Activation might need information such as system language to be set, so wait until
+ // the setup wizard is finished. The data bundle from the SMS will be re-requested upon
+ // activation.
+ queueActivationAfterProvisioned(context, subId);
+ return;
+ }
+
+ Intent intent = BaseTask.createIntent(context, ActivationTask.class, subId);
+ if (messageData != null) {
+ intent.putExtra(EXTRA_MESSAGE_DATA_BUNDLE, messageData);
+ }
+ context.startService(intent);
+ }
+
+ public void onCreate(Context context, Intent intent, int flags, int startId) {
+ super.onCreate(context, intent, flags, startId);
+ mMessageData = intent.getParcelableExtra(EXTRA_MESSAGE_DATA_BUNDLE);
+ }
+
+ @Override
+ public Intent createRestartIntent() {
+ Intent intent = super.createRestartIntent();
+ // mMessageData is discarded, request a fresh STATUS SMS for retries.
+ return intent;
+ }
+
+ @Override
+ @WorkerThread
+ public void onExecuteInBackgroundThread() {
+ Assert.isNotMainThread();
+ int subId = getSubId();
+
+ PhoneAccountHandle phoneAccountHandle = PhoneAccountHandleConverter.fromSubId(subId);
+ if (phoneAccountHandle == null) {
+ // This should never happen
+ VvmLog.e(TAG, "null phone account for subId " + subId);
+ return;
+ }
+
+ OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(getContext(), subId);
+ if (!helper.isValid()) {
+ VvmLog.i(TAG, "VVM not supported on subId " + subId);
+ VoicemailStatus.disable(getContext(), phoneAccountHandle);
+ return;
+ }
+
+ // OmtpVvmCarrierConfigHelper can start the activation process; it will pass in a vvm
+ // content provider URI which we will use. On some occasions, setting that URI will
+ // fail, so we will perform a few attempts to ensure that the vvm content provider has
+ // a good chance of being started up.
+ if (!VoicemailStatus.edit(getContext(), phoneAccountHandle)
+ .setType(helper.getVvmType())
+ .apply()) {
+ VvmLog.e(TAG, "Failed to configure content provider - " + helper.getVvmType());
+ fail();
+ }
+ VvmLog.i(TAG, "VVM content provider configured - " + helper.getVvmType());
+
+ if (!OmtpVvmSourceManager.getInstance(getContext())
+ .isVvmSourceRegistered(phoneAccountHandle)) {
+ // This account has not been activated before during the lifetime of this boot.
+ VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(getContext(),
+ phoneAccountHandle);
+ if (preferences.getString(OmtpConstants.SERVER_ADDRESS, null) == null) {
+ // Only show the "activating" message if activation has not been completed before.
+ // Subsequent activations are more of a status check and usually does not
+ // concern the user.
+ helper.handleEvent(VoicemailStatus.edit(getContext(), phoneAccountHandle),
+ OmtpEvents.CONFIG_ACTIVATING);
+ } else {
+ // The account has been activated on this device before. Pretend it is already
+ // activated. If there are any activation error it will overwrite this status.
+ helper.handleEvent(VoicemailStatus.edit(getContext(), phoneAccountHandle),
+ OmtpEvents.CONFIG_ACTIVATING_SUBSEQUENT);
+ }
+
+ }
+ if (!hasSignal(getContext(), subId)) {
+ VvmLog.i(TAG, "Service lost during activation, aborting");
+ // Restore the "NO SIGNAL" state since it will be overwritten by the CONFIG_ACTIVATING
+ // event.
+ helper.handleEvent(VoicemailStatus.edit(getContext(), phoneAccountHandle),
+ OmtpEvents.NOTIFICATION_SERVICE_LOST);
+ // Don't retry, a new activation will be started after the signal returned.
+ return;
+ }
+
+ helper.activateSmsFilter();
+ VoicemailStatus.Editor status = mRetryPolicy.getVoicemailStatusEditor();
+
+ VisualVoicemailProtocol protocol = helper.getProtocol();
+
+ Bundle data;
+ if (mMessageData != null) {
+ // The content of STATUS SMS is provided to launch this task, no need to request it
+ // again.
+ data = mMessageData;
+ } else {
+ try (StatusSmsFetcher fetcher = new StatusSmsFetcher(getContext(), subId)) {
+ protocol.startActivation(helper, fetcher.getSentIntent());
+ // Both the fetcher and OmtpMessageReceiver will be triggered, but
+ // OmtpMessageReceiver will just route the SMS back to ActivationTask, which will be
+ // rejected because the task is still running.
+ data = fetcher.get();
+ } catch (TimeoutException e) {
+ // The carrier is expected to return an STATUS SMS within STATUS_SMS_TIMEOUT_MILLIS
+ // handleEvent() will do the logging.
+ helper.handleEvent(status, OmtpEvents.CONFIG_STATUS_SMS_TIME_OUT);
+ fail();
+ return;
+ } catch (CancellationException e) {
+ VvmLog.e(TAG, "Unable to send status request SMS");
+ fail();
+ return;
+ } catch (InterruptedException | ExecutionException | IOException e) {
+ VvmLog.e(TAG, "can't get future STATUS SMS", e);
+ fail();
+ return;
+ }
+ }
+
+ StatusMessage message = new StatusMessage(data);
+ VvmLog.d(TAG, "STATUS SMS received: st=" + message.getProvisioningStatus()
+ + ", rc=" + message.getReturnCode());
+
+ if (message.getProvisioningStatus().equals(OmtpConstants.SUBSCRIBER_READY)) {
+ VvmLog.d(TAG, "subscriber ready, no activation required");
+ updateSource(getContext(), phoneAccountHandle, getSubId(), status, message);
+ } else {
+ if (helper.supportsProvisioning()) {
+ VvmLog.i(TAG, "Subscriber not ready, start provisioning");
+ helper.startProvisioning(this, phoneAccountHandle, status, message, data);
+
+ } else if (message.getProvisioningStatus().equals(OmtpConstants.SUBSCRIBER_NEW)) {
+ VvmLog.i(TAG, "Subscriber new but provisioning is not supported");
+ // Ignore the non-ready state and attempt to use the provided info as is.
+ // This is probably caused by not completing the new user tutorial.
+ updateSource(getContext(), phoneAccountHandle, getSubId(), status, message);
+ } else {
+ VvmLog.i(TAG, "Subscriber not ready but provisioning is not supported");
+ helper.handleEvent(status, OmtpEvents.CONFIG_SERVICE_NOT_AVAILABLE);
+ PhoneGlobals.getInstance().setShouldCheckVisualVoicemailConfigurationForMwi(subId, false);
+ }
+ }
+ }
+
+ public static void updateSource(Context context, PhoneAccountHandle phone, int subId,
+ VoicemailStatus.Editor status, StatusMessage message) {
+ OmtpVvmSourceManager vvmSourceManager =
+ OmtpVvmSourceManager.getInstance(context);
+
+ if (OmtpConstants.SUCCESS.equals(message.getReturnCode())) {
+ OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(context, subId);
+ helper.handleEvent(status, OmtpEvents.CONFIG_REQUEST_STATUS_SUCCESS);
+
+ // Save the IMAP credentials in preferences so they are persistent and can be retrieved.
+ VisualVoicemailPreferences prefs = new VisualVoicemailPreferences(context, phone);
+ message.putStatus(prefs.edit()).apply();
+
+ // Add the source to indicate that it is active.
+ vvmSourceManager.addSource(phone);
+
+ SyncTask.start(context, phone, OmtpVvmSyncService.SYNC_FULL_SYNC);
+ // Remove the message waiting indicator, which is a sticky notification for traditional
+ // voicemails.
+ PhoneGlobals.getInstance()
+ .setShouldCheckVisualVoicemailConfigurationForMwi(subId, true);
+ PhoneGlobals.getInstance().clearMwiIndicator(subId);
+ } else {
+ VvmLog.e(TAG, "Visual voicemail not available for subscriber.");
+ }
+ }
+
+ private static boolean hasSignal(Context context, int subId) {
+ return context.getSystemService(TelephonyManager.class)
+ .getServiceStateForSubscriber(subId).getState() == ServiceState.STATE_IN_SERVICE;
+ }
+
+ private static void queueActivationAfterProvisioned(Context context, int subId) {
+ if (sDeviceProvisionedObserver == null) {
+ sDeviceProvisionedObserver = new DeviceProvisionedObserver(context);
+ context.getContentResolver()
+ .registerContentObserver(Settings.Global.getUriFor(Global.DEVICE_PROVISIONED),
+ false, sDeviceProvisionedObserver);
+ }
+ sDeviceProvisionedObserver.addSubId(subId);
+ }
+
+ private static class DeviceProvisionedObserver extends ContentObserver {
+
+ private final Context mContext;
+ private final Set<Integer> mSubIds = new HashSet<>();
+
+ private DeviceProvisionedObserver(Context context) {
+ super(null);
+ mContext = context;
+ }
+
+ public void addSubId(int subId) {
+ mSubIds.add(subId);
+ }
+
+ @Override
+ public void onChange(boolean selfChange) {
+ if (isDeviceProvisioned(mContext)) {
+ VvmLog.i(TAG, "device provisioned, resuming activation");
+ for (int subId : mSubIds) {
+ start(mContext, subId, null);
+ }
+ mContext.getContentResolver().unregisterContentObserver(sDeviceProvisionedObserver);
+ sDeviceProvisionedObserver = null;
+ }
+ }
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/DefaultOmtpEventHandler.java b/src/com/android/phone/vvm/omtp/DefaultOmtpEventHandler.java
new file mode 100644
index 0000000..0c19a6a
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/DefaultOmtpEventHandler.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.content.Context;
+import android.provider.VoicemailContract;
+import android.provider.VoicemailContract.Status;
+
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.OmtpEvents.Type;
+
+public class DefaultOmtpEventHandler {
+
+ private static final String TAG = "DefErrorCodeHandler";
+
+ public static void handleEvent(Context context, OmtpVvmCarrierConfigHelper config,
+ VoicemailStatus.Editor status, OmtpEvents event) {
+ switch (event.getType()) {
+ case Type.CONFIGURATION:
+ handleConfigurationEvent(context, status, event);
+ break;
+ case Type.DATA_CHANNEL:
+ handleDataChannelEvent(context, status, event);
+ break;
+ case Type.NOTIFICATION_CHANNEL:
+ handleNotificationChannelEvent(context, config, status, event);
+ break;
+ case Type.OTHER:
+ handleOtherEvent(context, status, event);
+ break;
+ default:
+ VvmLog.wtf(TAG, "invalid event type " + event.getType() + " for " + event);
+ }
+ }
+
+ private static void handleConfigurationEvent(Context context, VoicemailStatus.Editor status,
+ OmtpEvents event) {
+ switch (event) {
+ case CONFIG_DEFAULT_PIN_REPLACED:
+ case CONFIG_REQUEST_STATUS_SUCCESS:
+ case CONFIG_PIN_SET:
+ status
+ .setConfigurationState(VoicemailContract.Status.CONFIGURATION_STATE_OK)
+ .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_OK)
+ .apply();
+ break;
+ case CONFIG_ACTIVATING:
+ // Wipe all errors from the last activation. All errors shown should be new errors
+ // for this activation.
+ status
+ .setConfigurationState(Status.CONFIGURATION_STATE_CONFIGURING)
+ .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_OK)
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_OK).apply();
+ break;
+ case CONFIG_ACTIVATING_SUBSEQUENT:
+ status
+ .setConfigurationState(Status.CONFIGURATION_STATE_OK)
+ .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_OK)
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_OK).apply();
+ break;
+ case CONFIG_SERVICE_NOT_AVAILABLE:
+ status
+ .setConfigurationState(Status.CONFIGURATION_STATE_FAILED)
+ .apply();
+ break;
+ case CONFIG_STATUS_SMS_TIME_OUT:
+ status
+ .setConfigurationState(Status.CONFIGURATION_STATE_FAILED)
+ .apply();
+ break;
+ default:
+ VvmLog.wtf(TAG, "invalid configuration event " + event);
+ }
+ }
+
+ private static void handleDataChannelEvent(Context context, VoicemailStatus.Editor status,
+ OmtpEvents event) {
+ switch (event) {
+ case DATA_IMAP_OPERATION_STARTED:
+ case DATA_IMAP_OPERATION_COMPLETED:
+ status
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_OK)
+ .apply();
+ break;
+
+ case DATA_NO_CONNECTION:
+ status
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_NO_CONNECTION)
+ .apply();
+ break;
+
+ case DATA_NO_CONNECTION_CELLULAR_REQUIRED:
+ status
+ .setDataChannelState(
+ Status.DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED)
+ .apply();
+ break;
+ case DATA_INVALID_PORT:
+ status
+ .setDataChannelState(
+ VoicemailContract.Status.DATA_CHANNEL_STATE_BAD_CONFIGURATION)
+ .apply();
+ break;
+ case DATA_CANNOT_RESOLVE_HOST_ON_NETWORK:
+ status
+ .setDataChannelState(
+ VoicemailContract.Status.DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR)
+ .apply();
+ break;
+ case DATA_SSL_INVALID_HOST_NAME:
+ case DATA_CANNOT_ESTABLISH_SSL_SESSION:
+ case DATA_IOE_ON_OPEN:
+ case DATA_GENERIC_IMAP_IOE:
+ status
+ .setDataChannelState(
+ VoicemailContract.Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR)
+ .apply();
+ break;
+ case DATA_BAD_IMAP_CREDENTIAL:
+ case DATA_AUTH_UNKNOWN_USER:
+ case DATA_AUTH_UNKNOWN_DEVICE:
+ case DATA_AUTH_INVALID_PASSWORD:
+ case DATA_AUTH_MAILBOX_NOT_INITIALIZED:
+ case DATA_AUTH_SERVICE_NOT_PROVISIONED:
+ case DATA_AUTH_SERVICE_NOT_ACTIVATED:
+ case DATA_AUTH_USER_IS_BLOCKED:
+ status
+ .setDataChannelState(
+ VoicemailContract.Status.DATA_CHANNEL_STATE_BAD_CONFIGURATION)
+ .apply();
+ break;
+
+ case DATA_REJECTED_SERVER_RESPONSE:
+ case DATA_INVALID_INITIAL_SERVER_RESPONSE:
+ case DATA_MAILBOX_OPEN_FAILED:
+ case DATA_SSL_EXCEPTION:
+ case DATA_ALL_SOCKET_CONNECTION_FAILED:
+ status
+ .setDataChannelState(
+ VoicemailContract.Status.DATA_CHANNEL_STATE_SERVER_ERROR)
+ .apply();
+ break;
+
+ default:
+ VvmLog.wtf(TAG, "invalid data channel event " + event);
+ }
+ }
+
+ private static void handleNotificationChannelEvent(Context context,
+ OmtpVvmCarrierConfigHelper config, VoicemailStatus.Editor status, OmtpEvents event) {
+ switch (event) {
+ case NOTIFICATION_IN_SERVICE:
+ status
+ .setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_OK)
+ // Clear the error state. A sync should follow signal return so any error
+ // will be reposted.
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_OK)
+ .apply();
+ break;
+ case NOTIFICATION_SERVICE_LOST:
+ status.setNotificationChannelState(Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION);
+ if (config.isCellularDataRequired()) {
+ status.setDataChannelState(
+ Status.DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED);
+ }
+ status.apply();
+ break;
+ default:
+ VvmLog.wtf(TAG, "invalid notification channel event " + event);
+ }
+ }
+
+ private static void handleOtherEvent(Context context, VoicemailStatus.Editor status,
+ OmtpEvents event) {
+ switch (event) {
+ case OTHER_SOURCE_REMOVED:
+ status
+ .setConfigurationState(Status.CONFIGURATION_STATE_NOT_CONFIGURED)
+ .setNotificationChannelState(
+ Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION)
+ .setDataChannelState(Status.DATA_CHANNEL_STATE_NO_CONNECTION)
+ .apply();
+ break;
+ default:
+ VvmLog.wtf(TAG, "invalid other event " + event);
+ }
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/LocalLogHelper.java b/src/com/android/phone/vvm/omtp/LocalLogHelper.java
deleted file mode 100644
index a3de74f..0000000
--- a/src/com/android/phone/vvm/omtp/LocalLogHelper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.phone.vvm.omtp;
-
-import com.android.internal.telephony.PhoneFactory;
-
-/**
- * Helper methods for adding to Telephony local logs.
- */
-public class LocalLogHelper {
- public static final String KEY = "OmtpVvm";
- private static final int MAX_OMTP_VVM_LOGS = 20;
-
- public static void log(String tag, String log) {
- try {
- PhoneFactory.addLocalLog(KEY, MAX_OMTP_VVM_LOGS);
- } catch (IllegalArgumentException e){
- } finally {
- PhoneFactory.localLog(KEY, tag + ": " + log);
- }
- }
-}
diff --git a/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiver.java b/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiver.java
deleted file mode 100644
index a2b85f7..0000000
--- a/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiver.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2016 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.vvm.omtp;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.Set;
-
-/**
- * Stores subscription ID of SIMs while the device is locked to process them after the device is
- * unlocked. This class is only intended to be used within {@link SimChangeReceiver}. subId is used
- * for Visual voicemail activation/deactivation, which need to be done when the device is unlocked.
- * But the enumeration of subIds happen on boot, when the device could be locked. This class is used
- * to defer all activation/deactivation until the device is unlocked.
- *
- * The subIds are stored in device encrypted {@link SharedPreferences} (readable/writable even
- * locked). after the device is unlocked the list is read and deleted.
- */
-public class OmtpBootCompletedReceiver extends BroadcastReceiver {
-
- private static final String TAG = "OmtpBootCompletedRcvr";
-
- private static final String DEFERRED_SUBID_LIST_KEY = "deferred_sub_id_key";
-
- @VisibleForTesting
- interface SubIdProcessor{
- void process(Context context,int subId);
- }
-
- private SubIdProcessor mSubIdProcessor = new SubIdProcessor() {
- @Override
- public void process(Context context, int subId) {
- SimChangeReceiver.processSubId(context,subId);
- }
- };
-
- /**
- * Write the subId to the the list.
- */
- public static void addDeferredSubId(Context context, int subId) {
- SharedPreferences sharedPreferences = getSubIdSharedPreference(context);
- Set<String> subIds =
- new ArraySet<>(sharedPreferences.getStringSet(DEFERRED_SUBID_LIST_KEY, null));
- subIds.add(String.valueOf(subId));
- sharedPreferences.edit().putStringSet(DEFERRED_SUBID_LIST_KEY, subIds).apply();
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- // Listens to android.intent.action.BOOT_COMPLETED
- if(!intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
- return;
- }
-
- Log.v(TAG, "processing deferred subId list");
- Set<Integer> subIds = readAndDeleteSubIds(context);
- for (Integer subId : subIds) {
- Log.v(TAG, "processing subId " + subId);
- mSubIdProcessor.process(context, subId);
- }
- }
-
- /**
- * Read all subId from the list to a unique integer set, and delete the preference.
- */
- private static Set<Integer> readAndDeleteSubIds(Context context) {
- SharedPreferences sharedPreferences = getSubIdSharedPreference(context);
- Set<String> subIdStrings = sharedPreferences.getStringSet(DEFERRED_SUBID_LIST_KEY, null);
- Set<Integer> subIds = new ArraySet<>();
- if(subIdStrings == null) {
- return subIds;
- }
- for(String string : subIdStrings){
- subIds.add(Integer.valueOf(string));
- }
- getSubIdSharedPreference(context).edit().remove(DEFERRED_SUBID_LIST_KEY).apply();
- return subIds;
- }
-
- @VisibleForTesting
- void setSubIdProcessorForTest(SubIdProcessor processor){
- mSubIdProcessor = processor;
- }
-
- private static SharedPreferences getSubIdSharedPreference(Context context) {
- return PreferenceManager
- .getDefaultSharedPreferences(context.createDeviceProtectedStorageContext());
- }
-}
diff --git a/src/com/android/phone/vvm/omtp/OmtpConstants.java b/src/com/android/phone/vvm/omtp/OmtpConstants.java
index fa3cb63..3f5722f 100644
--- a/src/com/android/phone/vvm/omtp/OmtpConstants.java
+++ b/src/com/android/phone/vvm/omtp/OmtpConstants.java
@@ -15,22 +15,24 @@
*/
package com.android.phone.vvm.omtp;
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.Map;
/**
- * Wrapper class to hold relevant OMTP constants as defined in the OMTP spec.
- * <p>
- * In essence this is a programmatic representation of the relevant portions of OMTP spec.
+ * Wrapper class to hold relevant OMTP constants as defined in the OMTP spec. <p> In essence this is
+ * a programmatic representation of the relevant portions of OMTP spec.
*/
public class OmtpConstants {
public static final String SMS_FIELD_SEPARATOR = ";";
public static final String SMS_KEY_VALUE_SEPARATOR = "=";
public static final String SMS_PREFIX_SEPARATOR = ":";
- public static final String CLIENT_PREFIX = "//VVM";
- public static final String SYNC_SMS_PREFIX = CLIENT_PREFIX + ":SYNC:";
- public static final String STATUS_SMS_PREFIX = CLIENT_PREFIX + ":STATUS:";
+ public static final String SYNC_SMS_PREFIX = "SYNC";
+ public static final String STATUS_SMS_PREFIX = "STATUS";
// This is the format designated by the OMTP spec.
public static final String DATE_TIME_FORMAT = "dd/MM/yyyy HH:mm Z";
@@ -123,6 +125,7 @@
public static final String SERVER_ADDRESS = "srv";
/** Phone number to access voicemails through Telephony User Interface */
public static final String TUI_ACCESS_NUMBER = "tui";
+ public static final String TUI_PASSWORD_LENGTH = "pw_len";
/** Number to send client origination SMS */
public static final String CLIENT_SMS_DESTINATION_NUMBER = "dn";
public static final String IMAP_PORT = "ipt";
@@ -137,8 +140,6 @@
* <p>
* Referred by {@link OmtpConstants#PROVISIONING_STATUS}.
*/
- // TODO: As per the spec the code could be either be with or w/o quotes = "N"/N). Currently
- // this only handles the w/o quotes values.
public static final String SUBSCRIBER_NEW = "N";
public static final String SUBSCRIBER_READY = "R";
public static final String SUBSCRIBER_PROVISIONED = "P";
@@ -188,6 +189,61 @@
put(RETURN_CODE, RETURN_CODE_VALUES);
}};
+ /**
+ * IMAP command extensions
+ */
+
+ /**
+ * OMTP spec v1.3 2.3.1 Change password request syntax
+ *
+ * This changes the PIN to access the Telephone User Interface, the traditional voicemail
+ * system.
+ */
+ public static final String IMAP_CHANGE_TUI_PWD_FORMAT = "XCHANGE_TUI_PWD PWD=%1$s OLD_PWD=%2$s";
+
+ /**
+ * OMTP spec v1.3 2.4.1 Change languate request syntax
+ *
+ * This changes the language in the Telephone User Interface.
+ */
+ public static final String IMAP_CHANGE_VM_LANG_FORMAT = "XCHANGE_VM_LANG LANG=%1$s";
+
+ /**
+ * OMTP spec v1.3 2.5.1 Close NUT Request syntax
+ *
+ * This disables the new user tutorial, the message played to new users calling in the Telephone
+ * User Interface.
+ */
+ public static final String IMAP_CLOSE_NUT = "XCLOSE_NUT";
+
+ /**
+ * Possible NO responses for CHANGE_TUI_PWD
+ */
+
+ public static final String RESPONSE_CHANGE_PIN_TOO_SHORT = "password too short";
+ public static final String RESPONSE_CHANGE_PIN_TOO_LONG = "password too long";
+ public static final String RESPONSE_CHANGE_PIN_TOO_WEAK = "password too weak";
+ public static final String RESPONSE_CHANGE_PIN_MISMATCH = "old password mismatch";
+ public static final String RESPONSE_CHANGE_PIN_INVALID_CHARACTER =
+ "password contains invalid characters";
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {CHANGE_PIN_SUCCESS, CHANGE_PIN_TOO_SHORT, CHANGE_PIN_TOO_LONG,
+ CHANGE_PIN_TOO_WEAK, CHANGE_PIN_MISMATCH, CHANGE_PIN_INVALID_CHARACTER,
+ CHANGE_PIN_SYSTEM_ERROR})
+
+ public @interface ChangePinResult {
+
+ }
+
+ public static final int CHANGE_PIN_SUCCESS = 0;
+ public static final int CHANGE_PIN_TOO_SHORT = 1;
+ public static final int CHANGE_PIN_TOO_LONG = 2;
+ public static final int CHANGE_PIN_TOO_WEAK = 3;
+ public static final int CHANGE_PIN_MISMATCH = 4;
+ public static final int CHANGE_PIN_INVALID_CHARACTER = 5;
+ public static final int CHANGE_PIN_SYSTEM_ERROR = 6;
+
/** Indicates the client is Google visual voicemail version 1.0. */
public static final String CLIENT_TYPE_GOOGLE_10 = "google.vvm.10";
}
diff --git a/src/com/android/phone/vvm/omtp/OmtpEvents.java b/src/com/android/phone/vvm/omtp/OmtpEvents.java
new file mode 100644
index 0000000..7a89418
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/OmtpEvents.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Events internal to the OMTP client. These should be translated into {@link
+ * android.provider.VoicemailContract.Status} error codes before writing into the voicemail status
+ * table.
+ */
+public enum OmtpEvents {
+
+ // Configuration State
+ CONFIG_REQUEST_STATUS_SUCCESS(Type.CONFIGURATION, true),
+
+ CONFIG_PIN_SET(Type.CONFIGURATION, true),
+ // The voicemail PIN is replaced with a generated PIN, user should change it.
+ CONFIG_DEFAULT_PIN_REPLACED(Type.CONFIGURATION, true),
+ CONFIG_ACTIVATING(Type.CONFIGURATION, true),
+ // There are already activation records, this is only a book-keeping activation.
+ CONFIG_ACTIVATING_SUBSEQUENT(Type.CONFIGURATION, true),
+ CONFIG_STATUS_SMS_TIME_OUT(Type.CONFIGURATION),
+ CONFIG_SERVICE_NOT_AVAILABLE(Type.CONFIGURATION),
+
+ // Data channel State
+
+ // A new sync has started, old errors in data channel should be cleared.
+ DATA_IMAP_OPERATION_STARTED(Type.DATA_CHANNEL, true),
+ // Successfully downloaded/uploaded data from the server, which means the data channel is clear.
+ DATA_IMAP_OPERATION_COMPLETED(Type.DATA_CHANNEL, true),
+ // The port provided in the STATUS SMS is invalid.
+ DATA_INVALID_PORT(Type.DATA_CHANNEL),
+ // No connection to the internet, and the carrier requires cellular data
+ DATA_NO_CONNECTION_CELLULAR_REQUIRED(Type.DATA_CHANNEL),
+ // No connection to the internet.
+ DATA_NO_CONNECTION(Type.DATA_CHANNEL),
+ // Address lookup for the server hostname failed. DNS error?
+ DATA_CANNOT_RESOLVE_HOST_ON_NETWORK(Type.DATA_CHANNEL),
+ // All destination address that resolves to the server hostname are rejected or timed out
+ DATA_ALL_SOCKET_CONNECTION_FAILED(Type.DATA_CHANNEL),
+ // Failed to establish SSL with the server, either with a direct SSL connection or by
+ // STARTTLS command
+ DATA_CANNOT_ESTABLISH_SSL_SESSION(Type.DATA_CHANNEL),
+ // Identity of the server cannot be verified.
+ DATA_SSL_INVALID_HOST_NAME(Type.DATA_CHANNEL),
+ // The server rejected our username/password
+ DATA_BAD_IMAP_CREDENTIAL(Type.DATA_CHANNEL),
+
+ DATA_AUTH_UNKNOWN_USER(Type.DATA_CHANNEL),
+ DATA_AUTH_UNKNOWN_DEVICE(Type.DATA_CHANNEL),
+ DATA_AUTH_INVALID_PASSWORD(Type.DATA_CHANNEL),
+ DATA_AUTH_MAILBOX_NOT_INITIALIZED(Type.DATA_CHANNEL),
+ DATA_AUTH_SERVICE_NOT_PROVISIONED(Type.DATA_CHANNEL),
+ DATA_AUTH_SERVICE_NOT_ACTIVATED(Type.DATA_CHANNEL),
+ DATA_AUTH_USER_IS_BLOCKED(Type.DATA_CHANNEL),
+
+ // A command to the server didn't result with an "OK" or continuation request
+ DATA_REJECTED_SERVER_RESPONSE(Type.DATA_CHANNEL),
+ // The server did not greet us with a "OK", possibly not a IMAP server.
+ DATA_INVALID_INITIAL_SERVER_RESPONSE(Type.DATA_CHANNEL),
+ // An IOException occurred while trying to open an ImapConnection
+ // TODO: reduce scope
+ DATA_IOE_ON_OPEN(Type.DATA_CHANNEL),
+ // The SELECT command on a mailbox is rejected
+ DATA_MAILBOX_OPEN_FAILED(Type.DATA_CHANNEL),
+ // An IOException has occurred
+ // TODO: reduce scope
+ DATA_GENERIC_IMAP_IOE(Type.DATA_CHANNEL),
+ // An SslException has occurred while opening an ImapConnection
+ // TODO: reduce scope
+ DATA_SSL_EXCEPTION(Type.DATA_CHANNEL),
+
+ // Notification Channel
+
+ // Cell signal restored, can received VVM SMSs
+ NOTIFICATION_IN_SERVICE(Type.NOTIFICATION_CHANNEL, true),
+ // Cell signal lost, cannot received VVM SMSs
+ NOTIFICATION_SERVICE_LOST(Type.NOTIFICATION_CHANNEL, false),
+
+
+ // Other
+ OTHER_SOURCE_REMOVED(Type.OTHER, false),
+
+ // VVM3
+ VVM3_NEW_USER_SETUP_FAILED,
+ // Table 4. client internal error handling
+ VVM3_VMG_DNS_FAILURE,
+ VVM3_SPG_DNS_FAILURE,
+ VVM3_VMG_CONNECTION_FAILED,
+ VVM3_SPG_CONNECTION_FAILED,
+ VVM3_VMG_TIMEOUT,
+ VVM3_STATUS_SMS_TIMEOUT,
+
+ VVM3_SUBSCRIBER_PROVISIONED,
+ VVM3_SUBSCRIBER_BLOCKED,
+ VVM3_SUBSCRIBER_UNKNOWN;
+
+ public static class Type {
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({CONFIGURATION, DATA_CHANNEL, NOTIFICATION_CHANNEL, OTHER})
+ public @interface Values {
+
+ }
+
+ public static final int CONFIGURATION = 1;
+ public static final int DATA_CHANNEL = 2;
+ public static final int NOTIFICATION_CHANNEL = 3;
+ public static final int OTHER = 4;
+ }
+
+ private final int mType;
+ private final boolean mIsSuccess;
+
+ OmtpEvents(int type, boolean isSuccess) {
+ mType = type;
+ mIsSuccess = isSuccess;
+ }
+
+ OmtpEvents(int type) {
+ mType = type;
+ mIsSuccess = false;
+ }
+
+ OmtpEvents() {
+ mType = Type.OTHER;
+ mIsSuccess = false;
+ }
+
+ @Type.Values
+ public int getType() {
+ return mType;
+ }
+
+ public boolean isSuccess() {
+ return mIsSuccess;
+ }
+
+}
diff --git a/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java b/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java
index 9534a10..0b321b5 100644
--- a/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java
+++ b/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelper.java
@@ -15,60 +15,189 @@
*/
package com.android.phone.vvm.omtp;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
import android.os.PersistableBundle;
+import android.telecom.PhoneAccountHandle;
import android.telephony.CarrierConfigManager;
-import android.telephony.SmsManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.VisualVoicemailSmsFilterSettings;
import android.text.TextUtils;
-import android.util.Log;
-
-import com.android.phone.vvm.omtp.sms.OmtpCvvmMessageSender;
-import com.android.phone.vvm.omtp.sms.OmtpMessageSender;
-import com.android.phone.vvm.omtp.sms.OmtpStandardMessageSender;
+import android.util.ArraySet;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.protocol.VisualVoicemailProtocol;
+import com.android.phone.vvm.omtp.protocol.VisualVoicemailProtocolFactory;
+import com.android.phone.vvm.omtp.sms.StatusMessage;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+import java.util.Arrays;
+import java.util.Set;
/**
- * Handle activation and deactivation of a visual voicemail source. This class is necessary to
- * retrieve carrier vvm configuration details before sending the appropriate texts.
+ * Manages carrier dependent visual voicemail configuration values. The primary source is the value
+ * retrieved from CarrierConfigManager. If CarrierConfigManager does not provide the config
+ * (KEY_VVM_TYPE_STRING is empty, or "hidden" configs), then the value hardcoded in telephony will
+ * be used (in res/xml/vvm_config.xml)
+ *
+ * Hidden configs are new configs that are planned for future APIs, or miscellaneous settings that
+ * may clutter CarrierConfigManager too much.
+ *
+ * The current hidden configs are: {@link #getSslPort()} {@link #getDisabledCapabilities()}
*/
public class OmtpVvmCarrierConfigHelper {
private static final String TAG = "OmtpVvmCarrierCfgHlpr";
- private Context mContext;
- private int mSubId;
- private PersistableBundle mCarrierConfig;
- private String mVvmType;
+
+ static final String KEY_VVM_TYPE_STRING = CarrierConfigManager.KEY_VVM_TYPE_STRING;
+ static final String KEY_VVM_DESTINATION_NUMBER_STRING =
+ CarrierConfigManager.KEY_VVM_DESTINATION_NUMBER_STRING;
+ static final String KEY_VVM_PORT_NUMBER_INT =
+ CarrierConfigManager.KEY_VVM_PORT_NUMBER_INT;
+ static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING =
+ CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING;
+ static final String KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY =
+ "carrier_vvm_package_name_string_array";
+ static final String KEY_VVM_PREFETCH_BOOL =
+ CarrierConfigManager.KEY_VVM_PREFETCH_BOOL;
+ static final String KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL =
+ CarrierConfigManager.KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL;
+
+ /**
+ * @see #getSslPort()
+ */
+ static final String KEY_VVM_SSL_PORT_NUMBER_INT =
+ "vvm_ssl_port_number_int";
+
+ /**
+ * @see #isLegacyModeEnabled()
+ */
+ static final String KEY_VVM_LEGACY_MODE_ENABLED_BOOL =
+ "vvm_legacy_mode_enabled_bool";
+
+ /**
+ * Ban a capability reported by the server from being used. The array of string should be a
+ * subset of the capabilities returned IMAP CAPABILITY command.
+ *
+ * @see #getDisabledCapabilities()
+ */
+ static final String KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY =
+ "vvm_disabled_capabilities_string_array";
+ static final String KEY_VVM_CLIENT_PREFIX_STRING =
+ "vvm_client_prefix_string";
+
+ private final Context mContext;
+ private final int mSubId;
+ private final PersistableBundle mCarrierConfig;
+ private final String mVvmType;
+ private final VisualVoicemailProtocol mProtocol;
+ private final PersistableBundle mTelephonyConfig;
+
+ private PhoneAccountHandle mPhoneAccountHandle;
public OmtpVvmCarrierConfigHelper(Context context, int subId) {
mContext = context;
mSubId = subId;
mCarrierConfig = getCarrierConfig();
+
+ TelephonyManager telephonyManager =
+ (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ mTelephonyConfig = new TelephonyVvmConfigManager(context.getResources())
+ .getConfig(telephonyManager.getSimOperator(subId));
+
mVvmType = getVvmType();
+ mProtocol = VisualVoicemailProtocolFactory.create(mContext.getResources(), mVvmType);
}
+ public OmtpVvmCarrierConfigHelper(Context context, PhoneAccountHandle handle) {
+ this(context, PhoneAccountHandleConverter.toSubId(handle));
+ mPhoneAccountHandle = handle;
+ }
+
+ @VisibleForTesting
+ OmtpVvmCarrierConfigHelper(Context context, PersistableBundle carrierConfig,
+ PersistableBundle telephonyConfig) {
+ mContext = context;
+ mSubId = 0;
+ mCarrierConfig = carrierConfig;
+ mTelephonyConfig = telephonyConfig;
+ mVvmType = getVvmType();
+ mProtocol = VisualVoicemailProtocolFactory.create(mContext.getResources(), mVvmType);
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public int getSubId() {
+ return mSubId;
+ }
+
+ @Nullable
+ public PhoneAccountHandle getPhoneAccountHandle() {
+ if (mPhoneAccountHandle == null) {
+ mPhoneAccountHandle = PhoneAccountHandleConverter.fromSubId(mSubId);
+ if (mPhoneAccountHandle == null) {
+ VvmLog.e(TAG, "null phone account for subId " + mSubId);
+ }
+ }
+ return mPhoneAccountHandle;
+ }
+
+ /**
+ * return whether the carrier's visual voicemail is supported, with KEY_VVM_TYPE_STRING set as a
+ * known protocol.
+ */
+ public boolean isValid() {
+ return mProtocol != null;
+ }
+
+ @Nullable
public String getVvmType() {
- if (mCarrierConfig == null) {
- return null;
- }
-
- return mCarrierConfig.getString(
- CarrierConfigManager.KEY_VVM_TYPE_STRING, null);
+ return (String) getValue(KEY_VVM_TYPE_STRING);
}
- public String getCarrierVvmPackageName() {
- if (mCarrierConfig == null) {
- return null;
- }
-
- return mCarrierConfig.getString(
- CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING, null);
+ @Nullable
+ public VisualVoicemailProtocol getProtocol() {
+ return mProtocol;
}
- public boolean isOmtpVvmType() {
- return (TelephonyManager.VVM_TYPE_OMTP.equals(mVvmType) ||
- TelephonyManager.VVM_TYPE_CVVM.equals(mVvmType));
+ /**
+ * @returns arbitrary String stored in the config file. Used for protocol specific values.
+ */
+ @Nullable
+ public String getString(String key) {
+ return (String) getValue(key);
+ }
+
+ @Nullable
+ public Set<String> getCarrierVvmPackageNames() {
+ Set<String> names = getCarrierVvmPackageNames(mCarrierConfig);
+ if (names != null) {
+ return names;
+ }
+ return getCarrierVvmPackageNames(mTelephonyConfig);
+ }
+
+ private static Set<String> getCarrierVvmPackageNames(@Nullable PersistableBundle bundle) {
+ if (bundle == null) {
+ return null;
+ }
+ Set<String> names = new ArraySet<>();
+ if (bundle.containsKey(KEY_CARRIER_VVM_PACKAGE_NAME_STRING)) {
+ names.add(bundle.getString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING));
+ }
+ if (bundle.containsKey(KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY)) {
+ names.addAll(Arrays.asList(
+ bundle.getStringArray(KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY)));
+ }
+ if (names.isEmpty()) {
+ return null;
+ }
+ return names;
}
/**
@@ -76,97 +205,241 @@
* so by checking if the carrier's voicemail app is installed.
*/
public boolean isEnabledByDefault() {
- String packageName = mCarrierConfig.getString(
- CarrierConfigManager.KEY_CARRIER_VVM_PACKAGE_NAME_STRING);
- if (packageName == null) {
- return true;
- }
- try {
- mContext.getPackageManager().getPackageInfo(packageName, 0);
+ if (!isValid()) {
return false;
- } catch (NameNotFoundException e) {
+ }
+
+ Set<String> carrierPackages = getCarrierVvmPackageNames();
+ if (carrierPackages == null) {
return true;
}
+ for (String packageName : carrierPackages) {
+ try {
+ mContext.getPackageManager().getPackageInfo(packageName, 0);
+ return false;
+ } catch (NameNotFoundException e) {
+ // Do nothing.
+ }
+ }
+ return true;
}
public boolean isCellularDataRequired() {
- if (mCarrierConfig == null) {
- return false;
- }
- return mCarrierConfig
- .getBoolean(CarrierConfigManager.KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL);
+ return (boolean) getValue(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL, false);
}
public boolean isPrefetchEnabled() {
- if (mCarrierConfig == null) {
- return false;
+ return (boolean) getValue(KEY_VVM_PREFETCH_BOOL, true);
+ }
+
+
+ public int getApplicationPort() {
+ return (int) getValue(KEY_VVM_PORT_NUMBER_INT, 0);
+ }
+
+ @Nullable
+ public String getDestinationNumber() {
+ return (String) getValue(KEY_VVM_DESTINATION_NUMBER_STRING);
+ }
+
+ /**
+ * Hidden config.
+ *
+ * @return Port to start a SSL IMAP connection directly.
+ *
+ * TODO: make config public and add to CarrierConfigManager
+ */
+ public int getSslPort() {
+ return (int) getValue(KEY_VVM_SSL_PORT_NUMBER_INT, 0);
+ }
+
+ /**
+ * Hidden Config.
+ *
+ * <p>Sometimes the server states it supports a certain feature but we found they have bug on
+ * the server side. For example, in b/28717550 the server reported AUTH=DIGEST-MD5 capability
+ * but using it to login will cause subsequent response to be erroneous.
+ *
+ * @return A set of capabilities that is reported by the IMAP CAPABILITY command, but determined
+ * to have issues and should not be used.
+ */
+ @Nullable
+ public Set<String> getDisabledCapabilities() {
+ Set<String> disabledCapabilities = getDisabledCapabilities(mCarrierConfig);
+ if (disabledCapabilities != null) {
+ return disabledCapabilities;
}
- return mCarrierConfig
- .getBoolean(CarrierConfigManager.KEY_VVM_PREFETCH_BOOL);
+ return getDisabledCapabilities(mTelephonyConfig);
+ }
+
+ @Nullable
+ private static Set<String> getDisabledCapabilities(@Nullable PersistableBundle bundle) {
+ if (bundle == null) {
+ return null;
+ }
+ if (!bundle.containsKey(KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY)) {
+ return null;
+ }
+ ArraySet<String> result = new ArraySet<String>();
+ result.addAll(
+ Arrays.asList(bundle.getStringArray(KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY)));
+ return result;
+ }
+
+ public String getClientPrefix() {
+ String prefix = (String) getValue(KEY_VVM_CLIENT_PREFIX_STRING);
+ if (prefix != null) {
+ return prefix;
+ }
+ return "//VVM";
+ }
+
+ /**
+ * Should legacy mode be used when the OMTP VVM client is disabled?
+ *
+ * <p>Legacy mode is a mode that on the carrier side visual voicemail is still activated, but on
+ * the client side all network operations are disabled. SMSs are still monitored so a new
+ * message SYNC SMS will be translated to show a message waiting indicator, like traditional
+ * voicemails.
+ *
+ * <p>This is for carriers that does not support VVM deactivation so voicemail can continue to
+ * function without the data cost.
+ */
+ public boolean isLegacyModeEnabled() {
+ return (boolean) getValue(KEY_VVM_LEGACY_MODE_ENABLED_BOOL, false);
}
public void startActivation() {
- OmtpMessageSender messageSender = getMessageSender();
- if (messageSender != null) {
- Log.i(TAG, "Requesting VVM activation for subId: " + mSubId);
- messageSender.requestVvmActivation(null);
+ PhoneAccountHandle phoneAccountHandle = getPhoneAccountHandle();
+ if (phoneAccountHandle == null) {
+ // This should never happen
+ // Error logged in getPhoneAccountHandle().
+ return;
}
+
+ if (mVvmType == null || mVvmType.isEmpty()) {
+ // The VVM type is invalid; we should never have gotten here in the first place since
+ // this is loaded initially in the constructor, and callers should check isValid()
+ // before trying to start activation anyways.
+ VvmLog.e(TAG, "startActivation : vvmType is null or empty for account " +
+ phoneAccountHandle);
+ return;
+ }
+
+ activateSmsFilter();
+
+ if (mProtocol != null) {
+ ActivationTask.start(mContext, mSubId, null);
+ }
+ }
+
+ public void activateSmsFilter() {
+ TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
+ telephonyManager.enableVisualVoicemailSmsFilter(mSubId,
+ new VisualVoicemailSmsFilterSettings.Builder().setClientPrefix(getClientPrefix())
+ .build());
}
public void startDeactivation() {
- OmtpMessageSender messageSender = getMessageSender();
- if (messageSender != null) {
- Log.i(TAG, "Requesting VVM deactivation for subId: " + mSubId);
- messageSender.requestVvmDeactivation(null);
+ if (!isLegacyModeEnabled()) {
+ // SMS should still be filtered in legacy mode
+ mContext.getSystemService(TelephonyManager.class)
+ .disableVisualVoicemailSmsFilter(mSubId);
+ }
+ if (mProtocol != null) {
+ mProtocol.startDeactivation(this);
}
}
+ public boolean supportsProvisioning() {
+ if (mProtocol != null) {
+ return mProtocol.supportsProvisioning();
+ }
+ return false;
+ }
+
+ public void startProvisioning(ActivationTask task, PhoneAccountHandle phone,
+ VoicemailStatus.Editor status, StatusMessage message, Bundle data) {
+ if (mProtocol != null) {
+ mProtocol.startProvisioning(task, phone, this, status, message, data);
+ }
+ }
+
+ public void requestStatus(@Nullable PendingIntent sentIntent) {
+ if (mProtocol != null) {
+ mProtocol.requestStatus(this, sentIntent);
+ }
+ }
+
+ public void handleEvent(VoicemailStatus.Editor status, OmtpEvents event) {
+ VvmLog.i(TAG, "OmtpEvent:" + event);
+ if (mProtocol != null) {
+ mProtocol.handleEvent(mContext, this, status, event);
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("OmtpVvmCarrierConfigHelper [");
+ builder.append("subId: ").append(getSubId())
+ .append(", carrierConfig: ").append(mCarrierConfig != null)
+ .append(", telephonyConfig: ").append(mTelephonyConfig != null)
+ .append(", type: ").append(getVvmType())
+ .append(", destinationNumber: ").append(getDestinationNumber())
+ .append(", applicationPort: ").append(getApplicationPort())
+ .append(", sslPort: ").append(getSslPort())
+ .append(", isEnabledByDefault: ").append(isEnabledByDefault())
+ .append(", isCellularDataRequired: ").append(isCellularDataRequired())
+ .append(", isPrefetchEnabled: ").append(isPrefetchEnabled())
+ .append(", isLegacyModeEnabled: ").append(isLegacyModeEnabled())
+ .append("]");
+ return builder.toString();
+ }
+
+ @Nullable
private PersistableBundle getCarrierConfig() {
if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
- Log.w(TAG, "Invalid subscriptionId or subscriptionId not provided in intent.");
+ VvmLog
+ .w(TAG, "Invalid subscriptionId or subscriptionId not provided in intent.");
return null;
}
CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
if (carrierConfigManager == null) {
- Log.w(TAG, "No carrier config service found.");
+ VvmLog.w(TAG, "No carrier config service found.");
return null;
}
- return carrierConfigManager.getConfigForSubId(mSubId);
+ PersistableBundle config = carrierConfigManager.getConfigForSubId(mSubId);
+
+ if (TextUtils.isEmpty(config.getString(CarrierConfigManager.KEY_VVM_TYPE_STRING))) {
+ return null;
+ }
+ return config;
}
- private OmtpMessageSender getMessageSender() {
- if (mCarrierConfig == null) {
- Log.w(TAG, "Empty carrier config.");
- return null;
- }
-
- int applicationPort = mCarrierConfig.getInt(
- CarrierConfigManager.KEY_VVM_PORT_NUMBER_INT, 0);
- String destinationNumber = mCarrierConfig.getString(
- CarrierConfigManager.KEY_VVM_DESTINATION_NUMBER_STRING);
- if (TextUtils.isEmpty(destinationNumber)) {
- Log.w(TAG, "No destination number for this carrier.");
- return null;
- }
-
- OmtpMessageSender messageSender = null;
- SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(mSubId);
- switch (mVvmType) {
- case TelephonyManager.VVM_TYPE_OMTP:
- messageSender = new OmtpStandardMessageSender(smsManager, (short) applicationPort,
- destinationNumber, null, OmtpConstants.PROTOCOL_VERSION1_1, null);
- break;
- case TelephonyManager.VVM_TYPE_CVVM:
- messageSender = new OmtpCvvmMessageSender(smsManager, (short) applicationPort,
- destinationNumber);
- break;
- default:
- Log.w(TAG, "Unexpected visual voicemail type: " + mVvmType);
- }
-
- return messageSender;
+ @Nullable
+ private Object getValue(String key) {
+ return getValue(key, null);
}
+
+ @Nullable
+ private Object getValue(String key, Object defaultValue) {
+ Object result;
+ if (mCarrierConfig != null) {
+ result = mCarrierConfig.get(key);
+ if (result != null) {
+ return result;
+ }
+ }
+ if (mTelephonyConfig != null) {
+ result = mTelephonyConfig.get(key);
+ if (result != null) {
+ return result;
+ }
+ }
+ return defaultValue;
+ }
+
}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
index 0a37493..25c27db 100644
--- a/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
+++ b/src/com/android/phone/vvm/omtp/SimChangeReceiver.java
@@ -18,20 +18,21 @@
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.os.UserHandle;
+import android.content.pm.IPackageManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.UserManager;
import android.telecom.PhoneAccountHandle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
-import android.util.Log;
-
+import android.telephony.TelephonyManager;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;
-import com.android.phone.PhoneUtils;
-import com.android.phone.R;
+import com.android.phone.VoicemailStatus;
import com.android.phone.settings.VisualVoicemailSettingsUtil;
import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
/**
* This class listens to the {@link CarrierConfigManager#ACTION_CARRIER_CONFIG_CHANGED} and {@link
@@ -43,18 +44,13 @@
*/
public class SimChangeReceiver extends BroadcastReceiver {
- private static final String TAG = "SimChangeReceiver";
+ private static final String TAG = "VvmSimChangeReceiver";
@Override
public void onReceive(Context context, Intent intent) {
- if (UserHandle.myUserId() != UserHandle.USER_SYSTEM) {
- Log.v(TAG, "Received broadcast for user that is not system.");
- return;
- }
-
final String action = intent.getAction();
if (action == null) {
- Log.w(TAG, "Null action for intent.");
+ VvmLog.w(TAG, "Null action for intent.");
return;
}
@@ -62,7 +58,7 @@
case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(
intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE))) {
- Log.i(TAG, "Sim removed, removing inactive accounts");
+ VvmLog.i(TAG, "Sim removed, removing inactive accounts");
OmtpVvmSourceManager.getInstance(context).removeInactiveSources();
}
break;
@@ -70,59 +66,71 @@
int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
- Log.i(TAG, "Received SIM change for invalid subscription id.");
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ VvmLog.i(TAG, "Received SIM change for invalid subscription id.");
return;
}
-
- if (!UserManager.get(context).isUserUnlocked()) {
- OmtpBootCompletedReceiver.addDeferredSubId(context, subId);
- } else {
+ VvmLog.d(TAG, "Carrier config changed");
+ if (UserManager.get(context).isUserUnlocked() && !isCryptKeeperMode()) {
processSubId(context, subId);
+ } else {
+ VvmLog.d(TAG, "User locked, activation request delayed until unlock");
+ // After the device is unlocked, VvmBootCompletedReceiver will iterate through
+ // all call capable subIds, nothing need to be done here.
}
break;
}
}
public static void processSubId(Context context, int subId) {
+ PhoneAccountHandle phoneAccount = PhoneAccountHandleConverter.fromSubId(subId);
+ if (phoneAccount == null) {
+ // This should never happen
+ VvmLog.e(TAG, "unable to convert subId " + subId + " to PhoneAccountHandle");
+ return;
+ }
+
OmtpVvmCarrierConfigHelper carrierConfigHelper =
new OmtpVvmCarrierConfigHelper(context, subId);
- if (carrierConfigHelper.isOmtpVvmType()) {
- PhoneAccountHandle phoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
- SubscriptionManager.getPhoneId(subId));
-
- boolean isUserSet = VisualVoicemailSettingsUtil.isVisualVoicemailUserSet(
- context, phoneAccount);
- boolean isEnabledInSettings =
- VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(context,
- phoneAccount);
- boolean isSupported =
- context.getResources().getBoolean(R.bool.allow_visual_voicemail);
- boolean isEnabled = isSupported && (isUserSet ? isEnabledInSettings :
- carrierConfigHelper.isEnabledByDefault());
-
- if (!isUserSet) {
- // Preserve the previous setting for "isVisualVoicemailEnabled" if it is
- // set by the user, otherwise, set this value for the first time.
- VisualVoicemailSettingsUtil.setVisualVoicemailEnabled(context, phoneAccount,
- isEnabled, /** isUserSet */false);
- }
-
- if (isEnabled) {
- LocalLogHelper.log(TAG, "Sim state or carrier config changed: requesting"
- + " activation for " + phoneAccount.getId());
-
+ if (carrierConfigHelper.isValid()) {
+ if (VisualVoicemailSettingsUtil.isEnabled(context, phoneAccount)) {
+ VvmLog.i(TAG, "Sim state or carrier config changed for " + subId);
// Add a phone state listener so that changes to the communication channels
// can be recorded.
OmtpVvmSourceManager.getInstance(context).addPhoneStateListener(
phoneAccount);
carrierConfigHelper.startActivation();
} else {
+ if (carrierConfigHelper.isLegacyModeEnabled()) {
+ // SMS still need to be filtered under legacy mode.
+ VvmLog.i(TAG, "activating SMS filter for legacy mode");
+ carrierConfigHelper.activateSmsFilter();
+ }
// It may be that the source was not registered to begin with but we want
// to run through the steps to remove the source just in case.
OmtpVvmSourceManager.getInstance(context).removeSource(phoneAccount);
- Log.v(TAG, "Sim change for disabled account.");
+ VvmLog.v(TAG, "Sim change for disabled account.");
}
+ } else {
+ String mccMnc = context.getSystemService(TelephonyManager.class).getSimOperator(subId);
+ VvmLog.d(TAG,
+ "visual voicemail not supported for carrier " + mccMnc + " on subId " + subId);
+ VoicemailStatus.disable(context, phoneAccount);
}
}
+
+ /**
+ * CryptKeeper mode is the pre-file based encryption locked state, when the user has selected
+ * "Require password to boot" and the device hasn't been unlocked yet during a reboot. {@link
+ * UserManager#isUserUnlocked()} will still return true in this mode, but storage in /data and
+ * all content providers will not be available(including SharedPreference).
+ */
+ private static boolean isCryptKeeperMode() {
+ try {
+ return IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
+ isOnlyCoreApps();
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/TelephonyVvmConfigManager.java b/src/com/android/phone/vvm/omtp/TelephonyVvmConfigManager.java
new file mode 100644
index 0000000..e91481e
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/TelephonyVvmConfigManager.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.annotation.Nullable;
+import android.content.res.Resources;
+import android.os.PersistableBundle;
+import android.util.ArrayMap;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.R;
+import com.android.phone.vvm.omtp.utils.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Load and caches telephony vvm config from res/xml/vvm_config.xml
+ */
+public class TelephonyVvmConfigManager {
+
+ private static final String TAG = "TelephonyVvmCfgMgr";
+
+ private static final boolean USE_DEBUG_CONFIG = false; //STOPSHIP if true
+
+ private static final String TAG_PERSISTABLEMAP = "pbundle_as_map";
+
+ static final String KEY_MCCMNC = "mccmnc";
+
+ private static Map<String, PersistableBundle> sCachedConfigs;
+
+ private final Map<String, PersistableBundle> mConfigs;
+
+ public TelephonyVvmConfigManager(Resources resources) {
+ if (sCachedConfigs == null) {
+ sCachedConfigs = loadConfigs(resources.getXml(R.xml.vvm_config));
+ }
+ mConfigs = sCachedConfigs;
+ }
+
+ @VisibleForTesting
+ TelephonyVvmConfigManager(XmlPullParser parser) {
+ mConfigs = loadConfigs(parser);
+ }
+
+ @Nullable
+ public PersistableBundle getConfig(String mccMnc) {
+ if (USE_DEBUG_CONFIG) {
+ return mConfigs.get("TEST");
+ }
+ return mConfigs.get(mccMnc);
+ }
+
+ private static Map<String, PersistableBundle> loadConfigs(XmlPullParser parser) {
+ Map<String, PersistableBundle> configs = new ArrayMap<>();
+ try {
+ ArrayList list = readBundleList(parser);
+ for (Object object : list) {
+ if (!(object instanceof PersistableBundle)) {
+ throw new IllegalArgumentException("PersistableBundle expected, got " + object);
+ }
+ PersistableBundle bundle = (PersistableBundle) object;
+ String[] mccMncs = bundle.getStringArray(KEY_MCCMNC);
+ if (mccMncs == null) {
+ throw new IllegalArgumentException("MCCMNC is null");
+ }
+ for (String mccMnc : mccMncs) {
+ configs.put(mccMnc, bundle);
+ }
+ }
+ } catch (IOException | XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+ return configs;
+ }
+
+ @Nullable
+ public static ArrayList readBundleList(XmlPullParser in) throws IOException,
+ XmlPullParserException {
+ final int outerDepth = in.getDepth();
+ int event;
+ while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
+ (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
+ if (event == XmlPullParser.START_TAG) {
+ final String startTag = in.getName();
+ final String[] tagName = new String[1];
+ in.next();
+ return XmlUtils.readThisListXml(in, startTag, tagName,
+ new MyReadMapCallback(), false);
+ }
+ }
+ return null;
+ }
+
+ public static PersistableBundle restoreFromXml(XmlPullParser in) throws IOException,
+ XmlPullParserException {
+ final int outerDepth = in.getDepth();
+ final String startTag = in.getName();
+ final String[] tagName = new String[1];
+ int event;
+ while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
+ (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
+ if (event == XmlPullParser.START_TAG) {
+ ArrayMap<String, ?> map =
+ XmlUtils.readThisArrayMapXml(in, startTag, tagName,
+ new MyReadMapCallback());
+ PersistableBundle result = new PersistableBundle();
+ for (Entry<String, ?> entry : map.entrySet()) {
+ Object value = entry.getValue();
+ if (value instanceof Integer) {
+ result.putInt(entry.getKey(), (int) value);
+ } else if (value instanceof Boolean) {
+ result.putBoolean(entry.getKey(), (boolean) value);
+ } else if (value instanceof String) {
+ result.putString(entry.getKey(), (String) value);
+ } else if (value instanceof String[]) {
+ result.putStringArray(entry.getKey(), (String[]) value);
+ } else if (value instanceof PersistableBundle) {
+ result.putPersistableBundle(entry.getKey(), (PersistableBundle) value);
+ }
+ }
+ return result;
+ }
+ }
+ return PersistableBundle.EMPTY;
+ }
+
+ static class MyReadMapCallback implements XmlUtils.ReadMapCallback {
+
+ @Override
+ public Object readThisUnknownObjectXml(XmlPullParser in, String tag)
+ throws XmlPullParserException, IOException {
+ if (TAG_PERSISTABLEMAP.equals(tag)) {
+ return restoreFromXml(in);
+ }
+ throw new XmlPullParserException("Unknown tag=" + tag);
+ }
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/VisualVoicemailPreferences.java b/src/com/android/phone/vvm/omtp/VisualVoicemailPreferences.java
new file mode 100644
index 0000000..be51ea9
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/VisualVoicemailPreferences.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+import android.telecom.PhoneAccountHandle;
+
+import com.android.phone.NeededForTesting;
+
+import java.util.Set;
+
+/**
+ * Save visual voicemail values in shared preferences to be retrieved later. Because a voicemail
+ * source is tied 1:1 to a phone account, the phone account handle is used in the key for each
+ * voicemail source and the associated data.
+ */
+public class VisualVoicemailPreferences {
+
+ private static final String VISUAL_VOICEMAIL_SHARED_PREFS_KEY_PREFIX =
+ "visual_voicemail_";
+
+ private final SharedPreferences mPreferences;
+ private final PhoneAccountHandle mPhoneAccountHandle;
+
+ public VisualVoicemailPreferences(Context context, PhoneAccountHandle phoneAccountHandle) {
+ mPreferences = PreferenceManager.getDefaultSharedPreferences(context);
+ mPhoneAccountHandle = phoneAccountHandle;
+ }
+
+ public class Editor {
+
+ private final SharedPreferences.Editor mEditor;
+
+ private Editor() {
+ mEditor = mPreferences.edit();
+ }
+
+ public void apply() {
+ mEditor.apply();
+ }
+
+ public Editor putBoolean(String key, boolean value) {
+ mEditor.putBoolean(getKey(key), value);
+ return this;
+ }
+
+ @NeededForTesting
+ public Editor putFloat(String key, float value) {
+ mEditor.putFloat(getKey(key), value);
+ return this;
+ }
+
+ public Editor putInt(String key, int value) {
+ mEditor.putInt(getKey(key), value);
+ return this;
+ }
+
+ @NeededForTesting
+ public Editor putLong(String key, long value) {
+ mEditor.putLong(getKey(key), value);
+ return this;
+ }
+
+ public Editor putString(String key, String value) {
+ mEditor.putString(getKey(key), value);
+ return this;
+ }
+
+ @NeededForTesting
+ public Editor putStringSet(String key, Set<String> value) {
+ mEditor.putStringSet(getKey(key), value);
+ return this;
+ }
+ }
+
+ public Editor edit() {
+ return new Editor();
+ }
+
+ public boolean getBoolean(String key, boolean defValue) {
+ return getValue(key, defValue);
+ }
+
+ @NeededForTesting
+ public float getFloat(String key, float defValue) {
+ return getValue(key, defValue);
+ }
+
+ public int getInt(String key, int defValue) {
+ return getValue(key, defValue);
+ }
+
+ @NeededForTesting
+ public long getLong(String key, long defValue) {
+ return getValue(key, defValue);
+ }
+
+ public String getString(String key, String defValue) {
+ return getValue(key, defValue);
+ }
+
+ @Nullable
+ public String getString(String key) {
+ return getValue(key, null);
+ }
+
+ @NeededForTesting
+ public Set<String> getStringSet(String key, Set<String> defValue) {
+ return getValue(key, defValue);
+ }
+
+ public boolean contains(String key) {
+ return mPreferences.contains(getKey(key));
+ }
+
+ private <T> T getValue(String key, T defValue) {
+ if (!contains(key)) {
+ return defValue;
+ }
+ Object object = mPreferences.getAll().get(getKey(key));
+ if (object == null) {
+ return defValue;
+ }
+ return (T) object;
+ }
+
+ private String getKey(String key) {
+ return VISUAL_VOICEMAIL_SHARED_PREFS_KEY_PREFIX + key + "_" + mPhoneAccountHandle.getId();
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java b/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java
new file mode 100644
index 0000000..9809c64
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import android.telephony.SubscriptionManager;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+
+/**
+ * Upon boot iterate through all callable phone account to activate visual voicemail. This happens
+ * after the device has been unlocked. {@link android.telephony.CarrierConfigManager#
+ * ACTION_CARRIER_CONFIG_CHANGED} can also trigger activation upon boot but it can happen before the
+ * device is unlocked and visual voicemail will not be activated.
+ *
+ * <p>TODO: An additional duplicated activation request will be sent as a result of this receiver,
+ * but similar issues is already covered in b/28730056 and a scheduling system should be used to
+ * resolve this.
+ */
+public class VvmBootCompletedReceiver extends BroadcastReceiver {
+
+ private static final String TAG = "VvmBootCompletedRcvr";
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ // Listens to android.intent.action.BOOT_COMPLETED
+ if (!intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
+ return;
+ }
+
+ VvmLog.v(TAG, "processing subId list");
+ for (PhoneAccountHandle handle : TelecomManager.from(context)
+ .getCallCapablePhoneAccounts()) {
+ int subId = PhoneAccountHandleConverter.toSubId(handle);
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ // getCallCapablePhoneAccounts() might return a PhoneAccountHandle with invalid
+ // subId if no SIM is inserted. This is intended as it is for emergency calls.
+ VvmLog.e(TAG, "phone account " + handle + " has invalid subId " + subId);
+ continue;
+ }
+ VvmLog.v(TAG, "processing subId " + subId);
+ SimChangeReceiver.processSubId(context, subId);
+ }
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/VvmLog.java b/src/com/android/phone/vvm/omtp/VvmLog.java
new file mode 100644
index 0000000..82d42af
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/VvmLog.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.phone.vvm.omtp;
+
+import android.util.LocalLog;
+import android.util.Log;
+
+import com.android.internal.util.IndentingPrintWriter;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Helper methods for adding to OMTP visual voicemail local logs.
+ */
+public class VvmLog {
+
+ private static final int MAX_OMTP_VVM_LOGS = 100;
+
+ private static final LocalLog sLocalLog = new LocalLog(MAX_OMTP_VVM_LOGS);
+
+ public static void log(String tag, String log) {
+ sLocalLog.log(tag + ": " + log);
+ }
+
+ public static void dump(FileDescriptor fd, PrintWriter printwriter, String[] args) {
+ IndentingPrintWriter indentingPrintWriter = new IndentingPrintWriter(printwriter, " ");
+ indentingPrintWriter.increaseIndent();
+ sLocalLog.dump(fd, indentingPrintWriter, args);
+ indentingPrintWriter.decreaseIndent();
+ }
+
+ public static int e(String tag, String log) {
+ log(tag, log);
+ return Log.e(tag, log);
+ }
+
+ public static int e(String tag, String log, Throwable e) {
+ log(tag, log + " " + e);
+ return Log.e(tag, log, e);
+ }
+
+ public static int w(String tag, String log) {
+ log(tag, log);
+ return Log.w(tag, log);
+ }
+
+ public static int w(String tag, String log, Throwable e) {
+ log(tag, log + " " + e);
+ return Log.w(tag, log, e);
+ }
+
+ public static int i(String tag, String log) {
+ log(tag, log);
+ return Log.i(tag, log);
+ }
+
+ public static int i(String tag, String log, Throwable e) {
+ log(tag, log + " " + e);
+ return Log.i(tag, log, e);
+ }
+
+ public static int d(String tag, String log) {
+ log(tag, log);
+ return Log.d(tag, log);
+ }
+
+ public static int d(String tag, String log, Throwable e) {
+ log(tag, log + " " + e);
+ return Log.d(tag, log, e);
+ }
+
+ public static int v(String tag, String log) {
+ log(tag, log);
+ return Log.v(tag, log);
+ }
+
+ public static int v(String tag, String log, Throwable e) {
+ log(tag, log + " " + e);
+ return Log.v(tag, log, e);
+ }
+
+ public static int wtf(String tag, String log) {
+ log(tag, log);
+ return Log.wtf(tag, log);
+ }
+
+ public static int wtf(String tag, String log, Throwable e) {
+ log(tag, log + " " + e);
+ return Log.wtf(tag, log, e);
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/VvmPackageInstallReceiver.java b/src/com/android/phone/vvm/omtp/VvmPackageInstallReceiver.java
index 4ec740e..7c20065 100644
--- a/src/com/android/phone/vvm/omtp/VvmPackageInstallReceiver.java
+++ b/src/com/android/phone/vvm/omtp/VvmPackageInstallReceiver.java
@@ -31,6 +31,9 @@
* enabled dialer vvm sources.
*/
public class VvmPackageInstallReceiver extends BroadcastReceiver {
+
+ private static final String TAG = "VvmPkgInstallReceiver";
+
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getData() == null) {
@@ -45,16 +48,21 @@
OmtpVvmSourceManager vvmSourceManager = OmtpVvmSourceManager.getInstance(context);
Set<PhoneAccountHandle> phoneAccounts = vvmSourceManager.getOmtpVvmSources();
for (PhoneAccountHandle phoneAccount : phoneAccounts) {
- if (VisualVoicemailSettingsUtil.isVisualVoicemailUserSet(context, phoneAccount)) {
+ if (VisualVoicemailSettingsUtil.isEnabledUserSet(context, phoneAccount)) {
// Skip the check if this voicemail source's setting is overridden by the user.
continue;
}
OmtpVvmCarrierConfigHelper carrierConfigHelper = new OmtpVvmCarrierConfigHelper(
context, PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccount));
- if (packageName.equals(carrierConfigHelper.getCarrierVvmPackageName())) {
- VisualVoicemailSettingsUtil.setVisualVoicemailEnabled(
- context, phoneAccount, false, false);
+ if (carrierConfigHelper.getCarrierVvmPackageNames() == null) {
+ continue;
+ }
+ if (carrierConfigHelper.getCarrierVvmPackageNames().contains(packageName)) {
+ // Force deactivate the client. The user can re-enable it in the settings.
+ // There are no need to update the settings for deactivation. At this point, if the
+ // default value is used it should be false because a carrier package is present.
+ VvmLog.i(TAG, "Carrier VVM package installed, disabling system VVM client");
OmtpVvmSourceManager.getInstance(context).removeSource(phoneAccount);
carrierConfigHelper.startDeactivation();
}
diff --git a/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java b/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
index 1b2e34e..7e2472b 100644
--- a/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
+++ b/src/com/android/phone/vvm/omtp/VvmPhoneStateListener.java
@@ -16,23 +16,24 @@
package com.android.phone.vvm.omtp;
import android.content.Context;
-import android.content.Intent;
-import android.provider.VoicemailContract;
import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
-import android.util.Log;
+import android.telephony.SubscriptionManager;
-import com.android.phone.PhoneGlobals;
import com.android.phone.PhoneUtils;
+import com.android.phone.VoicemailStatus;
import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
import com.android.phone.vvm.omtp.sync.OmtpVvmSyncService;
+import com.android.phone.vvm.omtp.sync.SyncTask;
import com.android.phone.vvm.omtp.sync.VoicemailStatusQueryHelper;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
/**
* Check if service is lost and indicate this in the voicemail status.
*/
public class VvmPhoneStateListener extends PhoneStateListener {
+
private static final String TAG = "VvmPhoneStateListener";
private PhoneAccountHandle mPhoneAccount;
@@ -47,6 +48,13 @@
@Override
public void onServiceStateChanged(ServiceState serviceState) {
+ int subId = PhoneAccountHandleConverter.toSubId(mPhoneAccount);
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ VvmLog.e(TAG, "onServiceStateChanged on phoneAccount " + mPhoneAccount
+ + " with invalid subId, ignoring");
+ return;
+ }
+
int state = serviceState.getState();
if (state == mPreviousState || (state != ServiceState.STATE_IN_SERVICE
&& mPreviousState != ServiceState.STATE_IN_SERVICE)) {
@@ -56,56 +64,42 @@
return;
}
+ OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(mContext, subId);
+
if (state == ServiceState.STATE_IN_SERVICE) {
VoicemailStatusQueryHelper voicemailStatusQueryHelper =
new VoicemailStatusQueryHelper(mContext);
if (voicemailStatusQueryHelper.isVoicemailSourceConfigured(mPhoneAccount)) {
if (!voicemailStatusQueryHelper.isNotificationsChannelActive(mPhoneAccount)) {
- Log.v(TAG, "Notifications channel is active for " + mPhoneAccount.getId());
- VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
- VoicemailContract.Status.CONFIGURATION_STATE_OK,
- VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
- VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
- PhoneGlobals.getInstance().clearMwiIndicator(
- PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount));
+ VvmLog
+ .v(TAG, "Notifications channel is active for " + subId);
+ helper.handleEvent(VoicemailStatus.edit(mContext, mPhoneAccount),
+ OmtpEvents.NOTIFICATION_IN_SERVICE);
}
}
if (OmtpVvmSourceManager.getInstance(mContext).isVvmSourceRegistered(mPhoneAccount)) {
- Log.v(TAG, "Signal returned: requesting resync for " + mPhoneAccount.getId());
- LocalLogHelper.log(TAG,
- "Signal returned: requesting resync for " + mPhoneAccount.getId());
+ VvmLog
+ .v(TAG, "Signal returned: requesting resync for " + subId);
// If the source is already registered, run a full sync in case something was missed
// while signal was down.
- Intent serviceIntent = OmtpVvmSyncService.getSyncIntent(
- mContext, OmtpVvmSyncService.SYNC_FULL_SYNC, mPhoneAccount,
- true /* firstAttempt */);
- mContext.startService(serviceIntent);
+ SyncTask.start(mContext, mPhoneAccount, OmtpVvmSyncService.SYNC_FULL_SYNC);
} else {
- Log.v(TAG, "Signal returned: reattempting activation for " + mPhoneAccount.getId());
- LocalLogHelper.log(TAG,
- "Signal returned: reattempting activation for " + mPhoneAccount.getId());
+ VvmLog.v(TAG,
+ "Signal returned: reattempting activation for " + subId);
// Otherwise initiate an activation because this means that an OMTP source was
// recognized but either the activation text was not successfully sent or a response
// was not received.
- OmtpVvmCarrierConfigHelper carrierConfigHelper = new OmtpVvmCarrierConfigHelper(
- mContext, PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount));
- carrierConfigHelper.startActivation();
+ helper.startActivation();
}
} else {
- Log.v(TAG, "Notifications channel is inactive for " + mPhoneAccount.getId());
- mContext.stopService(OmtpVvmSyncService.getSyncIntent(
- mContext, OmtpVvmSyncService.SYNC_FULL_SYNC, mPhoneAccount,
- true /* firstAttempt */));
+ VvmLog.v(TAG, "Notifications channel is inactive for " + subId);
if (!OmtpVvmSourceManager.getInstance(mContext).isVvmSourceRegistered(mPhoneAccount)) {
return;
}
-
- VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
- VoicemailContract.Status.CONFIGURATION_STATE_OK,
- VoicemailContract.Status.DATA_CHANNEL_STATE_NO_CONNECTION,
- VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION);
+ helper.handleEvent(VoicemailStatus.edit(mContext, mPhoneAccount),
+ OmtpEvents.NOTIFICATION_SERVICE_LOST);
}
mPreviousState = state;
}
diff --git a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
index da60ad1..9bda638 100644
--- a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
+++ b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
@@ -15,7 +15,9 @@
*/
package com.android.phone.vvm.omtp.fetch;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -29,14 +31,15 @@
import android.telecom.PhoneAccountHandle;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
-import android.util.Log;
-
+import com.android.internal.telephony.Phone;
import com.android.phone.PhoneUtils;
+import com.android.phone.VoicemailStatus;
import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
import com.android.phone.vvm.omtp.imap.ImapHelper;
+import com.android.phone.vvm.omtp.imap.ImapHelper.InitializingException;
import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
import com.android.phone.vvm.omtp.sync.VvmNetworkRequestCallback;
-
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -44,13 +47,15 @@
private static final String TAG = "FetchVoicemailReceiver";
- final static String[] PROJECTION = new String[] {
+ final static String[] PROJECTION = new String[]{
Voicemails.SOURCE_DATA, // 0
Voicemails.PHONE_ACCOUNT_ID, // 1
+ Voicemails.PHONE_ACCOUNT_COMPONENT_NAME, // 2
};
public static final int SOURCE_DATA = 0;
public static final int PHONE_ACCOUNT_ID = 1;
+ public static final int PHONE_ACCOUNT_COMPONENT_NAME = 2;
// Timeout used to call ConnectivityManager.requestNetwork
private static final int NETWORK_REQUEST_TIMEOUT_MILLIS = 60 * 1000;
@@ -71,23 +76,28 @@
@Override
public void onReceive(final Context context, Intent intent) {
if (VoicemailContract.ACTION_FETCH_VOICEMAIL.equals(intent.getAction())) {
+ VvmLog.i(TAG, "ACTION_FETCH_VOICEMAIL received");
mContext = context;
mContentResolver = context.getContentResolver();
mUri = intent.getData();
if (mUri == null) {
- Log.w(TAG, VoicemailContract.ACTION_FETCH_VOICEMAIL + " intent sent with no data");
+ VvmLog.w(TAG,
+ VoicemailContract.ACTION_FETCH_VOICEMAIL + " intent sent with no data");
return;
}
if (!context.getPackageName().equals(
mUri.getQueryParameter(VoicemailContract.PARAM_KEY_SOURCE_PACKAGE))) {
// Ignore if the fetch request is for a voicemail not from this package.
+ VvmLog.e(TAG,
+ "ACTION_FETCH_VOICEMAIL from foreign pacakge " + context.getPackageName());
return;
}
Cursor cursor = mContentResolver.query(mUri, PROJECTION, null, null, null);
if (cursor == null) {
+ VvmLog.i(TAG, "ACTION_FETCH_VOICEMAIL query returned null");
return;
}
try {
@@ -100,22 +110,29 @@
accountId = telephonyManager.getSimSerialNumber();
if (TextUtils.isEmpty(accountId)) {
- Log.e(TAG, "Account null and no default sim found.");
+ VvmLog.e(TAG, "Account null and no default sim found.");
return;
}
}
- mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(accountId);
+ mPhoneAccount = new PhoneAccountHandle(
+ ComponentName.unflattenFromString(
+ cursor.getString(PHONE_ACCOUNT_COMPONENT_NAME)),
+ cursor.getString(PHONE_ACCOUNT_ID));
if (!OmtpVvmSourceManager.getInstance(context)
.isVvmSourceRegistered(mPhoneAccount)) {
- Log.w(TAG, "Account not registered - cannot retrieve message.");
- return;
+ mPhoneAccount = getAccountFromMarshmallowAccount(context, mPhoneAccount);
+ if (mPhoneAccount == null) {
+ VvmLog.w(TAG, "Account not registered - cannot retrieve message.");
+ return;
+ }
+ VvmLog.i(TAG, "Fetching voicemail with Marshmallow PhoneAccountHandle");
}
int subId = PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount);
OmtpVvmCarrierConfigHelper carrierConfigHelper =
new OmtpVvmCarrierConfigHelper(context, subId);
-
+ VvmLog.i(TAG, "Requesting network to fetch voicemail");
mNetworkCallback = new fetchVoicemailNetworkRequestCallback(context,
mPhoneAccount);
mNetworkCallback.requestNetwork();
@@ -126,38 +143,64 @@
}
}
+ /**
+ * In ag/930496 the format of PhoneAccountHandle has changed between Marshmallow and Nougat.
+ * This method attempts to search the account from the old database in registered sources using
+ * the old format. There's a chance of M phone account collisions on multi-SIM devices, but
+ * visual voicemail is not supported on M multi-SIM.
+ */
+ @Nullable
+ private static PhoneAccountHandle getAccountFromMarshmallowAccount(Context context,
+ PhoneAccountHandle oldAccount) {
+ for (PhoneAccountHandle handle : OmtpVvmSourceManager.getInstance(context)
+ .getOmtpVvmSources()) {
+ Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(handle);
+ if (phone == null) {
+ continue;
+ }
+ // getIccSerialNumber() is used for ID before N, and getFullIccSerialNumber() after.
+ if (phone.getIccSerialNumber().equals(oldAccount.getId())) {
+ return handle;
+ }
+ }
+ return null;
+ }
+
private class fetchVoicemailNetworkRequestCallback extends VvmNetworkRequestCallback {
public fetchVoicemailNetworkRequestCallback(Context context,
PhoneAccountHandle phoneAccount) {
- super(context, phoneAccount);
+ super(context, phoneAccount, VoicemailStatus.edit(context, phoneAccount));
}
@Override
public void onAvailable(final Network network) {
super.onAvailable(network);
- fetchVoicemail(network);
+ fetchVoicemail(network, getVoicemailStatusEditor());
}
}
- private void fetchVoicemail(final Network network) {
+ private void fetchVoicemail(final Network network, final VoicemailStatus.Editor status) {
Executor executor = Executors.newCachedThreadPool();
executor.execute(new Runnable() {
@Override
public void run() {
try {
while (mRetryCount > 0) {
- ImapHelper imapHelper = new ImapHelper(mContext, mPhoneAccount, network);
- if (!imapHelper.isSuccessfullyInitialized()) {
- Log.w(TAG, "Can't retrieve Imap credentials.");
- return;
- }
-
- boolean success = imapHelper.fetchVoicemailPayload(
- new VoicemailFetchedCallback(mContext, mUri), mUid);
- if (!success && mRetryCount > 0) {
- mRetryCount--;
- } else {
+ VvmLog.i(TAG, "fetching voicemail, retry count=" + mRetryCount);
+ try (ImapHelper imapHelper = new ImapHelper(mContext, mPhoneAccount,
+ network, status)) {
+ boolean success = imapHelper.fetchVoicemailPayload(
+ new VoicemailFetchedCallback(mContext, mUri, mPhoneAccount),
+ mUid);
+ if (!success && mRetryCount > 0) {
+ VvmLog.i(TAG, "fetch voicemail failed, retrying");
+ mRetryCount--;
+ } else {
+ return;
+ }
+ } catch (InitializingException e) {
+ VvmLog.w(TAG, "Can't retrieve Imap credentials ", e);
return;
}
}
diff --git a/src/com/android/phone/vvm/omtp/fetch/VoicemailFetchedCallback.java b/src/com/android/phone/vvm/omtp/fetch/VoicemailFetchedCallback.java
index 3862d54..e70ba49 100644
--- a/src/com/android/phone/vvm/omtp/fetch/VoicemailFetchedCallback.java
+++ b/src/com/android/phone/vvm/omtp/fetch/VoicemailFetchedCallback.java
@@ -15,19 +15,20 @@
*/
package com.android.phone.vvm.omtp.fetch;
+import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.net.Uri;
import android.provider.VoicemailContract.Voicemails;
-import android.util.Log;
-
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import com.android.phone.R;
+import com.android.phone.vvm.omtp.VvmLog;
import com.android.phone.vvm.omtp.imap.VoicemailPayload;
-
-import libcore.io.IoUtils;
-
import java.io.IOException;
import java.io.OutputStream;
+import libcore.io.IoUtils;
/**
* Callback for when a voicemail payload is fetched. It copies the returned stream to the data
@@ -36,12 +37,17 @@
public class VoicemailFetchedCallback {
private static final String TAG = "VoicemailFetchedCallback";
- private ContentResolver mContentResolver;
- private Uri mUri;
+ private final Context mContext;
+ private final ContentResolver mContentResolver;
+ private final Uri mUri;
+ private final PhoneAccountHandle mPhoneAccountHandle;
- public VoicemailFetchedCallback(Context context, Uri uri) {
+ public VoicemailFetchedCallback(Context context, Uri uri,
+ PhoneAccountHandle phoneAccountHandle) {
+ mContext = context;
mContentResolver = context.getContentResolver();
mUri = uri;
+ mPhoneAccountHandle = phoneAccountHandle;
}
/**
@@ -50,8 +56,18 @@
*
* @param voicemailPayload The object containing the content data for the voicemail
*/
- public void setVoicemailContent(VoicemailPayload voicemailPayload) {
- Log.d(TAG, String.format("Writing new voicemail content: %s", mUri));
+ public void setVoicemailContent(@Nullable VoicemailPayload voicemailPayload) {
+ if (voicemailPayload == null) {
+ VvmLog.i(TAG, "Payload not found, message has unsupported format");
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.TRANSCRIPTION,
+ mContext.getString(R.string.vvm_unsupported_message_format,
+ TelecomManager.from(mContext).getVoiceMailNumber(mPhoneAccountHandle)));
+ updateVoicemail(values);
+ return;
+ }
+
+ VvmLog.d(TAG, String.format("Writing new voicemail content: %s", mUri));
OutputStream outputStream = null;
try {
@@ -61,7 +77,7 @@
outputStream.write(inputBytes);
}
} catch (IOException e) {
- Log.w(TAG, String.format("File not found for %s", mUri));
+ VvmLog.w(TAG, String.format("File not found for %s", mUri));
return;
} finally {
IoUtils.closeQuietly(outputStream);
@@ -71,9 +87,14 @@
ContentValues values = new ContentValues();
values.put(Voicemails.MIME_TYPE, voicemailPayload.getMimeType());
values.put(Voicemails.HAS_CONTENT, true);
+ updateVoicemail(values);
+ }
+
+ private void updateVoicemail(ContentValues values) {
int updatedCount = mContentResolver.update(mUri, values, null, null);
if (updatedCount != 1) {
- Log.e(TAG, "Updating voicemail should have updated 1 row, was: " + updatedCount);
+ VvmLog
+ .e(TAG, "Updating voicemail should have updated 1 row, was: " + updatedCount);
}
}
}
diff --git a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
index 2c10377..a03e421 100644
--- a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
+++ b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
@@ -16,21 +16,15 @@
package com.android.phone.vvm.omtp.imap;
import android.content.Context;
-import android.content.SharedPreferences;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
-import android.preference.PreferenceManager;
import android.provider.VoicemailContract;
-import android.provider.VoicemailContract.Status;
import android.telecom.PhoneAccountHandle;
import android.telecom.Voicemail;
-import android.telephony.TelephonyManager;
import android.util.Base64;
-import android.util.Log;
-
import com.android.phone.PhoneUtils;
-import com.android.phone.VoicemailUtils;
+import com.android.phone.VoicemailStatus;
import com.android.phone.common.mail.Address;
import com.android.phone.common.mail.Body;
import com.android.phone.common.mail.BodyPart;
@@ -41,30 +35,36 @@
import com.android.phone.common.mail.Multipart;
import com.android.phone.common.mail.TempDirectory;
import com.android.phone.common.mail.internet.MimeMessage;
+import com.android.phone.common.mail.store.ImapConnection;
import com.android.phone.common.mail.store.ImapFolder;
import com.android.phone.common.mail.store.ImapStore;
import com.android.phone.common.mail.store.imap.ImapConstants;
+import com.android.phone.common.mail.store.imap.ImapResponse;
import com.android.phone.common.mail.utils.LogUtils;
-import com.android.phone.settings.VisualVoicemailSettingsUtil;
import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.OmtpConstants.ChangePinResult;
+import com.android.phone.vvm.omtp.OmtpEvents;
import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VisualVoicemailPreferences;
+import com.android.phone.vvm.omtp.VvmLog;
import com.android.phone.vvm.omtp.fetch.VoicemailFetchedCallback;
import com.android.phone.vvm.omtp.sync.OmtpVvmSyncService.TranscriptionFetchedCallback;
-
-import libcore.io.IoUtils;
-
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
+import libcore.io.IoUtils;
/**
* A helper interface to abstract commands sent across IMAP interface for a given account.
*/
-public class ImapHelper {
- private final String TAG = "ImapHelper";
+public class ImapHelper implements Closeable {
+
+ private static final String TAG = "ImapHelper";
private ImapFolder mFolder;
private ImapStore mImapStore;
@@ -72,88 +72,111 @@
private final Context mContext;
private final PhoneAccountHandle mPhoneAccount;
private final Network mNetwork;
+ private final VoicemailStatus.Editor mStatus;
- SharedPreferences mPrefs;
+ VisualVoicemailPreferences mPrefs;
private static final String PREF_KEY_QUOTA_OCCUPIED = "quota_occupied_";
private static final String PREF_KEY_QUOTA_TOTAL = "quota_total_";
private int mQuotaOccupied;
private int mQuotaTotal;
- public ImapHelper(Context context, PhoneAccountHandle phoneAccount, Network network) {
+ private final OmtpVvmCarrierConfigHelper mConfig;
+
+ public class InitializingException extends Exception {
+
+ public InitializingException(String message) {
+ super(message);
+ }
+ }
+
+ public ImapHelper(Context context, PhoneAccountHandle phoneAccount, Network network,
+ VoicemailStatus.Editor status)
+ throws InitializingException {
+ this(context, new OmtpVvmCarrierConfigHelper(context,
+ PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccount)), phoneAccount, network, status);
+ }
+
+ public ImapHelper(Context context, OmtpVvmCarrierConfigHelper config,
+ PhoneAccountHandle phoneAccount, Network network, VoicemailStatus.Editor status)
+ throws InitializingException {
mContext = context;
mPhoneAccount = phoneAccount;
mNetwork = network;
+ mStatus = status;
+ mConfig = config;
+ mPrefs = new VisualVoicemailPreferences(context,
+ phoneAccount);
+
try {
TempDirectory.setTempDirectory(context);
- String username = VisualVoicemailSettingsUtil.getVisualVoicemailCredentials(context,
- OmtpConstants.IMAP_USER_NAME, phoneAccount);
- String password = VisualVoicemailSettingsUtil.getVisualVoicemailCredentials(context,
- OmtpConstants.IMAP_PASSWORD, phoneAccount);
- String serverName = VisualVoicemailSettingsUtil.getVisualVoicemailCredentials(context,
- OmtpConstants.SERVER_ADDRESS, phoneAccount);
+ String username = mPrefs.getString(OmtpConstants.IMAP_USER_NAME, null);
+ String password = mPrefs.getString(OmtpConstants.IMAP_PASSWORD, null);
+ String serverName = mPrefs.getString(OmtpConstants.SERVER_ADDRESS, null);
int port = Integer.parseInt(
- VisualVoicemailSettingsUtil.getVisualVoicemailCredentials(context,
- OmtpConstants.IMAP_PORT, phoneAccount));
+ mPrefs.getString(OmtpConstants.IMAP_PORT, null));
int auth = ImapStore.FLAG_NONE;
- OmtpVvmCarrierConfigHelper carrierConfigHelper = new OmtpVvmCarrierConfigHelper(context,
- PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccount));
- if (TelephonyManager.VVM_TYPE_CVVM.equals(carrierConfigHelper.getVvmType())) {
- // TODO: move these into the carrier config app
- port = 993;
+ int sslPort = mConfig.getSslPort();
+ if (sslPort != 0) {
+ port = sslPort;
auth = ImapStore.FLAG_SSL;
}
mImapStore = new ImapStore(
context, this, username, password, port, serverName, auth, network);
} catch (NumberFormatException e) {
- VoicemailUtils.setDataChannelState(
- mContext, mPhoneAccount, Status.DATA_CHANNEL_STATE_BAD_CONFIGURATION);
+ handleEvent(OmtpEvents.DATA_INVALID_PORT);
LogUtils.w(TAG, "Could not parse port number");
+ throw new InitializingException("cannot initialize ImapHelper:" + e.toString());
}
- mPrefs = PreferenceManager.getDefaultSharedPreferences(context);
- mQuotaOccupied = mPrefs.getInt(getSharedPrefsKey(PREF_KEY_QUOTA_OCCUPIED),
- VoicemailContract.Status.QUOTA_UNAVAILABLE);
- mQuotaTotal = mPrefs.getInt(getSharedPrefsKey(PREF_KEY_QUOTA_TOTAL),
- VoicemailContract.Status.QUOTA_UNAVAILABLE);
-
- Log.v(TAG, "Quota:" + mQuotaOccupied + "/" + mQuotaTotal);
+ mQuotaOccupied = mPrefs
+ .getInt(PREF_KEY_QUOTA_OCCUPIED, VoicemailContract.Status.QUOTA_UNAVAILABLE);
+ mQuotaTotal = mPrefs
+ .getInt(PREF_KEY_QUOTA_TOTAL, VoicemailContract.Status.QUOTA_UNAVAILABLE);
}
- /**
- * If mImapStore is null, this means that there was a missing or badly formatted port number,
- * which means there aren't sufficient credentials for login. If mImapStore is succcessfully
- * initialized, then ImapHelper is ready to go.
- */
- public boolean isSuccessfullyInitialized() {
- return mImapStore != null;
+ @Override
+ public void close() {
+ mImapStore.closeConnection();
}
- public boolean isRoaming(){
+ public boolean isRoaming() {
ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(
Context.CONNECTIVITY_SERVICE);
NetworkInfo info = connectivityManager.getNetworkInfo(mNetwork);
- if(info == null){
+ if (info == null) {
return false;
}
return info.isRoaming();
}
- /** The caller thread will block until the method returns. */
+ public OmtpVvmCarrierConfigHelper getConfig() {
+ return mConfig;
+ }
+
+ public ImapConnection connect() {
+ return mImapStore.getConnection();
+ }
+
+ /**
+ * The caller thread will block until the method returns.
+ */
public boolean markMessagesAsRead(List<Voicemail> voicemails) {
return setFlags(voicemails, Flag.SEEN);
}
- /** The caller thread will block until the method returns. */
+ /**
+ * The caller thread will block until the method returns.
+ */
public boolean markMessagesAsDeleted(List<Voicemail> voicemails) {
return setFlags(voicemails, Flag.DELETED);
}
- public void setDataChannelState(int dataChannelState) {
- VoicemailUtils.setDataChannelState(mContext, mPhoneAccount, dataChannelState);
+ public void handleEvent(OmtpEvents event) {
+ mConfig.handleEvent(mStatus, event);
}
/**
@@ -221,7 +244,7 @@
* transcription exists.
*/
private Voicemail getVoicemailFromMessageStructure(
- MessageStructureWrapper messageStructureWrapper) throws MessagingException{
+ MessageStructureWrapper messageStructureWrapper) throws MessagingException {
Message messageDetails = messageStructureWrapper.messageStructure;
TranscriptionFetchedListener listener = new TranscriptionFetchedListener();
@@ -229,7 +252,7 @@
FetchProfile fetchProfile = new FetchProfile();
fetchProfile.add(messageStructureWrapper.transcriptionBodyPart);
- mFolder.fetch(new Message[] {messageDetails}, fetchProfile, listener);
+ mFolder.fetch(new Message[]{messageDetails}, fetchProfile, listener);
}
// Found an audio attachment, this is a valid voicemail.
@@ -246,8 +269,8 @@
}
/**
- * The "from" field of a visual voicemail IMAP message is the number of the caller who left
- * the message. Extract this number from the list of "from" addresses.
+ * The "from" field of a visual voicemail IMAP message is the number of the caller who left the
+ * message. Extract this number from the list of "from" addresses.
*
* @param fromAddresses A list of addresses that comprise the "from" line.
* @return The number of the voicemail sender.
@@ -286,7 +309,7 @@
// The IMAP folder fetch method will call "messageRetrieved" on the listener when the
// message is successfully retrieved.
- mFolder.fetch(new Message[] {message}, fetchProfile, listener);
+ mFolder.fetch(new Message[]{message}, fetchProfile, listener);
return listener.getMessageStructure();
}
@@ -302,11 +325,6 @@
return false;
}
VoicemailPayload voicemailPayload = fetchVoicemailPayload(message);
-
- if (voicemailPayload == null) {
- return false;
- }
-
callback.setVoicemailContent(voicemailPayload);
return true;
} catch (MessagingException e) {
@@ -330,7 +348,7 @@
FetchProfile fetchProfile = new FetchProfile();
fetchProfile.add(FetchProfile.Item.BODY);
- mFolder.fetch(new Message[] {message}, fetchProfile, listener);
+ mFolder.fetch(new Message[]{message}, fetchProfile, listener);
return listener.getVoicemailPayload();
}
@@ -356,7 +374,7 @@
// This method is called synchronously so the transcription will be populated
// in the listener once the next method is called.
- mFolder.fetch(new Message[] {message}, fetchProfile, listener);
+ mFolder.fetch(new Message[]{message}, fetchProfile, listener);
callback.setVoicemailTranscription(listener.getVoicemailTranscription());
}
}
@@ -369,6 +387,84 @@
}
}
+
+ @ChangePinResult
+ public int changePin(String oldPin, String newPin)
+ throws MessagingException {
+ ImapConnection connection = mImapStore.getConnection();
+ try {
+ String command = getConfig().getProtocol()
+ .getCommand(OmtpConstants.IMAP_CHANGE_TUI_PWD_FORMAT);
+ connection.sendCommand(
+ String.format(Locale.US, command, newPin, oldPin), true);
+ return getChangePinResultFromImapResponse(connection.readResponse());
+ } catch (IOException ioe) {
+ VvmLog.e(TAG, "changePin: ", ioe);
+ return OmtpConstants.CHANGE_PIN_SYSTEM_ERROR;
+ } finally {
+ connection.destroyResponses();
+ }
+ }
+
+ public void changeVoicemailTuiLanguage(String languageCode)
+ throws MessagingException {
+ ImapConnection connection = mImapStore.getConnection();
+ try {
+ String command = getConfig().getProtocol()
+ .getCommand(OmtpConstants.IMAP_CHANGE_VM_LANG_FORMAT);
+ connection.sendCommand(
+ String.format(Locale.US, command, languageCode), true);
+ } catch (IOException ioe) {
+ LogUtils.e(TAG, ioe.toString());
+ } finally {
+ connection.destroyResponses();
+ }
+ }
+
+ public void closeNewUserTutorial() throws MessagingException {
+ ImapConnection connection = mImapStore.getConnection();
+ try {
+ String command = getConfig().getProtocol()
+ .getCommand(OmtpConstants.IMAP_CLOSE_NUT);
+ connection.executeSimpleCommand(command, false);
+ } catch (IOException ioe) {
+ throw new MessagingException(MessagingException.SERVER_ERROR, ioe.toString());
+ } finally {
+ connection.destroyResponses();
+ }
+ }
+
+ @ChangePinResult
+ private static int getChangePinResultFromImapResponse(ImapResponse response)
+ throws MessagingException {
+ if (!response.isTagged()) {
+ throw new MessagingException(MessagingException.SERVER_ERROR,
+ "tagged response expected");
+ }
+ if (!response.isOk()) {
+ String message = response.getStringOrEmpty(1).getString();
+ LogUtils.d(TAG, "change PIN failed: " + message);
+ if (OmtpConstants.RESPONSE_CHANGE_PIN_TOO_SHORT.equals(message)) {
+ return OmtpConstants.CHANGE_PIN_TOO_SHORT;
+ }
+ if (OmtpConstants.RESPONSE_CHANGE_PIN_TOO_LONG.equals(message)) {
+ return OmtpConstants.CHANGE_PIN_TOO_LONG;
+ }
+ if (OmtpConstants.RESPONSE_CHANGE_PIN_TOO_WEAK.equals(message)) {
+ return OmtpConstants.CHANGE_PIN_TOO_WEAK;
+ }
+ if (OmtpConstants.RESPONSE_CHANGE_PIN_MISMATCH.equals(message)) {
+ return OmtpConstants.CHANGE_PIN_MISMATCH;
+ }
+ if (OmtpConstants.RESPONSE_CHANGE_PIN_INVALID_CHARACTER.equals(message)) {
+ return OmtpConstants.CHANGE_PIN_INVALID_CHARACTER;
+ }
+ return OmtpConstants.CHANGE_PIN_SYSTEM_ERROR;
+ }
+ LogUtils.d(TAG, "change PIN succeeded");
+ return OmtpConstants.CHANGE_PIN_SUCCESS;
+ }
+
public void updateQuota() {
try {
mFolder = openImapFolder(ImapFolder.MODE_READ_WRITE);
@@ -393,28 +489,32 @@
return;
}
if (quota.occupied == mQuotaOccupied && quota.total == mQuotaTotal) {
- Log.v(TAG, "Quota hasn't changed");
+ VvmLog.v(TAG, "Quota hasn't changed");
return;
}
mQuotaOccupied = quota.occupied;
mQuotaTotal = quota.total;
- VoicemailContract.Status
- .setQuota(mContext, mPhoneAccount, mQuotaOccupied, mQuotaTotal);
- mPrefs.edit()
- .putInt(getSharedPrefsKey(PREF_KEY_QUOTA_OCCUPIED), mQuotaOccupied)
- .putInt(getSharedPrefsKey(PREF_KEY_QUOTA_TOTAL), mQuotaTotal)
+ VoicemailStatus.edit(mContext, mPhoneAccount)
+ .setQuota(mQuotaOccupied, mQuotaTotal)
.apply();
- Log.v(TAG, "Quota changed to " + mQuotaOccupied + "/" + mQuotaTotal);
+ mPrefs.edit()
+ .putInt(PREF_KEY_QUOTA_OCCUPIED, mQuotaOccupied)
+ .putInt(PREF_KEY_QUOTA_TOTAL, mQuotaTotal)
+ .apply();
+ VvmLog.v(TAG, "Quota changed to " + mQuotaOccupied + "/" + mQuotaTotal);
}
+
/**
- * A wrapper to hold a message with its header details and the structure for transcriptions
- * (so they can be fetched in the future).
+ * A wrapper to hold a message with its header details and the structure for transcriptions (so
+ * they can be fetched in the future).
*/
public class MessageStructureWrapper {
+
public Message messageStructure;
public BodyPart transcriptionBodyPart;
- public MessageStructureWrapper() { }
+ public MessageStructureWrapper() {
+ }
}
/**
@@ -422,6 +522,7 @@
*/
private final class MessageStructureFetchedListener
implements ImapFolder.MessageRetrievalListener {
+
private MessageStructureWrapper mMessageStructure;
public MessageStructureFetchedListener() {
@@ -453,7 +554,6 @@
* @param message The IMAP message.
* @return The MessageStructureWrapper object corresponding to an IMAP message and
* transcription.
- * @throws MessagingException
*/
private MessageStructureWrapper getMessageOrNull(Message message)
throws MessagingException {
@@ -474,6 +574,8 @@
messageStructureWrapper.messageStructure = message;
} else if (bodyPartMimeType.startsWith("text/")) {
messageStructureWrapper.transcriptionBodyPart = bodyPart;
+ } else {
+ VvmLog.v(TAG, "Unknown bodyPart MIME: " + bodyPartMimeType);
}
}
@@ -490,9 +592,12 @@
* Listener for the message body being fetched.
*/
private final class MessageBodyFetchedListener implements ImapFolder.MessageRetrievalListener {
+
private VoicemailPayload mVoicemailPayload;
- /** Returns the fetch voicemail payload. */
+ /**
+ * Returns the fetch voicemail payload.
+ */
public VoicemailPayload getVoicemailPayload() {
return mVoicemailPayload;
}
@@ -513,18 +618,18 @@
private VoicemailPayload getVoicemailPayloadFromMessage(Message message)
throws MessagingException, IOException {
Multipart multipart = (Multipart) message.getBody();
+ List<String> mimeTypes = new ArrayList<>();
for (int i = 0; i < multipart.getCount(); ++i) {
BodyPart bodyPart = multipart.getBodyPart(i);
String bodyPartMimeType = bodyPart.getMimeType().toLowerCase();
- LogUtils.d(TAG, "bodyPart mime type: " + bodyPartMimeType);
-
+ mimeTypes.add(bodyPartMimeType);
if (bodyPartMimeType.startsWith("audio/")) {
byte[] bytes = getDataFromBody(bodyPart.getBody());
LogUtils.d(TAG, String.format("Fetched %s bytes of data", bytes.length));
return new VoicemailPayload(bodyPartMimeType, bytes);
}
}
- LogUtils.e(TAG, "No audio attachment found on this voicemail");
+ LogUtils.e(TAG, "No audio attachment found on this voicemail, mimeTypes:" + mimeTypes);
return null;
}
}
@@ -534,9 +639,12 @@
*/
private final class TranscriptionFetchedListener implements
ImapFolder.MessageRetrievalListener {
+
private String mVoicemailTranscription;
- /** Returns the fetched voicemail transcription. */
+ /**
+ * Returns the fetched voicemail transcription.
+ */
public String getVoicemailTranscription() {
return mVoicemailTranscription;
}
@@ -594,8 +702,4 @@
IoUtils.closeQuietly(out);
}
}
-
- private String getSharedPrefsKey(String key) {
- return VisualVoicemailSettingsUtil.getVisualVoicemailSharedPrefsKey(key, mPhoneAccount);
- }
}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/protocol/CvvmProtocol.java b/src/com/android/phone/vvm/omtp/protocol/CvvmProtocol.java
new file mode 100644
index 0000000..9960b18
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/protocol/CvvmProtocol.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.protocol;
+
+import android.telephony.SmsManager;
+
+import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.sms.OmtpCvvmMessageSender;
+import com.android.phone.vvm.omtp.sms.OmtpMessageSender;
+
+/**
+ * A flavor of OMTP protocol with a different mobile originated (MO) format
+ *
+ * Used by carriers such as T-Mobile
+ */
+public class CvvmProtocol extends VisualVoicemailProtocol {
+
+ private static String IMAP_CHANGE_TUI_PWD_FORMAT = "CHANGE_TUI_PWD PWD=%1$s OLD_PWD=%2$s";
+ private static String IMAP_CHANGE_VM_LANG_FORMAT = "CHANGE_VM_LANG Lang=%1$s";
+ private static String IMAP_CLOSE_NUT = "CLOSE_NUT";
+
+ @Override
+ public OmtpMessageSender createMessageSender(SmsManager smsManager, short applicationPort,
+ String destinationNumber) {
+ return new OmtpCvvmMessageSender(smsManager, applicationPort, destinationNumber);
+ }
+
+ @Override
+ public String getCommand(String command) {
+ if (command == OmtpConstants.IMAP_CHANGE_TUI_PWD_FORMAT) {
+ return IMAP_CHANGE_TUI_PWD_FORMAT;
+ }
+ if (command == OmtpConstants.IMAP_CLOSE_NUT) {
+ return IMAP_CLOSE_NUT;
+ }
+ if (command == OmtpConstants.IMAP_CHANGE_VM_LANG_FORMAT) {
+ return IMAP_CHANGE_VM_LANG_FORMAT;
+ }
+ return super.getCommand(command);
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/protocol/OmtpProtocol.java b/src/com/android/phone/vvm/omtp/protocol/OmtpProtocol.java
new file mode 100644
index 0000000..d002652
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/protocol/OmtpProtocol.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.protocol;
+
+import android.telephony.SmsManager;
+
+import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.sms.OmtpMessageSender;
+import com.android.phone.vvm.omtp.sms.OmtpStandardMessageSender;
+
+public class OmtpProtocol extends VisualVoicemailProtocol {
+
+ @Override
+ public OmtpMessageSender createMessageSender(SmsManager smsManager, short applicationPort,
+ String destinationNumber) {
+ return new OmtpStandardMessageSender(smsManager, applicationPort, destinationNumber,
+ null, OmtpConstants.PROTOCOL_VERSION1_1, null);
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/protocol/ProtocolHelper.java b/src/com/android/phone/vvm/omtp/protocol/ProtocolHelper.java
new file mode 100644
index 0000000..748fd39
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/protocol/ProtocolHelper.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.protocol;
+
+import android.telephony.SmsManager;
+import android.text.TextUtils;
+
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.sms.OmtpMessageSender;
+
+public class ProtocolHelper {
+
+ private static final String TAG = "ProtocolHelper";
+
+ public static OmtpMessageSender getMessageSender(VisualVoicemailProtocol protocol,
+ OmtpVvmCarrierConfigHelper config) {
+
+ int applicationPort = config.getApplicationPort();
+ String destinationNumber = config.getDestinationNumber();
+ if (TextUtils.isEmpty(destinationNumber)) {
+ VvmLog.w(TAG, "No destination number for this carrier.");
+ return null;
+ }
+
+ SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(config.getSubId());
+ return protocol.createMessageSender(smsManager, (short) applicationPort, destinationNumber);
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/protocol/VisualVoicemailProtocol.java b/src/com/android/phone/vvm/omtp/protocol/VisualVoicemailProtocol.java
new file mode 100644
index 0000000..6e6d6ef
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/protocol/VisualVoicemailProtocol.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.protocol;
+
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.os.Bundle;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.SmsManager;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.ActivationTask;
+import com.android.phone.vvm.omtp.DefaultOmtpEventHandler;
+import com.android.phone.vvm.omtp.OmtpEvents;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.sms.OmtpMessageSender;
+import com.android.phone.vvm.omtp.sms.StatusMessage;
+
+public abstract class VisualVoicemailProtocol {
+
+ /**
+ * Activation should cause the carrier to respond with a STATUS SMS.
+ */
+ public void startActivation(OmtpVvmCarrierConfigHelper config, PendingIntent sentIntent) {
+ OmtpMessageSender messageSender = ProtocolHelper.getMessageSender(this, config);
+ if (messageSender != null) {
+ messageSender.requestVvmActivation(sentIntent);
+ }
+ }
+
+ public void startDeactivation(OmtpVvmCarrierConfigHelper config) {
+ OmtpMessageSender messageSender = ProtocolHelper.getMessageSender(this, config);
+ if (messageSender != null) {
+ messageSender.requestVvmDeactivation(null);
+ }
+ }
+
+ public boolean supportsProvisioning() {
+ return false;
+ }
+
+ public void startProvisioning(ActivationTask task, PhoneAccountHandle handle,
+ OmtpVvmCarrierConfigHelper config, VoicemailStatus.Editor editor, StatusMessage message,
+ Bundle data) {
+ // Do nothing
+ }
+
+ public void requestStatus(OmtpVvmCarrierConfigHelper config,
+ @Nullable PendingIntent sentIntent) {
+ OmtpMessageSender messageSender = ProtocolHelper.getMessageSender(this, config);
+ if (messageSender != null) {
+ messageSender.requestVvmStatus(sentIntent);
+ }
+ }
+
+ public abstract OmtpMessageSender createMessageSender(SmsManager smsManager,
+ short applicationPort, String destinationNumber);
+
+ /**
+ * Translate an OMTP IMAP command to the protocol specific one. For example, changing the TUI
+ * password on OMTP is XCHANGE_TUI_PWD, but on CVVM and VVM3 it is CHANGE_TUI_PWD.
+ *
+ * @param command A String command in {@link com.android.phone.vvm.omtp.OmtpConstants}, the exact
+ * instance should be used instead of its' value.
+ * @returns Translated command, or {@code null} if not available in this protocol
+ */
+ public String getCommand(String command) {
+ return command;
+ }
+
+ public void handleEvent(Context context, OmtpVvmCarrierConfigHelper config,
+ VoicemailStatus.Editor status, OmtpEvents event) {
+ DefaultOmtpEventHandler.handleEvent(context, config, status, event);
+ }
+
+ /**
+ * Given an VVM SMS with an unknown {@code event}, let the protocol attempt to translate it into
+ * an equivalent STATUS SMS. Returns {@code null} if it cannot be translated.
+ */
+ @Nullable
+ public Bundle translateStatusSmsBundle(OmtpVvmCarrierConfigHelper config, String event,
+ Bundle data) {
+ return null;
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/protocol/VisualVoicemailProtocolFactory.java b/src/com/android/phone/vvm/omtp/protocol/VisualVoicemailProtocolFactory.java
new file mode 100644
index 0000000..4d39ae2
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/protocol/VisualVoicemailProtocolFactory.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.protocol;
+
+import android.annotation.Nullable;
+import android.content.res.Resources;
+import android.telephony.TelephonyManager;
+
+import com.android.phone.R;
+import com.android.phone.vvm.omtp.VvmLog;
+
+public class VisualVoicemailProtocolFactory {
+
+ private static final String TAG = "VvmProtocolFactory";
+
+ private static final String VVM_TYPE_VVM3 = "vvm_type_vvm3";
+
+ @Nullable
+ public static VisualVoicemailProtocol create(Resources resources, String type) {
+ if (type == null) {
+ return null;
+ }
+ switch (type) {
+ case TelephonyManager.VVM_TYPE_OMTP:
+ return new OmtpProtocol();
+ case TelephonyManager.VVM_TYPE_CVVM:
+ return new CvvmProtocol();
+ case VVM_TYPE_VVM3:
+ if (resources.getBoolean(R.bool.vvm3_enabled)) {
+ return new Vvm3Protocol();
+ } else {
+ VvmLog.e(TAG, "VVM3 is disabled");
+ return null;
+ }
+ default:
+ VvmLog.e(TAG, "Unexpected visual voicemail type: " + type);
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/protocol/Vvm3EventHandler.java b/src/com/android/phone/vvm/omtp/protocol/Vvm3EventHandler.java
new file mode 100644
index 0000000..d95879f
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/protocol/Vvm3EventHandler.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.protocol;
+
+import android.annotation.IntDef;
+import android.content.Context;
+import android.util.Log;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.settings.VoicemailChangePinActivity;
+import com.android.phone.vvm.omtp.DefaultOmtpEventHandler;
+import com.android.phone.vvm.omtp.OmtpEvents;
+import com.android.phone.vvm.omtp.OmtpEvents.Type;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Handles {@link OmtpEvents} when {@link Vvm3Protocol} is being used. This handler writes custom
+ * error codes into the voicemail status table so support on the dialer side is required.
+ *
+ * TODO(b/29577838) disable VVM3 by default so support on system dialer can be ensured.
+ */
+public class Vvm3EventHandler {
+
+ private static final String TAG = "Vvm3EventHandler";
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({VMS_DNS_FAILURE, VMG_DNS_FAILURE, SPG_DNS_FAILURE, VMS_NO_CELLULAR, VMG_NO_CELLULAR,
+ SPG_NO_CELLULAR, VMS_TIMEOUT, VMG_TIMEOUT, STATUS_SMS_TIMEOUT, SUBSCRIBER_BLOCKED,
+ UNKNOWN_USER, UNKNOWN_DEVICE, INVALID_PASSWORD, MAILBOX_NOT_INITIALIZED,
+ SERVICE_NOT_PROVISIONED, SERVICE_NOT_ACTIVATED, USER_BLOCKED, IMAP_GETQUOTA_ERROR,
+ IMAP_SELECT_ERROR, IMAP_ERROR, VMG_INTERNAL_ERROR, VMG_DB_ERROR,
+ VMG_COMMUNICATION_ERROR, SPG_URL_NOT_FOUND, VMG_UNKNOWN_ERROR, PIN_NOT_SET})
+ public @interface ErrorCode {
+
+ }
+
+ public static final int VMS_DNS_FAILURE = -9001;
+ public static final int VMG_DNS_FAILURE = -9002;
+ public static final int SPG_DNS_FAILURE = -9003;
+ public static final int VMS_NO_CELLULAR = -9004;
+ public static final int VMG_NO_CELLULAR = -9005;
+ public static final int SPG_NO_CELLULAR = -9006;
+ public static final int VMS_TIMEOUT = -9007;
+ public static final int VMG_TIMEOUT = -9008;
+ public static final int STATUS_SMS_TIMEOUT = -9009;
+
+ public static final int SUBSCRIBER_BLOCKED = -9990;
+ public static final int UNKNOWN_USER = -9991;
+ public static final int UNKNOWN_DEVICE = -9992;
+ public static final int INVALID_PASSWORD = -9993;
+ public static final int MAILBOX_NOT_INITIALIZED = -9994;
+ public static final int SERVICE_NOT_PROVISIONED = -9995;
+ public static final int SERVICE_NOT_ACTIVATED = -9996;
+ public static final int USER_BLOCKED = -9998;
+ public static final int IMAP_GETQUOTA_ERROR = -9997;
+ public static final int IMAP_SELECT_ERROR = -9989;
+ public static final int IMAP_ERROR = -9999;
+
+ public static final int VMG_INTERNAL_ERROR = -101;
+ public static final int VMG_DB_ERROR = -102;
+ public static final int VMG_COMMUNICATION_ERROR = -103;
+ public static final int SPG_URL_NOT_FOUND = -301;
+
+ // Non VVM3 codes:
+ public static final int VMG_UNKNOWN_ERROR = -1;
+ public static final int PIN_NOT_SET = -100;
+ // STATUS SMS returned st=U and rc!=2. The user cannot be provisioned and must contact customer
+ // support.
+ public static final int SUBSCRIBER_UNKNOWN = -99;
+
+
+ public static void handleEvent(Context context, OmtpVvmCarrierConfigHelper config,
+ VoicemailStatus.Editor status, OmtpEvents event) {
+ boolean handled = false;
+ switch (event.getType()) {
+ case Type.CONFIGURATION:
+ handled = handleConfigurationEvent(context, status, event);
+ break;
+ case Type.DATA_CHANNEL:
+ handled = handleDataChannelEvent(status, event);
+ break;
+ case Type.NOTIFICATION_CHANNEL:
+ handled = handleNotificationChannelEvent(status, event);
+ break;
+ case Type.OTHER:
+ handled = handleOtherEvent(status, event);
+ break;
+ default:
+ com.android.services.telephony.Log
+ .wtf(TAG, "invalid event type " + event.getType() + " for " + event);
+ }
+ if (!handled) {
+ DefaultOmtpEventHandler.handleEvent(context, config, status, event);
+ }
+ }
+
+ private static boolean handleConfigurationEvent(Context context, VoicemailStatus.Editor status,
+ OmtpEvents event) {
+ switch (event) {
+ case CONFIG_REQUEST_STATUS_SUCCESS:
+ if (status.getPhoneAccountHandle() == null) {
+ // This should never happen.
+ Log.e(TAG, "status editor has null phone account handle");
+ return true;
+ }
+
+ if (!VoicemailChangePinActivity
+ .isDefaultOldPinSet(context, status.getPhoneAccountHandle())) {
+ return false;
+ } else {
+ postError(status, PIN_NOT_SET);
+ }
+ break;
+ case CONFIG_DEFAULT_PIN_REPLACED:
+ postError(status, PIN_NOT_SET);
+ break;
+ case CONFIG_STATUS_SMS_TIME_OUT:
+ postError(status, STATUS_SMS_TIMEOUT);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean handleDataChannelEvent(VoicemailStatus.Editor status, OmtpEvents event) {
+ switch (event) {
+ case DATA_NO_CONNECTION:
+ case DATA_NO_CONNECTION_CELLULAR_REQUIRED:
+ case DATA_ALL_SOCKET_CONNECTION_FAILED:
+ postError(status, VMS_NO_CELLULAR);
+ break;
+ case DATA_SSL_INVALID_HOST_NAME:
+ case DATA_CANNOT_ESTABLISH_SSL_SESSION:
+ case DATA_IOE_ON_OPEN:
+ postError(status, VMS_TIMEOUT);
+ break;
+ case DATA_CANNOT_RESOLVE_HOST_ON_NETWORK:
+ postError(status, VMS_DNS_FAILURE);
+ break;
+ case DATA_BAD_IMAP_CREDENTIAL:
+ postError(status, IMAP_ERROR);
+ break;
+ case DATA_AUTH_UNKNOWN_USER:
+ postError(status, UNKNOWN_USER);
+ break;
+ case DATA_AUTH_UNKNOWN_DEVICE:
+ postError(status, UNKNOWN_DEVICE);
+ break;
+ case DATA_AUTH_INVALID_PASSWORD:
+ postError(status, INVALID_PASSWORD);
+ break;
+ case DATA_AUTH_MAILBOX_NOT_INITIALIZED:
+ postError(status, MAILBOX_NOT_INITIALIZED);
+ break;
+ case DATA_AUTH_SERVICE_NOT_PROVISIONED:
+ postError(status, SERVICE_NOT_PROVISIONED);
+ break;
+ case DATA_AUTH_SERVICE_NOT_ACTIVATED:
+ postError(status, SERVICE_NOT_ACTIVATED);
+ break;
+ case DATA_AUTH_USER_IS_BLOCKED:
+ postError(status, USER_BLOCKED);
+ break;
+ case DATA_REJECTED_SERVER_RESPONSE:
+ case DATA_INVALID_INITIAL_SERVER_RESPONSE:
+ case DATA_SSL_EXCEPTION:
+ postError(status, IMAP_ERROR);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ private static boolean handleNotificationChannelEvent(VoicemailStatus.Editor status,
+ OmtpEvents event) {
+ return false;
+ }
+
+ private static boolean handleOtherEvent(VoicemailStatus.Editor status,
+ OmtpEvents event) {
+ switch (event) {
+ case VVM3_NEW_USER_SETUP_FAILED:
+ postError(status, MAILBOX_NOT_INITIALIZED);
+ break;
+ case VVM3_VMG_DNS_FAILURE:
+ postError(status, VMG_DNS_FAILURE);
+ break;
+ case VVM3_SPG_DNS_FAILURE:
+ postError(status, SPG_DNS_FAILURE);
+ break;
+ case VVM3_VMG_CONNECTION_FAILED:
+ postError(status, VMG_NO_CELLULAR);
+ break;
+ case VVM3_SPG_CONNECTION_FAILED:
+ postError(status, SPG_NO_CELLULAR);
+ break;
+ case VVM3_VMG_TIMEOUT:
+ postError(status, VMG_TIMEOUT);
+ break;
+ case VVM3_SUBSCRIBER_PROVISIONED:
+ postError(status, SERVICE_NOT_ACTIVATED);
+ break;
+ case VVM3_SUBSCRIBER_BLOCKED:
+ postError(status, SUBSCRIBER_BLOCKED);
+ break;
+ case VVM3_SUBSCRIBER_UNKNOWN:
+ postError(status, SUBSCRIBER_UNKNOWN);
+ break;
+ default:
+ return false;
+ }
+ return true;
+ }
+
+ private static void postError(VoicemailStatus.Editor editor, @ErrorCode int errorCode) {
+ switch (errorCode) {
+ case VMG_DNS_FAILURE:
+ case SPG_DNS_FAILURE:
+ case VMG_NO_CELLULAR:
+ case SPG_NO_CELLULAR:
+ case VMG_TIMEOUT:
+ case SUBSCRIBER_BLOCKED:
+ case UNKNOWN_USER:
+ case UNKNOWN_DEVICE:
+ case INVALID_PASSWORD:
+ case MAILBOX_NOT_INITIALIZED:
+ case SERVICE_NOT_PROVISIONED:
+ case SERVICE_NOT_ACTIVATED:
+ case USER_BLOCKED:
+ case VMG_UNKNOWN_ERROR:
+ case SPG_URL_NOT_FOUND:
+ case VMG_INTERNAL_ERROR:
+ case VMG_DB_ERROR:
+ case VMG_COMMUNICATION_ERROR:
+ case PIN_NOT_SET:
+ case SUBSCRIBER_UNKNOWN:
+ editor.setConfigurationState(errorCode);
+ break;
+ case VMS_NO_CELLULAR:
+ case VMS_DNS_FAILURE:
+ case VMS_TIMEOUT:
+ case IMAP_GETQUOTA_ERROR:
+ case IMAP_SELECT_ERROR:
+ case IMAP_ERROR:
+ editor.setDataChannelState(errorCode);
+ break;
+ case STATUS_SMS_TIMEOUT:
+ editor.setNotificationChannelState(errorCode);
+ break;
+ default:
+ Log.wtf(TAG, "unknown error code: " + errorCode);
+ }
+ editor.apply();
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java b/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java
new file mode 100644
index 0000000..93e8fb9
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.protocol;
+
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.net.Network;
+import android.os.Bundle;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.SmsManager;
+import android.text.TextUtils;
+
+import com.android.phone.PhoneGlobals;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.common.mail.MessagingException;
+import com.android.phone.settings.VisualVoicemailSettingsUtil;
+import com.android.phone.settings.VoicemailChangePinActivity;
+import com.android.phone.vvm.omtp.ActivationTask;
+import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.OmtpEvents;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VisualVoicemailPreferences;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.imap.ImapHelper;
+import com.android.phone.vvm.omtp.imap.ImapHelper.InitializingException;
+import com.android.phone.vvm.omtp.sms.OmtpMessageSender;
+import com.android.phone.vvm.omtp.sms.StatusMessage;
+import com.android.phone.vvm.omtp.sms.Vvm3MessageSender;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequest;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequest.NetworkWrapper;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequest.RequestFailedException;
+
+import java.io.IOException;
+import java.security.SecureRandom;
+import java.util.Locale;
+
+/**
+ * A flavor of OMTP protocol with a different provisioning process
+ *
+ * Used by carriers such as Verizon Wireless
+ */
+public class Vvm3Protocol extends VisualVoicemailProtocol {
+
+ private static final String TAG = "Vvm3Protocol";
+
+ private static final String SMS_EVENT_UNRECOGNIZED = "UNRECOGNIZED";
+ private static final String SMS_EVENT_UNRECOGNIZED_CMD = "cmd";
+ private static final String SMS_EVENT_UNRECOGNIZED_STATUS = "STATUS";
+ private static final String DEFAULT_VMG_URL_KEY = "default_vmg_url";
+
+ private static final String IMAP_CHANGE_TUI_PWD_FORMAT = "CHANGE_TUI_PWD PWD=%1$s OLD_PWD=%2$s";
+ private static final String IMAP_CHANGE_VM_LANG_FORMAT = "CHANGE_VM_LANG Lang=%1$s";
+ private static final String IMAP_CLOSE_NUT = "CLOSE_NUT";
+
+ private static final String ISO639_Spanish = "es";
+
+ /**
+ * For VVM3, if the STATUS SMS returns {@link StatusMessage#getProvisioningStatus()} of {@link
+ * OmtpConstants#SUBSCRIBER_UNKNOWN} and {@link StatusMessage#getReturnCode()} of this value,
+ * the user can self-provision visual voicemail service. For other response codes, the user must
+ * contact customer support to resolve the issue.
+ */
+ private static final String VVM3_UNKNOWN_SUBSCRIBER_CAN_SUBSCRIBE_RESPONSE_CODE = "2";
+
+ // Default prompt level when using the telephone user interface.
+ // Standard prompt when the user call into the voicemail, and no prompts when someone else is
+ // leaving a voicemail.
+ private static final String VVM3_VM_LANGUAGE_ENGLISH_STANDARD_NO_GUEST_PROMPTS = "5";
+ private static final String VVM3_VM_LANGUAGE_SPANISH_STANDARD_NO_GUEST_PROMPTS = "6";
+
+ private static final int DEFAULT_PIN_LENGTH = 6;
+
+ @Override
+ public void startActivation(OmtpVvmCarrierConfigHelper config,
+ @Nullable PendingIntent sentIntent) {
+ // VVM3 does not support activation SMS.
+ // Send a status request which will start the provisioning process if the user is not
+ // provisioned.
+ VvmLog.i(TAG, "Activating");
+ config.requestStatus(sentIntent);
+ }
+
+ @Override
+ public void startDeactivation(OmtpVvmCarrierConfigHelper config) {
+ // VVM3 does not support deactivation.
+ // do nothing.
+ }
+
+ @Override
+ public boolean supportsProvisioning() {
+ return true;
+ }
+
+ @Override
+ public void startProvisioning(ActivationTask task, PhoneAccountHandle phoneAccountHandle,
+ OmtpVvmCarrierConfigHelper config, VoicemailStatus.Editor status, StatusMessage message,
+ Bundle data) {
+ VvmLog.i(TAG, "start vvm3 provisioning");
+ if (OmtpConstants.SUBSCRIBER_UNKNOWN.equals(message.getProvisioningStatus())) {
+ VvmLog.i(TAG, "Provisioning status: Unknown");
+ if (VVM3_UNKNOWN_SUBSCRIBER_CAN_SUBSCRIBE_RESPONSE_CODE
+ .equals(message.getReturnCode())) {
+ VvmLog.i(TAG, "Self provisioning available, subscribing");
+ new Vvm3Subscriber(task, phoneAccountHandle, config, status, data).subscribe();
+ } else {
+ config.handleEvent(status, OmtpEvents.VVM3_SUBSCRIBER_UNKNOWN);
+ PhoneGlobals.getInstance().setShouldCheckVisualVoicemailConfigurationForMwi(task.getSubId(),
+ false);
+ }
+ } else if (OmtpConstants.SUBSCRIBER_NEW.equals(message.getProvisioningStatus())) {
+ VvmLog.i(TAG, "setting up new user");
+ // Save the IMAP credentials in preferences so they are persistent and can be retrieved.
+ VisualVoicemailPreferences prefs =
+ new VisualVoicemailPreferences(config.getContext(), phoneAccountHandle);
+ message.putStatus(prefs.edit()).apply();
+
+ startProvisionNewUser(task, phoneAccountHandle, config, status, message);
+ } else if (OmtpConstants.SUBSCRIBER_PROVISIONED.equals(message.getProvisioningStatus())) {
+ VvmLog.i(TAG, "User provisioned but not activated, disabling VVM");
+ VisualVoicemailSettingsUtil
+ .setEnabled(config.getContext(), phoneAccountHandle, false);
+ PhoneGlobals.getInstance().setShouldCheckVisualVoicemailConfigurationForMwi(task.getSubId(),
+ false);
+ } else if (OmtpConstants.SUBSCRIBER_BLOCKED.equals(message.getProvisioningStatus())) {
+ VvmLog.i(TAG, "User blocked");
+ config.handleEvent(status, OmtpEvents.VVM3_SUBSCRIBER_BLOCKED);
+ PhoneGlobals.getInstance().setShouldCheckVisualVoicemailConfigurationForMwi(task.getSubId(),
+ false);
+ }
+ }
+
+ @Override
+ public OmtpMessageSender createMessageSender(SmsManager smsManager, short applicationPort,
+ String destinationNumber) {
+ return new Vvm3MessageSender(smsManager, applicationPort, destinationNumber);
+ }
+
+ @Override
+ public void handleEvent(Context context, OmtpVvmCarrierConfigHelper config,
+ VoicemailStatus.Editor status, OmtpEvents event) {
+ Vvm3EventHandler.handleEvent(context, config, status, event);
+ }
+
+ @Override
+ public String getCommand(String command) {
+ if (command == OmtpConstants.IMAP_CHANGE_TUI_PWD_FORMAT) {
+ return IMAP_CHANGE_TUI_PWD_FORMAT;
+ }
+ if (command == OmtpConstants.IMAP_CLOSE_NUT) {
+ return IMAP_CLOSE_NUT;
+ }
+ if (command == OmtpConstants.IMAP_CHANGE_VM_LANG_FORMAT) {
+ return IMAP_CHANGE_VM_LANG_FORMAT;
+ }
+ return super.getCommand(command);
+ }
+
+ @Override
+ public Bundle translateStatusSmsBundle(OmtpVvmCarrierConfigHelper config, String event,
+ Bundle data) {
+ // UNRECOGNIZED?cmd=STATUS is the response of a STATUS request when the user is provisioned
+ // with iPhone visual voicemail without VoLTE. Translate it into an unprovisioned status
+ // so provisioning can be done.
+ if (!SMS_EVENT_UNRECOGNIZED.equals(event)) {
+ return null;
+ }
+ if (!SMS_EVENT_UNRECOGNIZED_STATUS.equals(data.getString(SMS_EVENT_UNRECOGNIZED_CMD))) {
+ return null;
+ }
+ Bundle bundle = new Bundle();
+ bundle.putString(OmtpConstants.PROVISIONING_STATUS, OmtpConstants.SUBSCRIBER_UNKNOWN);
+ bundle.putString(OmtpConstants.RETURN_CODE,
+ VVM3_UNKNOWN_SUBSCRIBER_CAN_SUBSCRIBE_RESPONSE_CODE);
+ String vmgUrl = config.getString(DEFAULT_VMG_URL_KEY);
+ if (TextUtils.isEmpty(vmgUrl)) {
+ VvmLog.e(TAG, "Unable to translate STATUS SMS: VMG URL is not set in config");
+ return null;
+ }
+ bundle.putString(Vvm3Subscriber.VMG_URL_KEY, vmgUrl);
+ VvmLog.i(TAG, "UNRECOGNIZED?cmd=STATUS translated into unprovisioned STATUS SMS");
+ return bundle;
+ }
+
+ private void startProvisionNewUser(ActivationTask task, PhoneAccountHandle phoneAccountHandle,
+ OmtpVvmCarrierConfigHelper config, VoicemailStatus.Editor status,
+ StatusMessage message) {
+ try (NetworkWrapper wrapper = VvmNetworkRequest
+ .getNetwork(config, phoneAccountHandle, status)) {
+ Network network = wrapper.get();
+
+ VvmLog.i(TAG, "new user: network available");
+ try (ImapHelper helper = new ImapHelper(config.getContext(), phoneAccountHandle,
+ network, status)) {
+ // VVM3 has inconsistent error language code to OMTP. Just issue a raw command
+ // here.
+ // TODO(b/29082671): use LocaleList
+ if (Locale.getDefault().getLanguage()
+ .equals(new Locale(ISO639_Spanish).getLanguage())) {
+ // Spanish
+ helper.changeVoicemailTuiLanguage(
+ VVM3_VM_LANGUAGE_SPANISH_STANDARD_NO_GUEST_PROMPTS);
+ } else {
+ // English
+ helper.changeVoicemailTuiLanguage(
+ VVM3_VM_LANGUAGE_ENGLISH_STANDARD_NO_GUEST_PROMPTS);
+ }
+ VvmLog.i(TAG, "new user: language set");
+
+ if (setPin(config.getContext(), phoneAccountHandle, helper, message)) {
+ // Only close new user tutorial if the PIN has been changed.
+ helper.closeNewUserTutorial();
+ VvmLog.i(TAG, "new user: NUT closed");
+
+ config.requestStatus(null);
+ }
+ } catch (InitializingException | MessagingException | IOException e) {
+ config.handleEvent(status, OmtpEvents.VVM3_NEW_USER_SETUP_FAILED);
+ task.fail();
+ VvmLog.e(TAG, e.toString());
+ }
+ } catch (RequestFailedException e) {
+ config.handleEvent(status, OmtpEvents.DATA_NO_CONNECTION_CELLULAR_REQUIRED);
+ task.fail();
+ }
+
+ }
+
+
+ private static boolean setPin(Context context, PhoneAccountHandle phoneAccountHandle,
+ ImapHelper helper, StatusMessage message)
+ throws IOException, MessagingException {
+ String defaultPin = getDefaultPin(message);
+ if (defaultPin == null) {
+ VvmLog.i(TAG, "cannot generate default PIN");
+ return false;
+ }
+
+ if (VoicemailChangePinActivity.isDefaultOldPinSet(context, phoneAccountHandle)) {
+ // The pin was already set
+ VvmLog.i(TAG, "PIN already set");
+ return true;
+ }
+ String newPin = generatePin(getMinimumPinLength(context, phoneAccountHandle));
+ if (helper.changePin(defaultPin, newPin) == OmtpConstants.CHANGE_PIN_SUCCESS) {
+ VoicemailChangePinActivity.setDefaultOldPIN(context, phoneAccountHandle, newPin);
+ helper.handleEvent(OmtpEvents.CONFIG_DEFAULT_PIN_REPLACED);
+ }
+ VvmLog.i(TAG, "new user: PIN set");
+ return true;
+ }
+
+ @Nullable
+ private static String getDefaultPin(StatusMessage message) {
+ // The IMAP username is [phone number]@example.com
+ String username = message.getImapUserName();
+ try {
+ String number = username.substring(0, username.indexOf('@'));
+ if (number.length() < 4) {
+ VvmLog.e(TAG, "unable to extract number from IMAP username");
+ return null;
+ }
+ return "1" + number.substring(number.length() - 4);
+ } catch (StringIndexOutOfBoundsException e) {
+ VvmLog.e(TAG, "unable to extract number from IMAP username");
+ return null;
+ }
+
+ }
+
+ private static int getMinimumPinLength(Context context, PhoneAccountHandle phoneAccountHandle) {
+ VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(context,
+ phoneAccountHandle);
+ // The OMTP pin length format is {min}-{max}
+ String[] lengths = preferences.getString(OmtpConstants.TUI_PASSWORD_LENGTH, "").split("-");
+ if (lengths.length == 2) {
+ try {
+ return Integer.parseInt(lengths[0]);
+ } catch (NumberFormatException e) {
+ return DEFAULT_PIN_LENGTH;
+ }
+ }
+ return DEFAULT_PIN_LENGTH;
+ }
+
+ private static String generatePin(int length) {
+ SecureRandom random = new SecureRandom();
+ return String.format(Locale.US, "%010d", Math.abs(random.nextLong()))
+ .substring(0, length);
+
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/protocol/Vvm3Subscriber.java b/src/com/android/phone/vvm/omtp/protocol/Vvm3Subscriber.java
new file mode 100644
index 0000000..ad00aa4
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/protocol/Vvm3Subscriber.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.protocol;
+
+import android.annotation.WorkerThread;
+import android.net.Network;
+import android.os.Build;
+import android.os.Bundle;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.TelephonyManager;
+import android.text.Html;
+import android.text.Spanned;
+import android.text.style.URLSpan;
+import android.util.ArrayMap;
+import com.android.phone.Assert;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.ActivationTask;
+import com.android.phone.vvm.omtp.OmtpEvents;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequest;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequest.NetworkWrapper;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequest.RequestFailedException;
+import com.android.volley.AuthFailureError;
+import com.android.volley.Request;
+import com.android.volley.RequestQueue;
+import com.android.volley.toolbox.HurlStack;
+import com.android.volley.toolbox.RequestFuture;
+import com.android.volley.toolbox.StringRequest;
+import com.android.volley.toolbox.Volley;
+import java.io.IOException;
+import java.net.CookieHandler;
+import java.net.CookieManager;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Random;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Class to subscribe to basic VVM3 visual voicemail, for example, Verizon. Subscription is required
+ * when the user is unprovisioned. This could happen when the user is on a legacy service, or
+ * switched over from devices that used other type of visual voicemail.
+ *
+ * The STATUS SMS will come with a URL to the voicemail management gateway. From it we can find the
+ * self provisioning gateway URL that we can modify voicemail services.
+ *
+ * A request to the self provisioning gateway to activate basic visual voicemail will return us with
+ * a web page. If the user hasn't subscribe to it yet it will contain a link to confirm the
+ * subscription. This link should be clicked through cellular network, and have cookies enabled.
+ *
+ * After the process is completed, the carrier should send us another STATUS SMS with a new or ready
+ * user.
+ */
+public class Vvm3Subscriber {
+
+ private static final String TAG = "Vvm3Subscriber";
+
+ private static final String OPERATION_GET_SPG_URL = "retrieveSPGURL";
+ private static final String SPG_URL_TAG = "spgurl";
+ private static final String TRANSACTION_ID_TAG = "transactionid";
+ //language=XML
+ private static final String VMG_XML_REQUEST_FORMAT = ""
+ + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
+ + "<VMGVVMRequest>"
+ + " <MessageHeader>"
+ + " <transactionid>%1$s</transactionid>"
+ + " </MessageHeader>"
+ + " <MessageBody>"
+ + " <mdn>%2$s</mdn>"
+ + " <operation>%3$s</operation>"
+ + " <source>Device</source>"
+ + " <devicemodel>%4$s</devicemodel>"
+ + " </MessageBody>"
+ + "</VMGVVMRequest>";
+
+ static final String VMG_URL_KEY = "vmg_url";
+
+ // Self provisioning POST key/values. VVM3 API 2.1.0 12.3
+ private static final String SPG_VZW_MDN_PARAM = "VZW_MDN";
+ private static final String SPG_VZW_SERVICE_PARAM = "VZW_SERVICE";
+ private static final String SPG_VZW_SERVICE_BASIC = "BVVM";
+ private static final String SPG_DEVICE_MODEL_PARAM = "DEVICE_MODEL";
+ // Value for all android device
+ private static final String SPG_DEVICE_MODEL_ANDROID = "DROID_4G";
+ private static final String SPG_APP_TOKEN_PARAM = "APP_TOKEN";
+ private static final String SPG_APP_TOKEN = "q8e3t5u2o1";
+ private static final String SPG_LANGUAGE_PARAM = "SPG_LANGUAGE_PARAM";
+ private static final String SPG_LANGUAGE_EN = "ENGLISH";
+
+ private static final String BASIC_SUBSCRIBE_LINK_TEXT = "Subscribe to Basic Visual Voice Mail";
+
+ private static final int REQUEST_TIMEOUT_SECONDS = 30;
+
+ private final ActivationTask mTask;
+ private final PhoneAccountHandle mHandle;
+ private final OmtpVvmCarrierConfigHelper mHelper;
+ private final VoicemailStatus.Editor mStatus;
+ private final Bundle mData;
+
+ private final String mNumber;
+
+ private RequestQueue mRequestQueue;
+
+ private static class ProvisioningException extends Exception {
+
+ public ProvisioningException(String message) {
+ super(message);
+ }
+ }
+
+ static {
+ // Set the default cookie handler to retain session data for the self provisioning gateway.
+ // Note; this is not ideal as it is application-wide, and can easily get clobbered.
+ // But it seems to be the preferred way to manage cookie for HttpURLConnection, and manually
+ // managing cookies will greatly increase complexity.
+ CookieManager cookieManager = new CookieManager();
+ CookieHandler.setDefault(cookieManager);
+ }
+
+ @WorkerThread
+ public Vvm3Subscriber(ActivationTask task, PhoneAccountHandle handle,
+ OmtpVvmCarrierConfigHelper helper, VoicemailStatus.Editor status, Bundle data) {
+ Assert.isNotMainThread();
+ mTask = task;
+ mHandle = handle;
+ mHelper = helper;
+ mStatus = status;
+ mData = data;
+
+ // Assuming getLine1Number() will work with VVM3. For unprovisioned users the IMAP username
+ // is not included in the status SMS, thus no other way to get the current phone number.
+ mNumber = mHelper.getContext().getSystemService(TelephonyManager.class)
+ .getLine1Number(mHelper.getSubId());
+ }
+
+ @WorkerThread
+ public void subscribe() {
+ Assert.isNotMainThread();
+ // Cellular data is required to subscribe.
+ // processSubscription() is called after network is available.
+ VvmLog.i(TAG, "Subscribing");
+
+ try (NetworkWrapper wrapper = VvmNetworkRequest.getNetwork(mHelper, mHandle, mStatus)) {
+ Network network = wrapper.get();
+ VvmLog.d(TAG, "provisioning: network available");
+ mRequestQueue = Volley
+ .newRequestQueue(mHelper.getContext(), new NetworkSpecifiedHurlStack(network));
+ processSubscription();
+ } catch (RequestFailedException e) {
+ mHelper.handleEvent(mStatus, OmtpEvents.VVM3_VMG_CONNECTION_FAILED);
+ mTask.fail();
+ }
+ }
+
+ private void processSubscription() {
+ try {
+ String gatewayUrl = getSelfProvisioningGateway();
+ String selfProvisionResponse = getSelfProvisionResponse(gatewayUrl);
+ String subscribeLink = findSubscribeLink(selfProvisionResponse);
+ clickSubscribeLink(subscribeLink);
+ } catch (ProvisioningException e) {
+ VvmLog.e(TAG, e.toString());
+ mTask.fail();
+ }
+ }
+
+ /**
+ * Get the URL to perform self-provisioning from the voicemail management gateway.
+ */
+ private String getSelfProvisioningGateway() throws ProvisioningException {
+ VvmLog.i(TAG, "retrieving SPG URL");
+ String response = vvm3XmlRequest(OPERATION_GET_SPG_URL);
+ return extractText(response, SPG_URL_TAG);
+ }
+
+ /**
+ * Sent a request to the self-provisioning gateway, which will return us with a webpage. The
+ * page might contain a "Subscribe to Basic Visual Voice Mail" link to complete the
+ * subscription. The cookie from this response and cellular data is required to click the link.
+ */
+ private String getSelfProvisionResponse(String url) throws ProvisioningException {
+ VvmLog.i(TAG, "Retrieving self provisioning response");
+
+ RequestFuture<String> future = RequestFuture.newFuture();
+
+ StringRequest stringRequest = new StringRequest(Request.Method.POST, url, future, future) {
+ @Override
+ protected Map<String, String> getParams() {
+ Map<String, String> params = new ArrayMap<>();
+ params.put(SPG_VZW_MDN_PARAM, mNumber);
+ params.put(SPG_VZW_SERVICE_PARAM, SPG_VZW_SERVICE_BASIC);
+ params.put(SPG_DEVICE_MODEL_PARAM, SPG_DEVICE_MODEL_ANDROID);
+ params.put(SPG_APP_TOKEN_PARAM, SPG_APP_TOKEN);
+ // Language to display the subscription page. The page is never shown to the user
+ // so just use English.
+ params.put(SPG_LANGUAGE_PARAM, SPG_LANGUAGE_EN);
+ return params;
+ }
+ };
+
+ mRequestQueue.add(stringRequest);
+ try {
+ return future.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ mHelper.handleEvent(mStatus, OmtpEvents.VVM3_SPG_CONNECTION_FAILED);
+ throw new ProvisioningException(e.toString());
+ }
+ }
+
+ private void clickSubscribeLink(String subscribeLink) throws ProvisioningException {
+ VvmLog.i(TAG, "Clicking subscribe link");
+ RequestFuture<String> future = RequestFuture.newFuture();
+
+ StringRequest stringRequest = new StringRequest(Request.Method.POST,
+ subscribeLink, future, future);
+ mRequestQueue.add(stringRequest);
+ try {
+ // A new STATUS SMS will be sent after this request.
+ future.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ } catch (TimeoutException | ExecutionException | InterruptedException e) {
+ mHelper.handleEvent(mStatus, OmtpEvents.VVM3_SPG_CONNECTION_FAILED);
+ throw new ProvisioningException(e.toString());
+ }
+ // It could take very long for the STATUS SMS to return. Waiting for it is unreliable.
+ // Just leave the CONFIG STATUS as CONFIGURING and end the task. The user can always
+ // manually retry if it took too long.
+ }
+
+ private String vvm3XmlRequest(String operation) throws ProvisioningException {
+ VvmLog.d(TAG, "Sending vvm3XmlRequest for " + operation);
+ String voicemailManagementGateway = mData.getString(VMG_URL_KEY);
+ if (voicemailManagementGateway == null) {
+ VvmLog.e(TAG, "voicemailManagementGateway url unknown");
+ return null;
+ }
+ String transactionId = createTransactionId();
+ String body = String.format(Locale.US, VMG_XML_REQUEST_FORMAT,
+ transactionId, mNumber, operation, Build.MODEL);
+
+ RequestFuture<String> future = RequestFuture.newFuture();
+ StringRequest stringRequest = new StringRequest(Request.Method.POST,
+ voicemailManagementGateway, future, future) {
+ @Override
+ public byte[] getBody() throws AuthFailureError {
+ return body.getBytes();
+ }
+ };
+ mRequestQueue.add(stringRequest);
+
+ try {
+ String response = future.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ if (!transactionId.equals(extractText(response, TRANSACTION_ID_TAG))) {
+ throw new ProvisioningException("transactionId mismatch");
+ }
+ return response;
+ } catch (InterruptedException | ExecutionException | TimeoutException e) {
+ mHelper.handleEvent(mStatus, OmtpEvents.VVM3_VMG_CONNECTION_FAILED);
+ throw new ProvisioningException(e.toString());
+ }
+ }
+
+ private String findSubscribeLink(String response) throws ProvisioningException {
+ Spanned doc = Html.fromHtml(response, Html.FROM_HTML_MODE_LEGACY);
+ URLSpan[] spans = doc.getSpans(0, doc.length(), URLSpan.class);
+ StringBuilder fulltext = new StringBuilder();
+ for (URLSpan span : spans) {
+ String text = doc.subSequence(doc.getSpanStart(span), doc.getSpanEnd(span)).toString();
+ if (BASIC_SUBSCRIBE_LINK_TEXT.equals(text)) {
+ return span.getURL();
+ }
+ fulltext.append(text);
+ }
+ throw new ProvisioningException("Subscribe link not found: " + fulltext);
+ }
+
+ private String createTransactionId() {
+ return String.valueOf(Math.abs(new Random().nextLong()));
+ }
+
+ private String extractText(String xml, String tag) throws ProvisioningException {
+ Pattern pattern = Pattern.compile("<" + tag + ">(.*)<\\/" + tag + ">");
+ Matcher matcher = pattern.matcher(xml);
+ if (matcher.find()) {
+ return matcher.group(1);
+ }
+ throw new ProvisioningException("Tag " + tag + " not found in xml response");
+ }
+
+ private static class NetworkSpecifiedHurlStack extends HurlStack {
+
+ private final Network mNetwork;
+
+ public NetworkSpecifiedHurlStack(Network network) {
+ mNetwork = network;
+ }
+
+ @Override
+ protected HttpURLConnection createConnection(URL url) throws IOException {
+ return (HttpURLConnection) mNetwork.openConnection(url);
+ }
+
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/scheduling/BaseTask.java b/src/com/android/phone/vvm/omtp/scheduling/BaseTask.java
new file mode 100644
index 0000000..76537fa
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/scheduling/BaseTask.java
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.annotation.CallSuper;
+import android.annotation.MainThread;
+import android.annotation.WorkerThread;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.support.annotation.NonNull;
+import android.telephony.SubscriptionManager;
+import com.android.phone.Assert;
+import com.android.phone.NeededForTesting;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provides common utilities for task implementations, such as execution time and managing {@link
+ * Policy}
+ */
+public abstract class BaseTask implements Task {
+
+ private static final String EXTRA_SUB_ID = "extra_sub_id";
+
+ private Context mContext;
+
+ private int mId;
+ private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+ private boolean mHasStarted;
+ private volatile boolean mHasFailed;
+
+ @NonNull
+ private final List<Policy> mPolicies = new ArrayList<>();
+
+ private long mExecutionTime;
+
+ private static Clock sClock = new Clock();
+
+ protected BaseTask(int id) {
+ mId = id;
+ mExecutionTime = getTimeMillis();
+ }
+
+ /**
+ * Modify the task ID to prevent arbitrary task from executing. Can only be called before {@link
+ * #onCreate(Context, Intent, int, int)} returns.
+ */
+ @MainThread
+ public void setId(int id) {
+ Assert.isMainThread();
+ mId = id;
+ }
+
+ @MainThread
+ public boolean hasStarted() {
+ Assert.isMainThread();
+ return mHasStarted;
+ }
+
+ @MainThread
+ public boolean hasFailed() {
+ Assert.isMainThread();
+ return mHasFailed;
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public int getSubId() {
+ return mSubId;
+ }
+ /**
+ * Should be call in the constructor or {@link Policy#onCreate(BaseTask, Intent, int, int)} will
+ * be missed.
+ */
+ @MainThread
+ public BaseTask addPolicy(Policy policy) {
+ Assert.isMainThread();
+ mPolicies.add(policy);
+ return this;
+ }
+
+ /**
+ * Indicate the task has failed. {@link Policy#onFail()} will be triggered once the execution
+ * ends. This mechanism is used by policies for actions such as determining whether to schedule
+ * a retry. Must be call inside {@link #onExecuteInBackgroundThread()}
+ */
+ @WorkerThread
+ public void fail() {
+ Assert.isNotMainThread();
+ mHasFailed = true;
+ }
+
+ @MainThread
+ public void setExecutionTime(long timeMillis) {
+ Assert.isMainThread();
+ mExecutionTime = timeMillis;
+ }
+
+ public long getTimeMillis() {
+ return sClock.getTimeMillis();
+ }
+
+ /**
+ * Creates an intent that can be used to restart the current task. Derived class should build
+ * their intent upon this.
+ */
+ public Intent createRestartIntent() {
+ return createIntent(getContext(), this.getClass(), mSubId);
+ }
+
+ /**
+ * Creates an intent that can be used to start the {@link TaskSchedulerService}. Derived class
+ * should build their intent upon this.
+ */
+ public static Intent createIntent(Context context, Class<? extends BaseTask> task, int subId) {
+ Intent intent = TaskSchedulerService.createIntent(context, task);
+ intent.putExtra(EXTRA_SUB_ID, subId);
+ return intent;
+ }
+
+ @Override
+ public TaskId getId() {
+ return new TaskId(mId, mSubId);
+ }
+
+ @Override
+ @CallSuper
+ public void onCreate(Context context, Intent intent, int flags, int startId) {
+ mContext = context;
+ mSubId = intent.getIntExtra(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ for (Policy policy : mPolicies) {
+ policy.onCreate(this, intent, flags, startId);
+ }
+ }
+
+ @Override
+ public long getReadyInMilliSeconds() {
+ return mExecutionTime - getTimeMillis();
+ }
+
+ @Override
+ @CallSuper
+ public void onBeforeExecute() {
+ for (Policy policy : mPolicies) {
+ policy.onBeforeExecute();
+ }
+ mHasStarted = true;
+ }
+
+ @Override
+ @CallSuper
+ public void onCompleted() {
+ if (mHasFailed) {
+ for (Policy policy : mPolicies) {
+ policy.onFail();
+ }
+ }
+
+ for (Policy policy : mPolicies) {
+ policy.onCompleted();
+ }
+ }
+
+ @Override
+ public void onDuplicatedTaskAdded(Task task) {
+ for (Policy policy : mPolicies) {
+ policy.onDuplicatedTaskAdded();
+ }
+ }
+
+ @NeededForTesting
+ static class Clock {
+
+ public long getTimeMillis() {
+ return SystemClock.elapsedRealtime();
+ }
+ }
+
+ /**
+ * Used to replace the clock with an deterministic clock
+ */
+ @NeededForTesting
+ static void setClockForTesting(Clock clock) {
+ sClock = clock;
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/scheduling/BlockerTask.java b/src/com/android/phone/vvm/omtp/scheduling/BlockerTask.java
new file mode 100644
index 0000000..9d91828
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/scheduling/BlockerTask.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.content.Context;
+import android.content.Intent;
+
+import com.android.phone.vvm.omtp.VvmLog;
+
+/**
+ * Task to block another task of the same ID from being queued for a certain amount of time.
+ */
+public class BlockerTask extends BaseTask {
+
+ private static final String TAG = "BlockerTask";
+
+ public static final String EXTRA_TASK_ID = "extra_task_id";
+ public static final String EXTRA_BLOCK_FOR_MILLIS = "extra_block_for_millis";
+
+ public BlockerTask() {
+ super(TASK_INVALID);
+ }
+
+ @Override
+ public void onCreate(Context context, Intent intent, int flags, int startId) {
+ super.onCreate(context, intent, flags, startId);
+ setId(intent.getIntExtra(EXTRA_TASK_ID, TASK_INVALID));
+ setExecutionTime(getTimeMillis() + intent.getIntExtra(EXTRA_BLOCK_FOR_MILLIS, 0));
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ // Do nothing.
+ }
+
+ @Override
+ public void onDuplicatedTaskAdded(Task task) {
+ VvmLog
+ .v(TAG, task.toString() + "blocked, " + getReadyInMilliSeconds() + "millis remaining");
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/scheduling/MinimalIntervalPolicy.java b/src/com/android/phone/vvm/omtp/scheduling/MinimalIntervalPolicy.java
new file mode 100644
index 0000000..8bb22ca
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/scheduling/MinimalIntervalPolicy.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.content.Intent;
+
+import com.android.phone.vvm.omtp.scheduling.Task.TaskId;
+
+/**
+ * If a task with this policy succeeds, a {@link BlockerTask} with the same {@link TaskId} of the
+ * task will be queued immediately, preventing the same task from running for a certain amount of
+ * time.
+ */
+public class MinimalIntervalPolicy implements Policy {
+
+ BaseTask mTask;
+ TaskId mId;
+ int mBlockForMillis;
+
+ public MinimalIntervalPolicy(int blockForMillis) {
+ mBlockForMillis = blockForMillis;
+ }
+
+ @Override
+ public void onCreate(BaseTask task, Intent intent, int flags, int startId) {
+ mTask = task;
+ mId = mTask.getId();
+ }
+
+ @Override
+ public void onBeforeExecute() {
+
+ }
+
+ @Override
+ public void onCompleted() {
+ if (!mTask.hasFailed()) {
+ Intent intent = mTask
+ .createIntent(mTask.getContext(), BlockerTask.class, mId.subId);
+ intent.putExtra(BlockerTask.EXTRA_TASK_ID, mId.id);
+ intent.putExtra(BlockerTask.EXTRA_BLOCK_FOR_MILLIS, mBlockForMillis);
+ mTask.getContext().startService(intent);
+ }
+ }
+
+ @Override
+ public void onFail() {
+
+ }
+
+ @Override
+ public void onDuplicatedTaskAdded() {
+
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/scheduling/Policy.java b/src/com/android/phone/vvm/omtp/scheduling/Policy.java
new file mode 100644
index 0000000..fcb01b8
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/scheduling/Policy.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.content.Intent;
+
+/**
+ * A set of listeners managed by {@link BaseTask} for common behaviors such as retrying. Call {@link
+ * BaseTask#addPolicy(Policy)} to add a policy.
+ */
+public interface Policy {
+
+ void onCreate(BaseTask task, Intent intent, int flags, int startId);
+
+ void onBeforeExecute();
+
+ void onCompleted();
+
+ void onFail();
+
+ void onDuplicatedTaskAdded();
+}
diff --git a/src/com/android/phone/vvm/omtp/scheduling/PostponePolicy.java b/src/com/android/phone/vvm/omtp/scheduling/PostponePolicy.java
new file mode 100644
index 0000000..f23d7f7
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/scheduling/PostponePolicy.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.content.Intent;
+
+import com.android.phone.vvm.omtp.VvmLog;
+
+/**
+ * A task with Postpone policy will not be executed immediately. It will wait for a while and if a
+ * duplicated task is queued during the duration, the task will be postponed further. The task will
+ * only be executed if no new task was added in postponeMillis. Useful to batch small tasks in quick
+ * succession together.
+ */
+public class PostponePolicy implements Policy {
+
+ private static final String TAG = "PostponePolicy";
+
+ private final int mPostponeMillis;
+ private BaseTask mTask;
+
+ public PostponePolicy(int postponeMillis) {
+ mPostponeMillis = postponeMillis;
+ }
+
+ @Override
+ public void onCreate(BaseTask task, Intent intent, int flags, int startId) {
+ mTask = task;
+ mTask.setExecutionTime(mTask.getTimeMillis() + mPostponeMillis);
+ }
+
+ @Override
+ public void onBeforeExecute() {
+ // Do nothing
+ }
+
+ @Override
+ public void onCompleted() {
+ // Do nothing
+ }
+
+ @Override
+ public void onFail() {
+ // Do nothing
+ }
+
+ @Override
+ public void onDuplicatedTaskAdded() {
+ if (mTask.hasStarted()) {
+ return;
+ }
+ VvmLog.d(TAG, "postponing " + mTask);
+ mTask.setExecutionTime(mTask.getTimeMillis() + mPostponeMillis);
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/scheduling/RetryPolicy.java b/src/com/android/phone/vvm/omtp/scheduling/RetryPolicy.java
new file mode 100644
index 0000000..4f4126a
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/scheduling/RetryPolicy.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.content.Intent;
+import android.telecom.PhoneAccountHandle;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+
+/**
+ * A task with this policy will automatically re-queue itself if {@link BaseTask#fail()} has been
+ * called during {@link BaseTask#onExecuteInBackgroundThread()}. A task will be retried at most
+ * <code>retryLimit</code> times and with a <code>retryDelayMillis</code> interval in between.
+ */
+public class RetryPolicy implements Policy {
+
+ private static final String TAG = "RetryPolicy";
+ private static final String EXTRA_RETRY_COUNT = "extra_retry_count";
+
+ private final int mRetryLimit;
+ private final int mRetryDelayMillis;
+
+ private BaseTask mTask;
+
+ private int mRetryCount;
+ private boolean mFailed;
+
+ private VoicemailStatus.DeferredEditor mVoicemailStatusEditor;
+
+ public RetryPolicy(int retryLimit, int retryDelayMillis) {
+ mRetryLimit = retryLimit;
+ mRetryDelayMillis = retryDelayMillis;
+ }
+
+ private boolean hasMoreRetries() {
+ return mRetryCount < mRetryLimit;
+ }
+
+ /**
+ * Error status should only be set if retries has exhausted or the task is successful. Status
+ * writes to this editor will be deferred until the task has ended, and will only be committed
+ * if the task is successful or there are no retries left.
+ */
+ public VoicemailStatus.Editor getVoicemailStatusEditor() {
+ return mVoicemailStatusEditor;
+ }
+
+ @Override
+ public void onCreate(BaseTask task, Intent intent, int flags, int startId) {
+ mTask = task;
+ mRetryCount = intent.getIntExtra(EXTRA_RETRY_COUNT, 0);
+ if (mRetryCount > 0) {
+ VvmLog.d(TAG, "retry #" + mRetryCount + " for " + mTask + " queued, executing in "
+ + mRetryDelayMillis);
+ mTask.setExecutionTime(mTask.getTimeMillis() + mRetryDelayMillis);
+ }
+ PhoneAccountHandle phoneAccountHandle = PhoneAccountHandleConverter
+ .fromSubId(task.getSubId());
+ if (phoneAccountHandle == null) {
+ VvmLog.e(TAG, "null phone account for subId " + task.getSubId());
+ // This should never happen, but continue on if it does. The status write will be
+ // discarded.
+ }
+ mVoicemailStatusEditor = VoicemailStatus
+ .deferredEdit(task.getContext(), phoneAccountHandle);
+ }
+
+ @Override
+ public void onBeforeExecute() {
+
+ }
+
+ @Override
+ public void onCompleted() {
+ if (!mFailed || !hasMoreRetries()) {
+ if (!mFailed) {
+ VvmLog.d(TAG, mTask.toString() + " completed successfully");
+ }
+ if (!hasMoreRetries()) {
+ VvmLog.d(TAG, "Retry limit for " + mTask + " reached");
+ }
+ VvmLog.i(TAG, "committing deferred status: " + mVoicemailStatusEditor.getValues());
+ mVoicemailStatusEditor.deferredApply();
+ return;
+ }
+ VvmLog.i(TAG, "discarding deferred status: " + mVoicemailStatusEditor.getValues());
+ Intent intent = mTask.createRestartIntent();
+ intent.putExtra(EXTRA_RETRY_COUNT, mRetryCount + 1);
+
+ mTask.getContext().startService(intent);
+ }
+
+ @Override
+ public void onFail() {
+ mFailed = true;
+ }
+
+ @Override
+ public void onDuplicatedTaskAdded() {
+
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/scheduling/Task.java b/src/com/android/phone/vvm/omtp/scheduling/Task.java
new file mode 100644
index 0000000..05d86fd
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/scheduling/Task.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.annotation.MainThread;
+import android.annotation.WorkerThread;
+import android.content.Context;
+import android.content.Intent;
+import java.util.Objects;
+
+/**
+ * A task for {@link TaskSchedulerService} to execute. Since the task is sent through a intent to
+ * the scheduler, The task must be constructable with the intent. Specifically, It must have a
+ * constructor with zero arguments, and have all relevant data packed inside the intent. Use {@link
+ * TaskSchedulerService#createIntent(Context, Class)} to create a intent that will construct the
+ * Task.
+ *
+ * <p>Only {@link #onExecuteInBackgroundThread()} is run on the worker thread.
+ */
+public interface Task {
+
+ /**
+ * TaskId to indicate it has not be set. If a task does not provide a default TaskId it should
+ * be set before {@link Task#onCreate(Context, Intent, int, int) returns}
+ */
+ int TASK_INVALID = -1;
+
+ /**
+ * TaskId to indicate it should always be queued regardless of duplicates. {@link
+ * Task#onDuplicatedTaskAdded(Task)} will never be called on tasks with this TaskId.
+ */
+ int TASK_ALLOW_DUPLICATES = -2;
+
+ int TASK_UPLOAD = 1;
+ int TASK_SYNC = 2;
+ int TASK_ACTIVATION = 3;
+
+ /**
+ * Used to differentiate between types of tasks. If a task with the same TaskId is already in
+ * the queue the new task will be rejected.
+ */
+ class TaskId {
+
+ /**
+ * Indicates the operation type of the task.
+ */
+ public final int id;
+ /**
+ * Same operation for a different subId is allowed. subId is used to differentiate phone
+ * accounts in multi-SIM scenario. For example, each SIM can queue a sync task for their
+ * own.
+ */
+ public final int subId;
+
+ public TaskId(int id, int subId) {
+ this.id = id;
+ this.subId = subId;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof TaskId)) {
+ return false;
+ }
+ TaskId other = (TaskId) object;
+ return id == other.id && subId == other.subId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, subId);
+ }
+ }
+
+ TaskId getId();
+
+ @MainThread
+ void onCreate(Context context, Intent intent, int flags, int startId);
+
+ /**
+ * @return number of milliSeconds the scheduler should wait before running this task. A value
+ * less than {@link TaskSchedulerService#READY_TOLERANCE_MILLISECONDS} will be considered ready.
+ * If no tasks are ready, the scheduler will sleep for this amount of time before doing another
+ * check (it will still wake if a new task is added). The first task in the queue that is ready
+ * will be executed.
+ */
+ @MainThread
+ long getReadyInMilliSeconds();
+
+ /**
+ * Called on the main thread when the scheduler is about to send the task into the worker
+ * thread, calling {@link #onExecuteInBackgroundThread()}
+ */
+ @MainThread
+ void onBeforeExecute();
+
+ /**
+ * The actual payload of the task, executed on the worker thread.
+ */
+ @WorkerThread
+ void onExecuteInBackgroundThread();
+
+ /**
+ * Called on the main thread when {@link #onExecuteInBackgroundThread()} has finished or thrown
+ * an uncaught exception. The task is already removed from the queue at this point, and a same
+ * task can be queued again.
+ */
+ @MainThread
+ void onCompleted();
+
+ /**
+ * Another task with the same TaskId has been added. Necessary data can be retrieved from the
+ * other task, and after this returns the task will be discarded.
+ */
+ @MainThread
+ void onDuplicatedTaskAdded(Task task);
+}
diff --git a/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerService.java b/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerService.java
new file mode 100644
index 0000000..3d6fcdb
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerService.java
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.annotation.MainThread;
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.os.SystemClock;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.Assert;
+import com.android.phone.NeededForTesting;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.scheduling.Task.TaskId;
+import java.util.ArrayDeque;
+import java.util.Queue;
+
+/**
+ * A service to queue and run {@link Task} on a worker thread. Only one task will be ran at a time,
+ * and same task cannot exist in the queue at the same time. The service will be started when a
+ * intent is received, and stopped when there are no more tasks in the queue.
+ */
+public class TaskSchedulerService extends Service {
+
+ private static final String TAG = "VvmTaskScheduler";
+
+ private static final String ACTION_WAKEUP = "action_wakeup";
+
+ private static final int READY_TOLERANCE_MILLISECONDS = 100;
+
+ /**
+ * Threshold to determine whether to do a short or long sleep when a task is scheduled in the
+ * future.
+ *
+ * <p>A short sleep will continue to held the wake lock and use {@link
+ * Handler#postDelayed(Runnable, long)} to wait for the next task.
+ *
+ * <p>A long sleep will release the wake lock and set a {@link AlarmManager} alarm. The alarm is
+ * exact and will wake up the device. Note: as this service is run in the telephony process it
+ * does not seem to be restricted by doze or sleep, it will fire exactly at the moment. The
+ * unbundled version should take doze into account.
+ */
+ private static final int SHORT_SLEEP_THRESHOLD_MILLISECONDS = 60_000;
+ /**
+ * When there are no more tasks to be run the service should be stopped. But when all tasks has
+ * finished there might still be more tasks in the message queue waiting to be processed,
+ * especially the ones submitted in {@link Task#onCompleted()}. Wait for a while before stopping
+ * the service to make sure there are no pending messages.
+ */
+ private static final int STOP_DELAY_MILLISECONDS = 5_000;
+ private static final String EXTRA_CLASS_NAME = "extra_class_name";
+
+ private static final String WAKE_LOCK_TAG = "TaskSchedulerService_wakelock";
+
+ // The thread to run tasks on
+ private volatile WorkerThreadHandler mWorkerThreadHandler;
+
+ private Context mContext = this;
+ /**
+ * Used by tests to turn task handling into a single threaded process by calling {@link
+ * Handler#handleMessage(Message)} directly
+ */
+ private MessageSender mMessageSender = new MessageSender();
+
+ private MainThreadHandler mMainThreadHandler;
+
+ private WakeLock mWakeLock;
+
+ /**
+ * Main thread only, access through {@link #getTasks()}
+ */
+ private final Queue<Task> mTasks = new ArrayDeque<>();
+ private boolean mWorkerThreadIsBusy = false;
+
+ private final Runnable mStopServiceWithDelay = new Runnable() {
+ @Override
+ public void run() {
+ VvmLog.d(TAG, "Stopping service");
+ stopSelf();
+ }
+ };
+ /**
+ * Should attempt to run the next task when a task has finished or been added.
+ */
+ private boolean mTaskAutoRunDisabledForTesting = false;
+
+ @VisibleForTesting
+ final class WorkerThreadHandler extends Handler {
+
+ public WorkerThreadHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ @WorkerThread
+ public void handleMessage(Message msg) {
+ Assert.isNotMainThread();
+ Task task = (Task) msg.obj;
+ try {
+ VvmLog.v(TAG, "executing task " + task);
+ task.onExecuteInBackgroundThread();
+ } catch (Throwable throwable) {
+ VvmLog.e(TAG, "Exception while executing task " + task + ":", throwable);
+ }
+
+ Message schedulerMessage = mMainThreadHandler.obtainMessage();
+ schedulerMessage.obj = task;
+ mMessageSender.send(schedulerMessage);
+ }
+ }
+
+ @VisibleForTesting
+ final class MainThreadHandler extends Handler {
+
+ public MainThreadHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ @MainThread
+ public void handleMessage(Message msg) {
+ Assert.isMainThread();
+ Task task = (Task) msg.obj;
+ getTasks().remove(task);
+ task.onCompleted();
+ mWorkerThreadIsBusy = false;
+ maybeRunNextTask();
+ }
+ }
+
+ @Override
+ @MainThread
+ public void onCreate() {
+ super.onCreate();
+ mWakeLock = getSystemService(PowerManager.class)
+ .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG);
+ mWakeLock.setReferenceCounted(false);
+ HandlerThread thread = new HandlerThread("VvmTaskSchedulerService");
+ thread.start();
+
+ mWorkerThreadHandler = new WorkerThreadHandler(thread.getLooper());
+ mMainThreadHandler = new MainThreadHandler(Looper.getMainLooper());
+ }
+
+ @Override
+ public void onDestroy() {
+ mWorkerThreadHandler.getLooper().quit();
+ mWakeLock.release();
+ }
+
+ @Override
+ @MainThread
+ public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
+ Assert.isMainThread();
+ // maybeRunNextTask() will release the wakelock either by entering a long sleep or stopping
+ // the service.
+ mWakeLock.acquire();
+ if (ACTION_WAKEUP.equals(intent.getAction())) {
+ VvmLog.d(TAG, "woke up by AlarmManager");
+ } else {
+ Task task = createTask(intent, flags, startId);
+ if (task == null) {
+ VvmLog.e(TAG, "cannot create task form intent");
+ } else {
+ addTask(task);
+ }
+ }
+ maybeRunNextTask();
+ // STICKY means the service will be automatically restarted will the last intent if it is
+ // killed.
+ return START_NOT_STICKY;
+ }
+
+ @MainThread
+ @VisibleForTesting
+ void addTask(Task task) {
+ Assert.isMainThread();
+ if (task.getId().id == Task.TASK_INVALID) {
+ throw new AssertionError("Task id was not set to a valid value before adding.");
+ }
+ if (task.getId().id != Task.TASK_ALLOW_DUPLICATES) {
+ Task oldTask = getTask(task.getId());
+ if (oldTask != null) {
+ oldTask.onDuplicatedTaskAdded(task);
+ return;
+ }
+ }
+ mMainThreadHandler.removeCallbacks(mStopServiceWithDelay);
+ getTasks().add(task);
+ maybeRunNextTask();
+ }
+
+ @MainThread
+ @Nullable
+ private Task getTask(TaskId taskId) {
+ Assert.isMainThread();
+ for (Task task : getTasks()) {
+ if (task.getId().equals(taskId)) {
+ return task;
+ }
+ }
+ return null;
+ }
+
+ @MainThread
+ private Queue<Task> getTasks() {
+ Assert.isMainThread();
+ return mTasks;
+ }
+
+ /**
+ * Create an intent that will queue the <code>task</code>
+ */
+ public static Intent createIntent(Context context, Class<? extends Task> task) {
+ Intent intent = new Intent(context, TaskSchedulerService.class);
+ intent.putExtra(EXTRA_CLASS_NAME, task.getName());
+ return intent;
+ }
+
+ @VisibleForTesting
+ @MainThread
+ @Nullable
+ Task createTask(@Nullable Intent intent, int flags, int startId) {
+ Assert.isMainThread();
+ if (intent == null) {
+ return null;
+ }
+ String className = intent.getStringExtra(EXTRA_CLASS_NAME);
+ VvmLog.d(TAG, "create task:" + className);
+ if (className == null) {
+ throw new IllegalArgumentException("EXTRA_CLASS_NAME expected");
+ }
+ try {
+ Task task = (Task) Class.forName(className).newInstance();
+ task.onCreate(mContext, intent, flags, startId);
+ return task;
+ } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @MainThread
+ private void maybeRunNextTask() {
+ Assert.isMainThread();
+ if (mWorkerThreadIsBusy) {
+ return;
+ }
+ if (mTaskAutoRunDisabledForTesting) {
+ // If mTaskAutoRunDisabledForTesting is true, runNextTask() must be explicitly called
+ // to run the next task.
+ return;
+ }
+
+ runNextTask();
+ }
+
+ @VisibleForTesting
+ @MainThread
+ void runNextTask() {
+ Assert.isMainThread();
+ // The current alarm is no longer valid, a new one will be set up if required.
+ getSystemService(AlarmManager.class).cancel(getWakeupIntent());
+ if (getTasks().isEmpty()) {
+ prepareStop();
+ return;
+ }
+ Long minimalWaitTime = null;
+ for (Task task : getTasks()) {
+ long waitTime = task.getReadyInMilliSeconds();
+ if (waitTime < READY_TOLERANCE_MILLISECONDS) {
+ task.onBeforeExecute();
+ Message message = mWorkerThreadHandler.obtainMessage();
+ message.obj = task;
+ mWorkerThreadIsBusy = true;
+ mMessageSender.send(message);
+ return;
+ } else {
+ if (minimalWaitTime == null || waitTime < minimalWaitTime) {
+ minimalWaitTime = waitTime;
+ }
+ }
+ }
+ VvmLog.d(TAG, "minimal wait time:" + minimalWaitTime);
+ if (!mTaskAutoRunDisabledForTesting && minimalWaitTime != null) {
+ // No tasks are currently ready. Sleep until the next one should be.
+ // If a new task is added during the sleep the service will wake immediately.
+ sleep(minimalWaitTime);
+ }
+ }
+
+ private void sleep(long timeMillis) {
+ if (timeMillis < SHORT_SLEEP_THRESHOLD_MILLISECONDS) {
+ mMainThreadHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ maybeRunNextTask();
+ }
+ }, timeMillis);
+ return;
+ }
+
+ // Tasks does not have a strict timing requirement, use AlarmManager.set() so the OS could
+ // optimize the battery usage. As this service currently run in the telephony process the
+ // OS give it privileges to behave the same as setExact(), but set() is the targeted
+ // behavior once this is unbundled.
+ getSystemService(AlarmManager.class).set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + timeMillis,
+ getWakeupIntent());
+ mWakeLock.release();
+ VvmLog.d(TAG, "Long sleep for " + timeMillis + " millis");
+ }
+
+ private PendingIntent getWakeupIntent() {
+ Intent intent = new Intent(ACTION_WAKEUP, null, this, getClass());
+ return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+
+ private void prepareStop() {
+ VvmLog.d(TAG,
+ "No more tasks, stopping service if no task are added in "
+ + STOP_DELAY_MILLISECONDS + " millis");
+ mMainThreadHandler.postDelayed(mStopServiceWithDelay, STOP_DELAY_MILLISECONDS);
+ }
+
+ static class MessageSender {
+
+ public void send(Message message) {
+ message.sendToTarget();
+ }
+ }
+
+ @NeededForTesting
+ void setContextForTest(Context context) {
+ mContext = context;
+ }
+
+ @NeededForTesting
+ void setTaskAutoRunDisabledForTest(boolean value) {
+ mTaskAutoRunDisabledForTesting = value;
+ }
+
+ @NeededForTesting
+ void setMessageSenderForTest(MessageSender sender) {
+ mMessageSender = sender;
+ }
+
+ @NeededForTesting
+ void clearTasksForTest() {
+ mTasks.clear();
+ }
+
+ @Override
+ @Nullable
+ public IBinder onBind(Intent intent) {
+ return new LocalBinder();
+ }
+
+ @NeededForTesting
+ class LocalBinder extends Binder {
+
+ @NeededForTesting
+ public TaskSchedulerService getService() {
+ return TaskSchedulerService.this;
+ }
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/sms/LegacyModeSmsHandler.java b/src/com/android/phone/vvm/omtp/sms/LegacyModeSmsHandler.java
new file mode 100644
index 0000000..ba5bd70
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sms/LegacyModeSmsHandler.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 Google Inc. All Rights Reserved.
+ *
+ * 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.vvm.omtp.sms;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.VoicemailContract;
+import android.telecom.PhoneAccountHandle;
+
+import com.android.internal.telephony.Phone;
+import com.android.phone.PhoneUtils;
+import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
+
+/**
+ * Class ot handle voicemail SMS under legacy mode
+ *
+ * @see OmtpVvmCarrierConfigHelper#isLegacyModeEnabled()
+ */
+public class LegacyModeSmsHandler {
+
+ private static final String TAG = "LegacyModeSmsHandler";
+
+ public static void handle(Context context, Intent intent, PhoneAccountHandle handle) {
+ VvmLog.v(TAG, "processing VVM SMS on legacy mode");
+ String eventType = intent.getExtras()
+ .getString(VoicemailContract.EXTRA_VOICEMAIL_SMS_PREFIX);
+ Bundle data = intent.getExtras().getBundle(VoicemailContract.EXTRA_VOICEMAIL_SMS_FIELDS);
+
+ if (eventType.equals(OmtpConstants.SYNC_SMS_PREFIX)) {
+ SyncMessage message = new SyncMessage(data);
+ VvmLog.v(TAG, "Received SYNC sms for " + handle.getId() +
+ " with event " + message.getSyncTriggerEvent());
+
+ switch (message.getSyncTriggerEvent()) {
+ case OmtpConstants.NEW_MESSAGE:
+ case OmtpConstants.MAILBOX_UPDATE:
+ // The user has called into the voicemail and the new message count could
+ // change.
+ // For some carriers new message count could be set to 0 even if there are still
+ // unread messages, to clear the message waiting indicator.
+ VvmLog.v(TAG, "updating MWI");
+ Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(handle);
+ // Setting voicemail message count to non-zero will show the telephony voicemail
+ // notification, and zero will clear it.
+ phone.setVoiceMessageCount(message.getNewMessageCount());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 9ac37a4..397caf8 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -20,90 +20,98 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.os.Bundle;
import android.os.UserManager;
-import android.provider.Telephony;
import android.provider.VoicemailContract;
import android.telecom.PhoneAccountHandle;
import android.telecom.Voicemail;
-import android.telephony.SmsMessage;
-import android.util.Log;
-
-import com.android.internal.telephony.PhoneConstants;
-import com.android.phone.PhoneGlobals;
-import com.android.phone.PhoneUtils;
import com.android.phone.settings.VisualVoicemailSettingsUtil;
-import com.android.phone.vvm.omtp.LocalLogHelper;
+import com.android.phone.vvm.omtp.ActivationTask;
import com.android.phone.vvm.omtp.OmtpConstants;
-import com.android.phone.vvm.omtp.sync.OmtpVvmSourceManager;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.protocol.VisualVoicemailProtocol;
import com.android.phone.vvm.omtp.sync.OmtpVvmSyncService;
+import com.android.phone.vvm.omtp.sync.SyncOneTask;
+import com.android.phone.vvm.omtp.sync.SyncTask;
import com.android.phone.vvm.omtp.sync.VoicemailsQueryHelper;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
/**
* Receive SMS messages and send for processing by the OMTP visual voicemail source.
*/
public class OmtpMessageReceiver extends BroadcastReceiver {
+
private static final String TAG = "OmtpMessageReceiver";
private Context mContext;
- private PhoneAccountHandle mPhoneAccount;
@Override
public void onReceive(Context context, Intent intent) {
- if (!UserManager.get(context).isUserUnlocked()) {
- Log.i(TAG, "Received message on locked device");
- // A full sync will happen after the device is unlocked, so nothing need to be done.
- return;
- }
-
mContext = context;
- mPhoneAccount = PhoneUtils.makePstnPhoneAccountHandle(
- intent.getExtras().getInt(PhoneConstants.PHONE_KEY));
+ int subId = intent.getExtras().getInt(VoicemailContract.EXTRA_VOICEMAIL_SMS_SUBID);
+ PhoneAccountHandle phone = PhoneAccountHandleConverter.fromSubId(subId);
- if (mPhoneAccount == null) {
- Log.w(TAG, "Received message for null phone account");
+ if (phone == null) {
+ // This should never happen
+ VvmLog.i(TAG, "Received message for null phone account on subId " + subId);
return;
}
- if (!VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(mContext, mPhoneAccount)) {
- Log.v(TAG, "Received vvm message for disabled vvm source.");
+ if (!UserManager.get(context).isUserUnlocked()) {
+ VvmLog.i(TAG, "Received message on locked device");
+ // LegacyModeSmsHandler can handle new message notifications without storage access
+ LegacyModeSmsHandler.handle(context, intent, phone);
+ // A full sync will happen after the device is unlocked, so nothing else need to be
+ // done.
return;
}
- SmsMessage[] messages = Telephony.Sms.Intents.getMessagesFromIntent(intent);
-
- if (messages == null) {
- Log.w(TAG, "Message does not exist in the intent.");
- return;
- }
-
- StringBuilder messageBody = new StringBuilder();
-
- for (int i = 0; i < messages.length; i++) {
- if (messages[i].mWrappedSmsMessage != null) {
- messageBody.append(messages[i].getMessageBody());
- }
- }
-
- WrappedMessageData messageData = OmtpSmsParser.parse(messageBody.toString());
- if (messageData != null) {
- if (messageData.getPrefix() == OmtpConstants.SYNC_SMS_PREFIX) {
- SyncMessage message = new SyncMessage(messageData);
-
- Log.v(TAG, "Received SYNC sms for " + mPhoneAccount.getId() +
- " with event " + message.getSyncTriggerEvent());
- LocalLogHelper.log(TAG, "Received SYNC sms for " + mPhoneAccount.getId() +
- " with event " + message.getSyncTriggerEvent());
- processSync(message);
- } else if (messageData.getPrefix() == OmtpConstants.STATUS_SMS_PREFIX) {
- Log.v(TAG, "Received STATUS sms for " + mPhoneAccount.getId());
- LocalLogHelper.log(TAG, "Received Status sms for " + mPhoneAccount.getId());
- StatusMessage message = new StatusMessage(messageData);
- updateSource(message);
+ OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(mContext, subId);
+ if (!VisualVoicemailSettingsUtil.isEnabled(mContext, phone)) {
+ if (helper.isLegacyModeEnabled()) {
+ LegacyModeSmsHandler.handle(context, intent, phone);
} else {
- Log.e(TAG, "This should never have happened");
+ VvmLog.i(TAG, "Received vvm message for disabled vvm source.");
+ }
+ return;
+ }
+
+ String eventType = intent.getExtras()
+ .getString(VoicemailContract.EXTRA_VOICEMAIL_SMS_PREFIX);
+ Bundle data = intent.getExtras().getBundle(VoicemailContract.EXTRA_VOICEMAIL_SMS_FIELDS);
+
+ if (eventType == null || data == null) {
+ VvmLog.e(TAG, "Unparsable VVM SMS received, ignoring");
+ return;
+ }
+
+ if (eventType.equals(OmtpConstants.SYNC_SMS_PREFIX)) {
+ SyncMessage message = new SyncMessage(data);
+
+ VvmLog.v(TAG, "Received SYNC sms for " + subId +
+ " with event " + message.getSyncTriggerEvent());
+ processSync(phone, message);
+ } else if (eventType.equals(OmtpConstants.STATUS_SMS_PREFIX)) {
+ VvmLog.v(TAG, "Received Status sms for " + subId);
+ // If the STATUS SMS is initiated by ActivationTask the TaskSchedulerService will reject
+ // the follow request. Providing the data will also prevent ActivationTask from
+ // requesting another STATUS SMS. The following task will only run if the carrier
+ // spontaneous send a STATUS SMS, in that case, the VVM service should be reactivated.
+ ActivationTask.start(context, subId, data);
+ } else {
+ VvmLog.w(TAG, "Unknown prefix: " + eventType);
+ VisualVoicemailProtocol protocol = helper.getProtocol();
+ if (protocol == null) {
+ return;
+ }
+ Bundle statusData = helper.getProtocol()
+ .translateStatusSmsBundle(helper, eventType, data);
+ if (statusData != null) {
+ VvmLog.i(TAG, "Protocol recognized the SMS as STATUS, activating");
+ ActivationTask.start(context, subId, data);
}
}
- // Let this fall through: this is not a message we're interested in.
}
/**
@@ -114,13 +122,19 @@
*
* @param message The sync message to extract data from.
*/
- private void processSync(SyncMessage message) {
+ private void processSync(PhoneAccountHandle phone, SyncMessage message) {
Intent serviceIntent = null;
switch (message.getSyncTriggerEvent()) {
case OmtpConstants.NEW_MESSAGE:
+ if (!OmtpConstants.VOICE.equals(message.getContentType())) {
+ VvmLog.i(TAG, "Non-voice message of type '" + message.getContentType()
+ + "' received, ignoring");
+ return;
+ }
+
Voicemail.Builder builder = Voicemail.createForInsertion(
message.getTimestampMillis(), message.getSender())
- .setPhoneAccount(mPhoneAccount)
+ .setPhoneAccount(phone)
.setSourceData(message.getId())
.setDuration(message.getLength())
.setSourcePackage(mContext.getPackageName());
@@ -130,61 +144,19 @@
if (queryHelper.isVoicemailUnique(voicemail)) {
Uri uri = VoicemailContract.Voicemails.insert(mContext, voicemail);
voicemail = builder.setId(ContentUris.parseId(uri)).setUri(uri).build();
- serviceIntent = OmtpVvmSyncService.getSyncIntent(mContext,
- OmtpVvmSyncService.SYNC_DOWNLOAD_ONE_TRANSCRIPTION, mPhoneAccount,
- voicemail, true /* firstAttempt */);
+ SyncOneTask.start(mContext, phone, voicemail);
}
break;
case OmtpConstants.MAILBOX_UPDATE:
- serviceIntent = OmtpVvmSyncService.getSyncIntent(
- mContext, OmtpVvmSyncService.SYNC_DOWNLOAD_ONLY, mPhoneAccount,
- true /* firstAttempt */);
+ SyncTask.start(mContext, phone, OmtpVvmSyncService.SYNC_DOWNLOAD_ONLY);
break;
case OmtpConstants.GREETINGS_UPDATE:
// Not implemented in V1
break;
default:
- Log.e(TAG, "Unrecognized sync trigger event: " + message.getSyncTriggerEvent());
- break;
- }
-
- if (serviceIntent != null) {
- mContext.startService(serviceIntent);
- }
- }
-
- private void updateSource(StatusMessage message) {
- OmtpVvmSourceManager vvmSourceManager =
- OmtpVvmSourceManager.getInstance(mContext);
-
- if (OmtpConstants.SUCCESS.equals(message.getReturnCode())) {
- VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
- VoicemailContract.Status.CONFIGURATION_STATE_OK,
- VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
- VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
-
- // Save the IMAP credentials in preferences so they are persistent and can be retrieved.
- VisualVoicemailSettingsUtil.setVisualVoicemailCredentialsFromStatusMessage(
- mContext,
- mPhoneAccount,
- message);
-
- // Add the source to indicate that it is active.
- vvmSourceManager.addSource(mPhoneAccount);
-
- Intent serviceIntent = OmtpVvmSyncService.getSyncIntent(
- mContext, OmtpVvmSyncService.SYNC_FULL_SYNC, mPhoneAccount,
- true /* firstAttempt */);
- mContext.startService(serviceIntent);
-
- PhoneGlobals.getInstance().clearMwiIndicator(
- PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount));
- } else {
- Log.w(TAG, "Visual voicemail not available for subscriber.");
- // Override default isEnabled setting to false since visual voicemail is unable to
- // be accessed for some reason.
- VisualVoicemailSettingsUtil.setVisualVoicemailEnabled(mContext, mPhoneAccount,
- /* isEnabled */ false, /* isUserSet */ true);
+ VvmLog.e(TAG,
+ "Unrecognized sync trigger event: " + message.getSyncTriggerEvent());
+ break;
}
}
}
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageSender.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageSender.java
index 9080292..9a775f0 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageSender.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageSender.java
@@ -20,9 +20,10 @@
import android.telephony.SmsManager;
import com.android.phone.vvm.omtp.OmtpConstants;
-import com.android.services.telephony.Log;
+import com.android.phone.vvm.omtp.VvmLog;
import java.io.UnsupportedEncodingException;
+import java.util.Locale;
/**
* Send client originated OMTP messages to the OMTP server.
@@ -73,9 +74,10 @@
protected void sendSms(String text, PendingIntent sentIntent) {
// If application port is set to 0 then send simple text message, else send data message.
if (mApplicationPort == 0) {
- Log.v(TAG, String.format("Sending TEXT sms '%s' to %s", text, mDestinationNumber));
+ VvmLog
+ .v(TAG, String.format("Sending TEXT sms '%s' to %s", text, mDestinationNumber));
mSmsManager.sendTextMessageWithSelfPermissions(mDestinationNumber, null, text,
- sentIntent, null);
+ sentIntent, null, false);
} else {
byte[] data;
try {
@@ -83,8 +85,9 @@
} catch (UnsupportedEncodingException e) {
throw new IllegalStateException("Failed to encode: " + text);
}
- Log.v(TAG, String.format("Sending BINARY sms '%s' to %s:%d", text, mDestinationNumber,
- mApplicationPort));
+ VvmLog.v(TAG,
+ String.format(Locale.US, "Sending BINARY sms '%s' to %s:%d", text,
+ mDestinationNumber, mApplicationPort));
mSmsManager.sendDataMessageWithSelfPermissions(mDestinationNumber, null,
mApplicationPort, data, sentIntent, null);
}
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpProvisioningService.java b/src/com/android/phone/vvm/omtp/sms/OmtpProvisioningService.java
new file mode 100644
index 0000000..154eeeb
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpProvisioningService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.sms;
+
+import android.app.IntentService;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.provider.VoicemailContract;
+import android.telecom.PhoneAccountHandle;
+
+import com.android.phone.PhoneUtils;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+
+/**
+ * Performs visual voicemail provisioning in background thread. Not exported.
+ */
+public class OmtpProvisioningService extends IntentService {
+
+ public OmtpProvisioningService() {
+ super("OmtpProvisioningService");
+ }
+
+ /**
+ * Create an intent to start OmtpProvisioningService from a {@link
+ * VoicemailContract.ACTION_VOICEMAIL_SMS_RECEIVED} intent.
+ */
+ public static Intent getProvisionIntent(Context context, Intent messageIntent) {
+ Intent serviceIntent = new Intent(context, OmtpProvisioningService.class);
+
+ serviceIntent.putExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS_SUBID,
+ messageIntent.getExtras().getInt(VoicemailContract.EXTRA_VOICEMAIL_SMS_SUBID));
+ serviceIntent.putExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS_FIELDS,
+ messageIntent.getExtras().getBundle(VoicemailContract.EXTRA_VOICEMAIL_SMS_FIELDS));
+
+ return serviceIntent;
+ }
+
+ @Override
+ public void onHandleIntent(Intent intent) {
+ int subId = intent.getExtras().getInt(VoicemailContract.EXTRA_VOICEMAIL_SMS_SUBID);
+ PhoneAccountHandle phone = PhoneAccountHandleConverter.fromSubId(subId);
+
+ Bundle data = intent.getExtras().getBundle(VoicemailContract.EXTRA_VOICEMAIL_SMS_FIELDS);
+
+ StatusMessage message = new StatusMessage(data);
+ startProvisioning(phone, message, data);
+ }
+
+ private void startProvisioning(PhoneAccountHandle phone, StatusMessage message, Bundle data) {
+ OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(this,
+ PhoneUtils.getSubIdForPhoneAccountHandle(phone));
+
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpSmsParser.java b/src/com/android/phone/vvm/omtp/sms/OmtpSmsParser.java
deleted file mode 100644
index 54a2a02..0000000
--- a/src/com/android/phone/vvm/omtp/sms/OmtpSmsParser.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.phone.vvm.omtp.sms;
-
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.phone.vvm.omtp.OmtpConstants;
-
-import java.util.Map;
-
-/**
- * OMTP SMS parser interface, for parsing SYNC and STATUS SMS sent by OMTP visual voicemail server.
- */
-public class OmtpSmsParser {
- private static String TAG = "OmtpSmsParser";
- /**
- * Parses the supplied SMS body and returns back a structured OMTP message.
- * Returns null if unable to parse the SMS body.
- */
- public static WrappedMessageData parse(String smsBody) {
- if (smsBody == null) {
- return null;
- }
-
- WrappedMessageData messageData = null;
- if (smsBody.startsWith(OmtpConstants.SYNC_SMS_PREFIX)) {
- messageData = new WrappedMessageData(OmtpConstants.SYNC_SMS_PREFIX,
- parseSmsBody(smsBody.substring(OmtpConstants.SYNC_SMS_PREFIX.length())));
- // Check for a mandatory field.
- String triggerEvent = messageData.extractString(OmtpConstants.SYNC_TRIGGER_EVENT);
- if (triggerEvent == null) {
- Log.e(TAG, "Missing mandatory field: " + OmtpConstants.SYNC_TRIGGER_EVENT);
- return null;
- }
- } else if (smsBody.startsWith(OmtpConstants.STATUS_SMS_PREFIX)) {
- messageData = new WrappedMessageData(OmtpConstants.STATUS_SMS_PREFIX,
- parseSmsBody(smsBody.substring(OmtpConstants.STATUS_SMS_PREFIX.length())));
- }
-
- return messageData;
- }
-
- /**
- * Converts a String of key/value pairs into a Map object. The WrappedMessageData object
- * contains helper functions to retrieve the values.
- *
- * e.g. "//VVM:STATUS:st=R;rc=0;srv=1;dn=1;ipt=1;spt=0;u=eg@example.com;pw=1"
- * => "WrappedMessageData [mFields={st=R, ipt=1, srv=1, dn=1, u=eg@example.com, pw=1, rc=0}]"
- *
- * @param message The sms string with the prefix removed.
- * @return A WrappedMessageData object containing the map.
- */
- private static Map<String, String> parseSmsBody(String message) {
- Map<String, String> keyValues = new ArrayMap<String, String>();
- String[] entries = message.split(OmtpConstants.SMS_FIELD_SEPARATOR);
- for (String entry : entries) {
- String[] keyValue = entry.split(OmtpConstants.SMS_KEY_VALUE_SEPARATOR);
- if (keyValue.length != 2) {
- continue;
- }
- keyValues.put(keyValue[0].trim(), keyValue[1].trim());
- }
-
- return keyValues;
- }
-}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/sms/StatusMessage.java b/src/com/android/phone/vvm/omtp/sms/StatusMessage.java
index 7e4faac..65455d0 100644
--- a/src/com/android/phone/vvm/omtp/sms/StatusMessage.java
+++ b/src/com/android/phone/vvm/omtp/sms/StatusMessage.java
@@ -15,9 +15,12 @@
*/
package com.android.phone.vvm.omtp.sms;
+import android.os.Bundle;
import android.telecom.Log;
+import com.android.phone.NeededForTesting;
import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.VisualVoicemailPreferences;
/**
* Structured data representation of OMTP STATUS message.
@@ -42,6 +45,7 @@
private final String mSmtpPort;
private final String mSmtpUserName;
private final String mSmtpPassword;
+ private final String mTuiPasswordLength;
@Override
public String toString() {
@@ -56,23 +60,35 @@
+ ", mImapPassword=" + Log.pii(mImapPassword)
+ ", mSmtpPort=" + mSmtpPort
+ ", mSmtpUserName=" + mSmtpUserName
- + ", mSmtpPassword=" + Log.pii(mSmtpPassword) + "]";
+ + ", mSmtpPassword=" + Log.pii(mSmtpPassword)
+ + ", mTuiPasswordLength=" + mTuiPasswordLength + "]";
}
- public StatusMessage(WrappedMessageData wrappedData) {
- mProvisioningStatus = wrappedData.extractString(OmtpConstants.PROVISIONING_STATUS);
- mStatusReturnCode = wrappedData.extractString(OmtpConstants.RETURN_CODE);
- mSubscriptionUrl = wrappedData.extractString(OmtpConstants.SUBSCRIPTION_URL);
- mServerAddress = wrappedData.extractString(OmtpConstants.SERVER_ADDRESS);
- mTuiAccessNumber = wrappedData.extractString(OmtpConstants.TUI_ACCESS_NUMBER);
- mClientSmsDestinationNumber = wrappedData.extractString(
+ public StatusMessage(Bundle wrappedData) {
+ mProvisioningStatus = unquote(getString(wrappedData, OmtpConstants.PROVISIONING_STATUS));
+ mStatusReturnCode = getString(wrappedData, OmtpConstants.RETURN_CODE);
+ mSubscriptionUrl = getString(wrappedData, OmtpConstants.SUBSCRIPTION_URL);
+ mServerAddress = getString(wrappedData, OmtpConstants.SERVER_ADDRESS);
+ mTuiAccessNumber = getString(wrappedData, OmtpConstants.TUI_ACCESS_NUMBER);
+ mClientSmsDestinationNumber = getString(wrappedData,
OmtpConstants.CLIENT_SMS_DESTINATION_NUMBER);
- mImapPort = wrappedData.extractString(OmtpConstants.IMAP_PORT);
- mImapUserName = wrappedData.extractString(OmtpConstants.IMAP_USER_NAME);
- mImapPassword = wrappedData.extractString(OmtpConstants.IMAP_PASSWORD);
- mSmtpPort = wrappedData.extractString(OmtpConstants.SMTP_PORT);
- mSmtpUserName = wrappedData.extractString(OmtpConstants.SMTP_USER_NAME);
- mSmtpPassword = wrappedData.extractString(OmtpConstants.SMTP_PASSWORD);
+ mImapPort = getString(wrappedData, OmtpConstants.IMAP_PORT);
+ mImapUserName = getString(wrappedData, OmtpConstants.IMAP_USER_NAME);
+ mImapPassword = getString(wrappedData, OmtpConstants.IMAP_PASSWORD);
+ mSmtpPort = getString(wrappedData, OmtpConstants.SMTP_PORT);
+ mSmtpUserName = getString(wrappedData, OmtpConstants.SMTP_USER_NAME);
+ mSmtpPassword = getString(wrappedData, OmtpConstants.SMTP_PASSWORD);
+ mTuiPasswordLength = getString(wrappedData, OmtpConstants.TUI_PASSWORD_LENGTH);
+ }
+
+ private static String unquote(String string) {
+ if (string.length() < 2) {
+ return string;
+ }
+ if (string.startsWith("\"") && string.endsWith("\"")) {
+ return string.substring(1, string.length() - 1);
+ }
+ return string;
}
/**
@@ -93,6 +109,7 @@
* @return the URL of the voicemail server. This is the URL to send the users to for subscribing
* to the visual voicemail service.
*/
+ @NeededForTesting
public String getSubscriptionUrl() {
return mSubscriptionUrl;
}
@@ -109,6 +126,7 @@
* @return the Telephony User Interface number to call to access voicemails directly from the
* IVR.
*/
+ @NeededForTesting
public String getTuiAccessNumber() {
return mTuiAccessNumber;
}
@@ -116,6 +134,7 @@
/**
* @return the number to which client originated SMSes should be sent to.
*/
+ @NeededForTesting
public String getClientSmsDestinationNumber() {
return mClientSmsDestinationNumber;
}
@@ -144,6 +163,7 @@
/**
* @return the SMTP server port to talk to.
*/
+ @NeededForTesting
public String getSmtpPort() {
return mSmtpPort;
}
@@ -151,6 +171,7 @@
/**
* @return the SMTP user name to be used for SMTP authentication.
*/
+ @NeededForTesting
public String getSmtpUserName() {
return mSmtpUserName;
}
@@ -158,7 +179,32 @@
/**
* @return the SMTP password to be used for SMTP authentication.
*/
+ @NeededForTesting
public String getSmtpPassword() {
return mSmtpPassword;
}
+
+ public String getTuiPasswordLength() {
+ return mTuiPasswordLength;
+ }
+
+ private static String getString(Bundle bundle, String key) {
+ String value = bundle.getString(key);
+ if (value == null) {
+ return "";
+ }
+ return value;
+ }
+
+ /**
+ * Saves a StatusMessage to the {@link VisualVoicemailPreferences}. Not all fields are saved.
+ */
+ public VisualVoicemailPreferences.Editor putStatus(VisualVoicemailPreferences.Editor editor) {
+ return editor
+ .putString(OmtpConstants.IMAP_PORT, getImapPort())
+ .putString(OmtpConstants.SERVER_ADDRESS, getServerAddress())
+ .putString(OmtpConstants.IMAP_USER_NAME, getImapUserName())
+ .putString(OmtpConstants.IMAP_PASSWORD, getImapPassword())
+ .putString(OmtpConstants.TUI_PASSWORD_LENGTH, getTuiPasswordLength());
+ }
}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/sms/StatusSmsFetcher.java b/src/com/android/phone/vvm/omtp/sms/StatusSmsFetcher.java
new file mode 100644
index 0000000..69e4f5f
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sms/StatusSmsFetcher.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.phone.vvm.omtp.sms;
+
+import android.annotation.MainThread;
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.app.Activity;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.provider.VoicemailContract;
+import android.telephony.SmsManager;
+
+import com.android.phone.Assert;
+import com.android.phone.vvm.omtp.OmtpConstants;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.protocol.VisualVoicemailProtocol;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Intercepts a incoming STATUS SMS with a blocking call.
+ */
+public class StatusSmsFetcher extends BroadcastReceiver implements Closeable {
+
+ private static final String TAG = "VvmStatusSmsFetcher";
+
+ private static final long STATUS_SMS_TIMEOUT_MILLIS = 60_000;
+ private static final String ACTION_REQUEST_SENT_INTENT
+ = "com.android.phone.vvm.omtp.sms.REQUEST_SENT";
+ private static final int ACTION_REQUEST_SENT_REQUEST_CODE = 0;
+
+ private CompletableFuture<Bundle> mFuture = new CompletableFuture<>();
+
+ private final Context mContext;
+ private final int mSubId;
+
+ public StatusSmsFetcher(Context context, int subId) {
+ mContext = context;
+ mSubId = subId;
+ IntentFilter filter = new IntentFilter(VoicemailContract.ACTION_VOICEMAIL_SMS_RECEIVED);
+ filter.addAction(ACTION_REQUEST_SENT_INTENT);
+ context.registerReceiver(this, filter);
+ }
+
+ @Override
+ public void close() throws IOException {
+ mContext.unregisterReceiver(this);
+ }
+
+ @WorkerThread
+ @Nullable
+ public Bundle get() throws InterruptedException, ExecutionException, TimeoutException,
+ CancellationException {
+ Assert.isNotMainThread();
+ return mFuture.get(STATUS_SMS_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+ }
+
+ public PendingIntent getSentIntent() {
+ Intent intent = new Intent(ACTION_REQUEST_SENT_INTENT);
+ intent.setPackage(mContext.getPackageName());
+ // Because the receiver is registered dynamically, implicit intent must be used.
+ // There should only be a single status SMS request at a time.
+ return PendingIntent.getBroadcast(mContext, ACTION_REQUEST_SENT_REQUEST_CODE, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ }
+
+ @Override
+ @MainThread
+ public void onReceive(Context context, Intent intent) {
+ Assert.isMainThread();
+ if (ACTION_REQUEST_SENT_INTENT.equals(intent.getAction())) {
+ int resultCode = getResultCode();
+
+ if (resultCode == Activity.RESULT_OK) {
+ VvmLog.d(TAG, "Request SMS successfully sent");
+ return;
+ }
+
+ VvmLog.e(TAG, "Request SMS send failed: " + sentSmsResultToString(resultCode));
+ mFuture.cancel(true);
+ return;
+ }
+
+ int subId = intent.getExtras().getInt(VoicemailContract.EXTRA_VOICEMAIL_SMS_SUBID);
+
+ if (mSubId != subId) {
+ return;
+ }
+ String eventType = intent.getExtras()
+ .getString(VoicemailContract.EXTRA_VOICEMAIL_SMS_PREFIX);
+
+ if (eventType.equals(OmtpConstants.STATUS_SMS_PREFIX)) {
+ mFuture.complete(intent.getBundleExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS_FIELDS));
+ return;
+ }
+
+ if (eventType.equals(OmtpConstants.SYNC_SMS_PREFIX)) {
+ return;
+ }
+
+ VvmLog.i(TAG, "VVM SMS with event " + eventType
+ + " received, attempting to translate to STATUS SMS");
+ OmtpVvmCarrierConfigHelper helper = new OmtpVvmCarrierConfigHelper(context, subId);
+ VisualVoicemailProtocol protocol = helper.getProtocol();
+ if (protocol == null) {
+ return;
+ }
+ Bundle translatedBundle = protocol.translateStatusSmsBundle(helper, eventType,
+ intent.getBundleExtra(VoicemailContract.EXTRA_VOICEMAIL_SMS_FIELDS));
+
+ if (translatedBundle != null) {
+ VvmLog.i(TAG, "Translated to STATUS SMS");
+ mFuture.complete(translatedBundle);
+ }
+ }
+
+ private static String sentSmsResultToString(int resultCode) {
+ switch (resultCode) {
+ case Activity.RESULT_OK:
+ return "OK";
+ case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
+ return "RESULT_ERROR_GENERIC_FAILURE";
+ case SmsManager.RESULT_ERROR_NO_SERVICE:
+ return "RESULT_ERROR_GENERIC_FAILURE";
+ case SmsManager.RESULT_ERROR_NULL_PDU:
+ return "RESULT_ERROR_GENERIC_FAILURE";
+ case SmsManager.RESULT_ERROR_RADIO_OFF:
+ return "RESULT_ERROR_GENERIC_FAILURE";
+ default:
+ return "UNKNOWN CODE: " + resultCode;
+ }
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/sms/SyncMessage.java b/src/com/android/phone/vvm/omtp/sms/SyncMessage.java
index 6829981..632ff9e 100644
--- a/src/com/android/phone/vvm/omtp/sms/SyncMessage.java
+++ b/src/com/android/phone/vvm/omtp/sms/SyncMessage.java
@@ -15,8 +15,16 @@
*/
package com.android.phone.vvm.omtp.sms;
+import android.annotation.Nullable;
+import android.os.Bundle;
+
+import com.android.phone.NeededForTesting;
import com.android.phone.vvm.omtp.OmtpConstants;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
/**
* Structured data representation of an OMTP SYNC message.
*
@@ -26,17 +34,17 @@
// Sync event that triggered this message.
private final String mSyncTriggerEvent;
// Total number of new messages on the server.
- private final Integer mNewMessageCount;
+ private final int mNewMessageCount;
// UID of the new message.
private final String mMessageId;
// Length of the message.
- private final Integer mMessageLength;
+ private final int mMessageLength;
// Content type (voice, video, fax...) of the new message.
private final String mContentType;
// Sender of the new message.
private final String mSender;
// Timestamp (in millis) of the new message.
- private final Long mMsgTimeMillis;
+ private final long mMsgTimeMillis;
@Override
public String toString() {
@@ -49,16 +57,28 @@
+ ", mMsgTimeMillis=" + mMsgTimeMillis + "]";
}
- public SyncMessage(WrappedMessageData wrappedData) {
- mSyncTriggerEvent = wrappedData.extractString(OmtpConstants.SYNC_TRIGGER_EVENT);
- mMessageId = wrappedData.extractString(OmtpConstants.MESSAGE_UID);
- mMessageLength = wrappedData.extractInteger(OmtpConstants.MESSAGE_LENGTH);
- mContentType = wrappedData.extractString(OmtpConstants.CONTENT_TYPE);
- mSender = wrappedData.extractString(OmtpConstants.SENDER);
- mNewMessageCount = wrappedData.extractInteger(OmtpConstants.NUM_MESSAGE_COUNT);
- mMsgTimeMillis = wrappedData.extractTime(OmtpConstants.TIME);
+ public SyncMessage(Bundle wrappedData) {
+ mSyncTriggerEvent = getString(wrappedData, OmtpConstants.SYNC_TRIGGER_EVENT);
+ mMessageId = getString(wrappedData, OmtpConstants.MESSAGE_UID);
+ mMessageLength = getInt(wrappedData, OmtpConstants.MESSAGE_LENGTH);
+ mContentType = getString(wrappedData, OmtpConstants.CONTENT_TYPE);
+ mSender = getString(wrappedData, OmtpConstants.SENDER);
+ mNewMessageCount = getInt(wrappedData, OmtpConstants.NUM_MESSAGE_COUNT);
+ mMsgTimeMillis = parseTime(wrappedData.getString(OmtpConstants.TIME));
}
+ private static long parseTime(@Nullable String value) {
+ if (value == null) {
+ return 0L;
+ }
+ try {
+ return new SimpleDateFormat(
+ OmtpConstants.DATE_TIME_FORMAT, Locale.US)
+ .parse(value).getTime();
+ } catch (ParseException e) {
+ return 0L;
+ }
+ }
/**
* @return the event that triggered the sync message. This is a mandatory field and must always
* be set.
@@ -70,8 +90,9 @@
/**
* @return the number of new messages stored on the voicemail server.
*/
+ @NeededForTesting
public int getNewMessageCount() {
- return mNewMessageCount != null ? mNewMessageCount : 0;
+ return mNewMessageCount;
}
/**
@@ -90,6 +111,7 @@
* Expected to be set only for
* {@link com.android.phone.vvm.omtp.OmtpConstants#NEW_MESSAGE}
*/
+ @NeededForTesting
public String getContentType() {
return mContentType;
}
@@ -101,7 +123,7 @@
* {@link com.android.phone.vvm.omtp.OmtpConstants#NEW_MESSAGE}
*/
public int getLength() {
- return mMessageLength != null ? mMessageLength : 0;
+ return mMessageLength;
}
/**
@@ -121,6 +143,26 @@
* {@link com.android.phone.vvm.omtp.OmtpConstants#NEW_MESSAGE}
*/
public long getTimestampMillis() {
- return mMsgTimeMillis != null ? mMsgTimeMillis : 0;
+ return mMsgTimeMillis;
+ }
+
+ private static int getInt(Bundle wrappedData, String key) {
+ String value = wrappedData.getString(key);
+ if (value == null) {
+ return 0;
+ }
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ return 0;
+ }
+ }
+
+ private static String getString(Bundle wrappedData, String key) {
+ String value = wrappedData.getString(key);
+ if (value == null) {
+ return "";
+ }
+ return value;
}
}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/sms/Vvm3MessageSender.java b/src/com/android/phone/vvm/omtp/sms/Vvm3MessageSender.java
new file mode 100644
index 0000000..dc2ea58
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sms/Vvm3MessageSender.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.sms;
+
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.telephony.SmsManager;
+
+public class Vvm3MessageSender extends OmtpMessageSender {
+
+ /**
+ * Creates a new instance of Vvm3MessageSender.
+ *
+ * @param smsManager SMS sending library. There is a different SmsManager for each SIM.
+ * @param applicationPort If set to a value > 0 then a binary sms is sent to this port number.
+ * Otherwise, a standard text SMS is sent.
+ */
+ public Vvm3MessageSender(SmsManager smsManager, short applicationPort,
+ String destinationNumber) {
+ super(smsManager, applicationPort, destinationNumber);
+ }
+
+ @Override
+ public void requestVvmActivation(@Nullable PendingIntent sentIntent) {
+ // Activation not supported for VVM3, send a status request instead.
+ requestVvmStatus(sentIntent);
+ }
+
+ @Override
+ public void requestVvmDeactivation(@Nullable PendingIntent sentIntent) {
+ // Deactivation not supported for VVM3, do nothing
+ }
+
+
+ @Override
+ public void requestVvmStatus(@Nullable PendingIntent sentIntent) {
+ // Status message:
+ // STATUS
+ StringBuilder sb = new StringBuilder().append("STATUS");
+ sendSms(sb.toString(), sentIntent);
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/sms/WrappedMessageData.java b/src/com/android/phone/vvm/omtp/sms/WrappedMessageData.java
deleted file mode 100644
index b4c86d4..0000000
--- a/src/com/android/phone/vvm/omtp/sms/WrappedMessageData.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-package com.android.phone.vvm.omtp.sms;
-
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.phone.vvm.omtp.OmtpConstants;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Class wrapping the raw OMTP message data, internally represented as as map of all key-value pairs
- * found in the SMS body.
- * <p>
- * Provides convenience methods to extract parse fields of different types.
- * <p>
- * All the methods return null if either the field was not present or it could not be parsed.
- */
-public class WrappedMessageData {
- private final String TAG = "WrappedMessageData";
- private final String mPrefix;
- private final Map<String, String> mFields;
-
- @Override
- public String toString() {
- return "WrappedMessageData [mFields=" + mFields + "]";
- }
-
- WrappedMessageData(String prefix, Map<String, String> keyValues) {
- mPrefix = prefix;
- mFields = new ArrayMap<String, String>();
- mFields.putAll(keyValues);
- }
-
- /**
- * @return The String prefix of the message, designating whether this is the message data of a
- * STATUS or SYNC sms.
- */
- String getPrefix() {
- return mPrefix;
- }
-
- /**
- * Extracts the requested field from underlying data and returns the String value as is.
- *
- * @param field The requested field.
- * @return the parsed string value, or null if the field was not present or not valid.
- */
- String extractString(final String field) {
- String value = mFields.get(field);
- if (value == null) {
- return null;
- }
-
- String[] possibleValues = OmtpConstants.possibleValuesMap.get(field);
- if (possibleValues == null) {
- return value;
- }
- for (int i = 0; i < possibleValues.length; i++) {
- if (TextUtils.equals(value, possibleValues[i])) {
- return value;
- }
- }
- Log.e(TAG, "extractString - value \"" + value +
- "\" of field \"" + field + "\" is not allowed.");
- return null;
- }
-
- /**
- * Extracts the requested field from underlying data and parses it as an {@link Integer}.
- *
- * @param field The requested field.
- * @return the parsed integer value, or null if the field was not present.
- */
- Integer extractInteger(final String field) {
- String value = mFields.get(field);
- if (value == null) {
- return null;
- }
-
- try {
- return Integer.decode(value);
- } catch (NumberFormatException e) {
- Log.e(TAG, "extractInteger - could not parse integer: " + value);
- return null;
- }
- }
-
- /**
- * Extracts the requested field from underlying data and parses it as a date/time represented in
- * {@link OmtpConstants#DATE_TIME_FORMAT} format.
- *
- * @param field The requested field.
- * @return the parsed string value, or null if the field was not present.
- */
- Long extractTime(final String field) {
- String value = mFields.get(field);
- if (value == null) {
- return null;
- }
-
- try {
- return new SimpleDateFormat(
- OmtpConstants.DATE_TIME_FORMAT, Locale.US).parse(value).getTime();
- } catch (ParseException e) {
- Log.e(TAG, "extractTime - could not parse time: " + value);
- return null;
- }
- }
-}
\ No newline at end of file
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java
index 0520098..9b06462 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSourceManager.java
@@ -16,16 +16,14 @@
package com.android.phone.vvm.omtp.sync;
import android.content.Context;
-import android.provider.VoicemailContract;
import android.telecom.PhoneAccountHandle;
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
-
import com.android.internal.telephony.Phone;
import com.android.phone.PhoneUtils;
+import com.android.phone.VoicemailStatus;
import com.android.phone.vvm.omtp.VvmPhoneStateListener;
-
import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -105,13 +103,11 @@
}
public void removeSource(PhoneAccountHandle phoneAccount) {
- VoicemailContract.Status.setStatus(mContext, phoneAccount,
- VoicemailContract.Status.CONFIGURATION_STATE_NOT_CONFIGURED,
- VoicemailContract.Status.DATA_CHANNEL_STATE_NO_CONNECTION,
- VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_NO_CONNECTION);
+ // TODO: should use OmtpVvmCarrierConfigHelper to handle the event. But currently it
+ // couldn't handle events on removed SIMs
+ VoicemailStatus.disable(mContext, phoneAccount);
removePhoneStateListener(phoneAccount);
mActiveVvmSources.remove(phoneAccount);
- OmtpVvmSyncService.cancelAllRetries(mContext, phoneAccount);
}
public void addPhoneStateListener(Phone phone) {
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncReceiver.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncReceiver.java
index 0902b6d..41178eb 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncReceiver.java
@@ -20,7 +20,13 @@
import android.content.Context;
import android.content.Intent;
import android.provider.VoicemailContract;
-import android.util.Log;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+import com.android.phone.settings.VisualVoicemailSettingsUtil;
+import com.android.phone.vvm.omtp.ActivationTask;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+import java.util.List;
public class OmtpVvmSyncReceiver extends BroadcastReceiver {
@@ -29,11 +35,27 @@
@Override
public void onReceive(final Context context, Intent intent) {
if (VoicemailContract.ACTION_SYNC_VOICEMAIL.equals(intent.getAction())) {
- Log.v(TAG, "Sync intent received");
- Intent syncIntent = OmtpVvmSyncService
- .getSyncIntent(context, OmtpVvmSyncService.SYNC_FULL_SYNC, null, true);
- intent.putExtra(OmtpVvmSyncService.EXTRA_IS_MANUAL_SYNC, true);
- context.startService(syncIntent);
+ VvmLog.v(TAG, "Sync intent received");
+ for (PhoneAccountHandle source : OmtpVvmSourceManager.getInstance(context)
+ .getOmtpVvmSources()) {
+ SyncTask.start(context, source, OmtpVvmSyncService.SYNC_FULL_SYNC);
+ }
+ activateUnactivatedAccounts(context);
+ }
+ }
+
+ private static void activateUnactivatedAccounts(Context context) {
+ List<PhoneAccountHandle> accounts =
+ context.getSystemService(TelecomManager.class).getCallCapablePhoneAccounts();
+ for (PhoneAccountHandle phoneAccount : accounts) {
+ if (!VisualVoicemailSettingsUtil.isEnabled(context, phoneAccount)) {
+ continue;
+ }
+ int subId = PhoneAccountHandleConverter.toSubId(phoneAccount);
+ if (!OmtpVvmSourceManager.getInstance(context).isVvmSourceRegistered(phoneAccount)) {
+ VvmLog.i(TAG, "Unactivated account " + phoneAccount + " found, activating");
+ ActivationTask.start(context, subId, null);
+ }
}
}
}
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index e44904b..58797de 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -15,44 +15,39 @@
*/
package com.android.phone.vvm.omtp.sync;
-import android.app.AlarmManager;
-import android.app.IntentService;
-import android.app.PendingIntent;
import android.content.Context;
-import android.content.Intent;
import android.net.Network;
-import android.net.NetworkInfo;
import android.net.Uri;
import android.provider.VoicemailContract;
-import android.provider.VoicemailContract.Status;
import android.telecom.PhoneAccountHandle;
import android.telecom.Voicemail;
import android.text.TextUtils;
-import android.util.Log;
-
+import com.android.phone.Assert;
import com.android.phone.PhoneUtils;
-import com.android.phone.VoicemailUtils;
+import com.android.phone.VoicemailStatus;
import com.android.phone.settings.VisualVoicemailSettingsUtil;
-import com.android.phone.vvm.omtp.LocalLogHelper;
+import com.android.phone.vvm.omtp.ActivationTask;
+import com.android.phone.vvm.omtp.OmtpEvents;
import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
import com.android.phone.vvm.omtp.fetch.VoicemailFetchedCallback;
import com.android.phone.vvm.omtp.imap.ImapHelper;
-
+import com.android.phone.vvm.omtp.imap.ImapHelper.InitializingException;
+import com.android.phone.vvm.omtp.scheduling.BaseTask;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequest.NetworkWrapper;
+import com.android.phone.vvm.omtp.sync.VvmNetworkRequest.RequestFailedException;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Set;
/**
* Sync OMTP visual voicemail.
*/
-public class OmtpVvmSyncService extends IntentService {
+public class OmtpVvmSyncService {
private static final String TAG = OmtpVvmSyncService.class.getSimpleName();
- // Number of retries
- private static final int NETWORK_RETRY_COUNT = 3;
-
/**
* Signifies a sync with both uploading to the server and downloading from the server.
*/
@@ -70,210 +65,78 @@
*/
public static final String SYNC_DOWNLOAD_ONE_TRANSCRIPTION =
"download_one_transcription";
- /**
- * The account to sync.
- */
- public static final String EXTRA_PHONE_ACCOUNT = "phone_account";
- /**
- * The voicemail to fetch.
- */
- public static final String EXTRA_VOICEMAIL = "voicemail";
- /**
- * The sync request is initiated by the user, should allow shorter sync interval.
- */
- public static final String EXTRA_IS_MANUAL_SYNC = "is_manual_sync";
- // Minimum time allowed between full syncs
- private static final int MINIMUM_FULL_SYNC_INTERVAL_MILLIS = 60 * 1000;
- // Minimum time allowed between manual syncs
- private static final int MINIMUM_MANUAL_SYNC_INTERVAL_MILLIS = 3 * 1000;
+ private final Context mContext;
+
+ // Record the timestamp of the last full sync so that duplicate syncs can be reduced.
+ private static final String LAST_FULL_SYNC_TIMESTAMP = "last_full_sync_timestamp";
+ // Constant indicating that there has never been a full sync.
+ public static final long NO_PRIOR_FULL_SYNC = -1;
private VoicemailsQueryHelper mQueryHelper;
- public OmtpVvmSyncService() {
- super("OmtpVvmSyncService");
+ public OmtpVvmSyncService(Context context) {
+ mContext = context;
+ mQueryHelper = new VoicemailsQueryHelper(mContext);
}
- public static Intent getSyncIntent(Context context, String action,
- PhoneAccountHandle phoneAccount, boolean firstAttempt) {
- return getSyncIntent(context, action, phoneAccount, null, firstAttempt);
+ public void sync(BaseTask task, String action, PhoneAccountHandle phoneAccount,
+ Voicemail voicemail, VoicemailStatus.Editor status) {
+ Assert.isTrue(phoneAccount != null);
+ VvmLog.v(TAG, "Sync requested: " + action + " - for account: " + phoneAccount);
+ setupAndSendRequest(task, phoneAccount, voicemail, action, status);
}
- public static Intent getSyncIntent(Context context, String action,
- PhoneAccountHandle phoneAccount, Voicemail voicemail, boolean firstAttempt) {
- if (firstAttempt) {
- if (phoneAccount != null) {
- VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(context,
- phoneAccount);
- } else {
- OmtpVvmSourceManager vvmSourceManager =
- OmtpVvmSourceManager.getInstance(context);
- Set<PhoneAccountHandle> sources = vvmSourceManager.getOmtpVvmSources();
- for (PhoneAccountHandle source : sources) {
- VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(context, source);
- }
- }
- }
-
- Intent serviceIntent = new Intent(context, OmtpVvmSyncService.class);
- serviceIntent.setAction(action);
- if (phoneAccount != null) {
- serviceIntent.putExtra(EXTRA_PHONE_ACCOUNT, phoneAccount);
- }
- if (voicemail != null) {
- serviceIntent.putExtra(EXTRA_VOICEMAIL, voicemail);
- }
-
- cancelRetriesForIntent(context, serviceIntent);
- return serviceIntent;
- }
-
- /**
- * Cancel all retry syncs for an account.
- *
- * @param context The context the service runs in.
- * @param phoneAccount The phone account for which to cancel syncs.
- */
- public static void cancelAllRetries(Context context, PhoneAccountHandle phoneAccount) {
- cancelRetriesForIntent(context, getSyncIntent(context, SYNC_FULL_SYNC, phoneAccount,
- false));
- }
-
- /**
- * A helper method to cancel all pending alarms for intents that would be identical to the given
- * intent.
- *
- * @param context The context the service runs in.
- * @param intent The intent to search and cancel.
- */
- private static void cancelRetriesForIntent(Context context, Intent intent) {
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- alarmManager.cancel(PendingIntent.getService(context, 0, intent, 0));
-
- Intent copyIntent = new Intent(intent);
- if (SYNC_FULL_SYNC.equals(copyIntent.getAction())) {
- // A full sync action should also cancel both of the other types of syncs
- copyIntent.setAction(SYNC_DOWNLOAD_ONLY);
- alarmManager.cancel(PendingIntent.getService(context, 0, copyIntent, 0));
- copyIntent.setAction(SYNC_UPLOAD_ONLY);
- alarmManager.cancel(PendingIntent.getService(context, 0, copyIntent, 0));
- }
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- mQueryHelper = new VoicemailsQueryHelper(this);
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- if (intent == null) {
- Log.d(TAG, "onHandleIntent: could not handle null intent");
+ private void setupAndSendRequest(BaseTask task, PhoneAccountHandle phoneAccount,
+ Voicemail voicemail, String action, VoicemailStatus.Editor status) {
+ if (!VisualVoicemailSettingsUtil.isEnabled(mContext, phoneAccount)) {
+ VvmLog.v(TAG, "Sync requested for disabled account");
return;
}
- String action = intent.getAction();
- PhoneAccountHandle phoneAccount = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT);
- LocalLogHelper.log(TAG, "Sync requested: " + action +
- " for all accounts: " + String.valueOf(phoneAccount == null));
-
- boolean isManualSync = intent.getBooleanExtra(EXTRA_IS_MANUAL_SYNC, false);
- Voicemail voicemail = intent.getParcelableExtra(EXTRA_VOICEMAIL);
- if (phoneAccount != null) {
- Log.v(TAG, "Sync requested: " + action + " - for account: " + phoneAccount);
- setupAndSendRequest(phoneAccount, voicemail, action, isManualSync);
- } else {
- Log.v(TAG, "Sync requested: " + action + " - for all accounts");
- OmtpVvmSourceManager vvmSourceManager =
- OmtpVvmSourceManager.getInstance(this);
- Set<PhoneAccountHandle> sources = vvmSourceManager.getOmtpVvmSources();
- for (PhoneAccountHandle source : sources) {
- setupAndSendRequest(source, null, action, isManualSync);
- }
- }
- }
-
- private void setupAndSendRequest(PhoneAccountHandle phoneAccount, Voicemail voicemail,
- String action, boolean isManualSync) {
- if (!VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(this, phoneAccount)) {
- Log.v(TAG, "Sync requested for disabled account");
+ int subId = PhoneAccountHandleConverter.toSubId(phoneAccount);
+ if (!OmtpVvmSourceManager.getInstance(mContext).isVvmSourceRegistered(phoneAccount)) {
+ ActivationTask.start(mContext, subId, null);
return;
}
- if (SYNC_FULL_SYNC.equals(action)) {
- long lastSyncTime = VisualVoicemailSettingsUtil.getVisualVoicemailLastFullSyncTime(
- this, phoneAccount);
- long currentTime = System.currentTimeMillis();
- int minimumInterval = isManualSync ? MINIMUM_MANUAL_SYNC_INTERVAL_MILLIS
- : MINIMUM_MANUAL_SYNC_INTERVAL_MILLIS;
- if (currentTime - lastSyncTime < minimumInterval) {
- // If it's been less than a minute since the last sync, bail.
- Log.v(TAG, "Avoiding duplicate full sync: synced recently for "
- + phoneAccount.getId());
-
- /**
- * Perform a NOOP change to the database so the sender can observe the sync is
- * completed.
- * TODO: Instead of this hack, refactor the sync to be synchronous so the sender
- * can use sendOrderedBroadcast() to register a callback once all syncs are
- * finished
- * b/26937720
- */
- Status.setStatus(this, phoneAccount,
- Status.CONFIGURATION_STATE_IGNORE,
- Status.DATA_CHANNEL_STATE_IGNORE,
- Status.NOTIFICATION_CHANNEL_STATE_IGNORE);
+ OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(mContext, subId);
+ // DATA_IMAP_OPERATION_STARTED posting should not be deferred. This event clears all data
+ // channel errors, which should happen when the task starts, not when it ends. It is the
+ // "Sync in progress..." status.
+ config.handleEvent(VoicemailStatus.edit(mContext, phoneAccount),
+ OmtpEvents.DATA_IMAP_OPERATION_STARTED);
+ try (NetworkWrapper network = VvmNetworkRequest.getNetwork(config, phoneAccount, status)) {
+ if (network == null) {
+ VvmLog.e(TAG, "unable to acquire network");
+ task.fail();
return;
}
- VisualVoicemailSettingsUtil.setVisualVoicemailLastFullSyncTime(
- this, phoneAccount, currentTime);
+ doSync(task, network.get(), phoneAccount, voicemail, action, status);
+ } catch (RequestFailedException e) {
+ config.handleEvent(status, OmtpEvents.DATA_NO_CONNECTION_CELLULAR_REQUIRED);
+ task.fail();
}
-
- VvmNetworkRequestCallback networkCallback = new SyncNetworkRequestCallback(this,
- phoneAccount, voicemail, action);
- networkCallback.requestNetwork();
}
- private void doSync(Network network, VvmNetworkRequestCallback callback,
- PhoneAccountHandle phoneAccount, Voicemail voicemail, String action) {
- int retryCount = NETWORK_RETRY_COUNT;
- try {
- while (retryCount > 0) {
- ImapHelper imapHelper = new ImapHelper(this, phoneAccount, network);
- if (!imapHelper.isSuccessfullyInitialized()) {
- Log.w(TAG, "Can't retrieve Imap credentials.");
- VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
- phoneAccount);
- return;
- }
-
- boolean success = true;
- if (voicemail == null) {
- success = syncAll(action, imapHelper, phoneAccount);
- } else {
- success = syncOne(imapHelper, voicemail, phoneAccount);
- }
+ private void doSync(BaseTask task, Network network, PhoneAccountHandle phoneAccount,
+ Voicemail voicemail, String action, VoicemailStatus.Editor status) {
+ try (ImapHelper imapHelper = new ImapHelper(mContext, phoneAccount, network, status)) {
+ boolean success;
+ if (voicemail == null) {
+ success = syncAll(action, imapHelper, phoneAccount);
+ } else {
+ success = syncOne(imapHelper, voicemail, phoneAccount);
+ }
+ if (success) {
+ // TODO: b/30569269 failure should interrupt all subsequent task via exceptions
imapHelper.updateQuota();
-
- // Need to check again for whether visual voicemail is enabled because it could have
- // been disabled while waiting for the response from the network.
- if (VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(this, phoneAccount) &&
- !success) {
- retryCount--;
- Log.v(TAG, "Retrying " + action);
- } else {
- // Nothing more to do here, just exit.
- VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
- phoneAccount);
- VoicemailUtils.setDataChannelState(
- this, phoneAccount, Status.DATA_CHANNEL_STATE_OK);
- return;
- }
+ imapHelper.handleEvent(OmtpEvents.DATA_IMAP_OPERATION_COMPLETED);
+ } else {
+ task.fail();
}
- } finally {
- if (callback != null) {
- callback.releaseNetwork();
- }
+ } catch (InitializingException e) {
+ VvmLog.w(TAG, "Can't retrieve Imap credentials.", e);
+ return;
}
}
@@ -288,61 +151,25 @@
downloadSuccess = download(imapHelper, account);
}
- Log.v(TAG, "upload succeeded: [" + String.valueOf(uploadSuccess)
+ VvmLog.v(TAG, "upload succeeded: [" + String.valueOf(uploadSuccess)
+ "] download succeeded: [" + String.valueOf(downloadSuccess) + "]");
- boolean success = uploadSuccess && downloadSuccess;
- if (!uploadSuccess || !downloadSuccess) {
- if (uploadSuccess) {
- action = SYNC_DOWNLOAD_ONLY;
- } else if (downloadSuccess) {
- action = SYNC_UPLOAD_ONLY;
- }
- }
-
- return success;
+ return uploadSuccess && downloadSuccess;
}
private boolean syncOne(ImapHelper imapHelper, Voicemail voicemail,
PhoneAccountHandle account) {
if (shouldPerformPrefetch(account, imapHelper)) {
- VoicemailFetchedCallback callback = new VoicemailFetchedCallback(this,
- voicemail.getUri());
+ VoicemailFetchedCallback callback = new VoicemailFetchedCallback(mContext,
+ voicemail.getUri(), account);
imapHelper.fetchVoicemailPayload(callback, voicemail.getSourceData());
}
return imapHelper.fetchTranscription(
- new TranscriptionFetchedCallback(this, voicemail),
+ new TranscriptionFetchedCallback(mContext, voicemail),
voicemail.getSourceData());
}
- private class SyncNetworkRequestCallback extends VvmNetworkRequestCallback {
-
- Voicemail mVoicemail;
- private String mAction;
-
- public SyncNetworkRequestCallback(Context context, PhoneAccountHandle phoneAccount,
- Voicemail voicemail, String action) {
- super(context, phoneAccount);
- mAction = action;
- mVoicemail = voicemail;
- }
-
- @Override
- public void onAvailable(Network network) {
- super.onAvailable(network);
- NetworkInfo info = getConnectivityManager().getNetworkInfo(network);
- if (info == null) {
- Log.d(TAG, "Network Type: Unknown");
- } else {
- Log.d(TAG, "Network Type: " + info.getTypeName());
- }
-
- doSync(network, this, mPhoneAccount, mVoicemail, mAction);
- }
-
- }
-
private boolean upload(ImapHelper imapHelper) {
List<Voicemail> readVoicemails = mQueryHelper.getReadVoicemails();
List<Voicemail> deletedVoicemails = mQueryHelper.getDeletedVoicemails();
@@ -361,7 +188,7 @@
if (readVoicemails.size() > 0) {
if (imapHelper.markMessagesAsRead(readVoicemails)) {
- mQueryHelper.markReadInDatabase(readVoicemails);
+ mQueryHelper.markCleanInDatabase(readVoicemails);
} else {
success = false;
}
@@ -407,9 +234,10 @@
// The leftover messages are messages that exist on the server but not locally.
boolean prefetchEnabled = shouldPerformPrefetch(account, imapHelper);
for (Voicemail remoteVoicemail : remoteMap.values()) {
- Uri uri = VoicemailContract.Voicemails.insert(this, remoteVoicemail);
+ Uri uri = VoicemailContract.Voicemails.insert(mContext, remoteVoicemail);
if (prefetchEnabled) {
- VoicemailFetchedCallback fetchedCallback = new VoicemailFetchedCallback(this, uri);
+ VoicemailFetchedCallback fetchedCallback =
+ new VoicemailFetchedCallback(mContext, uri, account);
imapHelper.fetchVoicemailPayload(fetchedCallback, remoteVoicemail.getSourceData());
}
}
@@ -419,28 +247,10 @@
private boolean shouldPerformPrefetch(PhoneAccountHandle account, ImapHelper imapHelper) {
OmtpVvmCarrierConfigHelper carrierConfigHelper = new OmtpVvmCarrierConfigHelper(
- this, PhoneUtils.getSubIdForPhoneAccountHandle(account));
+ mContext, PhoneUtils.getSubIdForPhoneAccountHandle(account));
return carrierConfigHelper.isPrefetchEnabled() && !imapHelper.isRoaming();
}
- protected void setRetryAlarm(PhoneAccountHandle phoneAccount, String action) {
- Intent serviceIntent = new Intent(this, OmtpVvmSyncService.class);
- serviceIntent.setAction(action);
- serviceIntent.putExtra(OmtpVvmSyncService.EXTRA_PHONE_ACCOUNT, phoneAccount);
- PendingIntent pendingIntent = PendingIntent.getService(this, 0, serviceIntent, 0);
- long retryInterval = VisualVoicemailSettingsUtil.getVisualVoicemailRetryInterval(this,
- phoneAccount);
-
- Log.v(TAG, "Retrying " + action + " in " + retryInterval + "ms");
-
- AlarmManager alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
- alarmManager.set(AlarmManager.RTC, System.currentTimeMillis() + retryInterval,
- pendingIntent);
-
- VisualVoicemailSettingsUtil.setVisualVoicemailRetryInterval(this, phoneAccount,
- retryInterval * 2);
- }
-
/**
* Builds a map from provider data to message for the given collection of voicemails.
*/
diff --git a/src/com/android/phone/vvm/omtp/sync/SyncOneTask.java b/src/com/android/phone/vvm/omtp/sync/SyncOneTask.java
new file mode 100644
index 0000000..510efc7
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sync/SyncOneTask.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.sync;
+
+import android.content.Context;
+import android.content.Intent;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.Voicemail;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.scheduling.BaseTask;
+import com.android.phone.vvm.omtp.scheduling.RetryPolicy;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+
+/**
+ * Task to download a single voicemail from the server. This task is initiated by a SMS notifying
+ * the new voicemail arrival, and ignores the duplicated tasks constraint.
+ */
+public class SyncOneTask extends BaseTask {
+
+ private static final int RETRY_TIMES = 2;
+ private static final int RETRY_INTERVAL_MILLIS = 5_000;
+
+ private static final String EXTRA_PHONE_ACCOUNT_HANDLE = "extra_phone_account_handle";
+ private static final String EXTRA_SYNC_TYPE = "extra_sync_type";
+ private static final String EXTRA_VOICEMAIL = "extra_voicemail";
+
+ private PhoneAccountHandle mPhone;
+ private String mSyncType;
+ private Voicemail mVoicemail;
+
+ public static void start(Context context, PhoneAccountHandle phone, Voicemail voicemail) {
+ Intent intent = BaseTask
+ .createIntent(context, SyncOneTask.class,
+ PhoneAccountHandleConverter.toSubId(phone));
+ intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phone);
+ intent.putExtra(EXTRA_SYNC_TYPE, OmtpVvmSyncService.SYNC_DOWNLOAD_ONE_TRANSCRIPTION);
+ intent.putExtra(EXTRA_VOICEMAIL, voicemail);
+ context.startService(intent);
+ }
+
+ public SyncOneTask() {
+ super(TASK_ALLOW_DUPLICATES);
+ addPolicy(new RetryPolicy(RETRY_TIMES, RETRY_INTERVAL_MILLIS));
+ }
+
+ public void onCreate(Context context, Intent intent, int flags, int startId) {
+ super.onCreate(context, intent, flags, startId);
+ mPhone = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE);
+ mSyncType = intent.getStringExtra(EXTRA_SYNC_TYPE);
+ mVoicemail = intent.getParcelableExtra(EXTRA_VOICEMAIL);
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ OmtpVvmSyncService service = new OmtpVvmSyncService(getContext());
+ service.sync(this, mSyncType, mPhone, mVoicemail,
+ VoicemailStatus.edit(getContext(), mPhone));
+ }
+
+ @Override
+ public Intent createRestartIntent() {
+ Intent intent = super.createRestartIntent();
+ intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, mPhone);
+ intent.putExtra(EXTRA_SYNC_TYPE, mSyncType);
+ intent.putExtra(EXTRA_VOICEMAIL, mVoicemail);
+ return intent;
+ }
+
+}
diff --git a/src/com/android/phone/vvm/omtp/sync/SyncTask.java b/src/com/android/phone/vvm/omtp/sync/SyncTask.java
new file mode 100644
index 0000000..7374ee6
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sync/SyncTask.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.sync;
+
+import android.content.Context;
+import android.content.Intent;
+import android.telecom.PhoneAccountHandle;
+import com.android.phone.vvm.omtp.scheduling.BaseTask;
+import com.android.phone.vvm.omtp.scheduling.MinimalIntervalPolicy;
+import com.android.phone.vvm.omtp.scheduling.RetryPolicy;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+
+/**
+ * System initiated sync request.
+ */
+public class SyncTask extends BaseTask {
+
+ // Try sync for a total of 5 times, should take around 5 minutes before finally giving up.
+ private static final int RETRY_TIMES = 4;
+ private static final int RETRY_INTERVAL_MILLIS = 5_000;
+ private static final int MINIMAL_INTERVAL_MILLIS = 60_000;
+
+ private static final String EXTRA_PHONE_ACCOUNT_HANDLE = "extra_phone_account_handle";
+ private static final String EXTRA_SYNC_TYPE = "extra_sync_type";
+
+ private final RetryPolicy mRetryPolicy;
+
+ private PhoneAccountHandle mPhone;
+ private String mSyncType;
+
+ public static void start(Context context, PhoneAccountHandle phone, String syncType) {
+ Intent intent = BaseTask
+ .createIntent(context, SyncTask.class, PhoneAccountHandleConverter.toSubId(phone));
+ intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, phone);
+ intent.putExtra(EXTRA_SYNC_TYPE, syncType);
+ context.startService(intent);
+ }
+
+ public SyncTask() {
+ super(TASK_SYNC);
+ mRetryPolicy = new RetryPolicy(RETRY_TIMES, RETRY_INTERVAL_MILLIS);
+ addPolicy(mRetryPolicy);
+ addPolicy(new MinimalIntervalPolicy(MINIMAL_INTERVAL_MILLIS));
+ }
+
+ public void onCreate(Context context, Intent intent, int flags, int startId) {
+ super.onCreate(context, intent, flags, startId);
+ mPhone = intent.getParcelableExtra(EXTRA_PHONE_ACCOUNT_HANDLE);
+ mSyncType = intent.getStringExtra(EXTRA_SYNC_TYPE);
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ OmtpVvmSyncService service = new OmtpVvmSyncService(getContext());
+ service.sync(this, mSyncType, mPhone, null, mRetryPolicy.getVoicemailStatusEditor());
+ }
+
+ @Override
+ public Intent createRestartIntent() {
+ Intent intent = super.createRestartIntent();
+ intent.putExtra(EXTRA_PHONE_ACCOUNT_HANDLE, mPhone);
+ intent.putExtra(EXTRA_SYNC_TYPE, mSyncType);
+ return intent;
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/sync/UploadTask.java b/src/com/android/phone/vvm/omtp/sync/UploadTask.java
new file mode 100644
index 0000000..87c0a46
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sync/UploadTask.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.sync;
+
+import android.content.Context;
+import android.content.Intent;
+import android.telecom.PhoneAccountHandle;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.VvmLog;
+import com.android.phone.vvm.omtp.scheduling.BaseTask;
+import com.android.phone.vvm.omtp.scheduling.PostponePolicy;
+import com.android.phone.vvm.omtp.utils.PhoneAccountHandleConverter;
+
+/**
+ * Upload task triggered by database changes. Will wait until the database has been stable for
+ * {@link #POSTPONE_MILLIS} to execute.
+ */
+public class UploadTask extends BaseTask {
+
+ private static final String TAG = "VvmUploadTask";
+
+ private static final int POSTPONE_MILLIS = 5_000;
+
+ public UploadTask() {
+ super(TASK_UPLOAD);
+ addPolicy(new PostponePolicy(POSTPONE_MILLIS));
+ }
+
+ public static void start(Context context, PhoneAccountHandle phoneAccountHandle) {
+ Intent intent = BaseTask
+ .createIntent(context, UploadTask.class,
+ PhoneAccountHandleConverter.toSubId(phoneAccountHandle));
+ context.startService(intent);
+ }
+
+ @Override
+ public void onCreate(Context context, Intent intent, int flags, int startId) {
+ super.onCreate(context, intent, flags, startId);
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ OmtpVvmSyncService service = new OmtpVvmSyncService(getContext());
+
+ PhoneAccountHandle phoneAccountHandle = PhoneAccountHandleConverter.fromSubId(getSubId());
+ if (phoneAccountHandle == null) {
+ // This should never happen
+ VvmLog.e(TAG, "null phone account for subId " + getSubId());
+ return;
+ }
+ service.sync(this, OmtpVvmSyncService.SYNC_UPLOAD_ONLY,
+ phoneAccountHandle, null,
+ VoicemailStatus.edit(getContext(), phoneAccountHandle));
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/sync/VoicemailProviderChangeReceiver.java b/src/com/android/phone/vvm/omtp/sync/VoicemailProviderChangeReceiver.java
index c2e6178..bc9e6e1 100644
--- a/src/com/android/phone/vvm/omtp/sync/VoicemailProviderChangeReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sync/VoicemailProviderChangeReceiver.java
@@ -19,20 +19,23 @@
import android.content.Context;
import android.content.Intent;
import android.provider.VoicemailContract;
+import android.telecom.PhoneAccountHandle;
/**
* Receives changes to the voicemail provider so they can be sent to the voicemail server.
*/
public class VoicemailProviderChangeReceiver extends BroadcastReceiver {
+
@Override
public void onReceive(Context context, Intent intent) {
boolean isSelfChanged = intent.getBooleanExtra(VoicemailContract.EXTRA_SELF_CHANGE, false);
OmtpVvmSourceManager vvmSourceManager =
OmtpVvmSourceManager.getInstance(context);
if (vvmSourceManager.getOmtpVvmSources().size() > 0 && !isSelfChanged) {
- Intent serviceIntent = OmtpVvmSyncService.getSyncIntent(
- context, OmtpVvmSyncService.SYNC_UPLOAD_ONLY, null, true /* firstAttempt */);
- context.startService(serviceIntent);
+ for (PhoneAccountHandle source : OmtpVvmSourceManager.getInstance(context)
+ .getOmtpVvmSources()) {
+ UploadTask.start(context, source);
+ }
}
}
}
diff --git a/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java b/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
index 9a84232..9906386 100644
--- a/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
+++ b/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
@@ -25,7 +25,6 @@
import android.provider.VoicemailContract.Voicemails;
import android.telecom.PhoneAccountHandle;
import android.telecom.Voicemail;
-
import java.util.ArrayList;
import java.util.List;
@@ -150,15 +149,6 @@
new String[] { Long.toString(voicemail.getId()) });
}
- /**
- * Sends an update command to the voicemail content provider for a list of voicemails.
- * From the view of the provider, since the updater is the owner of the entry, a blank
- * "update" means that the voicemail source is indicating that the server has up-to-date
- * information on the voicemail. This flips the "dirty" bit to "0".
- *
- * @param voicemails The list of voicemails to update
- * @return The number of voicemails updated
- */
public int markReadInDatabase(List<Voicemail> voicemails) {
int count = voicemails.size();
for (int i = 0; i < count; i++) {
@@ -178,6 +168,32 @@
}
/**
+ * Sends an update command to the voicemail content provider for a list of voicemails. From the
+ * view of the provider, since the updater is the owner of the entry, a blank "update" means
+ * that the voicemail source is indicating that the server has up-to-date information on the
+ * voicemail. This flips the "dirty" bit to "0".
+ *
+ * @param voicemails The list of voicemails to update
+ * @return The number of voicemails updated
+ */
+ public int markCleanInDatabase(List<Voicemail> voicemails) {
+ int count = voicemails.size();
+ for (int i = 0; i < count; i++) {
+ markCleanInDatabase(voicemails.get(i));
+ }
+ return count;
+ }
+
+ /**
+ * Utility method to mark single message as clean.
+ */
+ public void markCleanInDatabase(Voicemail voicemail) {
+ Uri uri = ContentUris.withAppendedId(mSourceUri, voicemail.getId());
+ ContentValues contentValues = new ContentValues();
+ mContentResolver.update(uri, contentValues, null, null);
+ }
+
+ /**
* Utility method to add a transcription to the voicemail.
*/
public void updateWithTranscription(Voicemail voicemail, String transcription) {
diff --git a/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequest.java b/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequest.java
new file mode 100644
index 0000000..3bdb45b
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.sync;
+
+import android.net.Network;
+import android.support.annotation.NonNull;
+import android.telecom.PhoneAccountHandle;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
+import java.io.Closeable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+/**
+ * Class to retrieve a {@link Network} synchronously. {@link #getNetwork(OmtpVvmCarrierConfigHelper,
+ * PhoneAccountHandle)} will block until a suitable network is retrieved or it has failed.
+ */
+public class VvmNetworkRequest {
+
+ private static final String TAG = "VvmNetworkRequest";
+
+ /**
+ * A wrapper around a Network returned by a {@link VvmNetworkRequestCallback}, which should be
+ * closed once not needed anymore.
+ */
+ public static class NetworkWrapper implements Closeable {
+
+ private final Network mNetwork;
+ private final VvmNetworkRequestCallback mCallback;
+
+ private NetworkWrapper(Network network, VvmNetworkRequestCallback callback) {
+ mNetwork = network;
+ mCallback = callback;
+ }
+
+ public Network get() {
+ return mNetwork;
+ }
+
+ @Override
+ public void close() {
+ mCallback.releaseNetwork();
+ }
+ }
+
+ public static class RequestFailedException extends Exception {
+
+ private RequestFailedException(Throwable cause) {
+ super(cause);
+ }
+ }
+
+ @NonNull
+ public static NetworkWrapper getNetwork(OmtpVvmCarrierConfigHelper config,
+ PhoneAccountHandle handle, VoicemailStatus.Editor status) throws RequestFailedException {
+ FutureNetworkRequestCallback callback = new FutureNetworkRequestCallback(config, handle,
+ status);
+ callback.requestNetwork();
+ try {
+ return callback.getFuture().get();
+ } catch (InterruptedException | ExecutionException e) {
+ callback.releaseNetwork();
+ VvmLog.e(TAG, "can't get future network", e);
+ throw new RequestFailedException(e);
+ }
+ }
+
+ private static class FutureNetworkRequestCallback extends VvmNetworkRequestCallback {
+
+ /**
+ * {@link CompletableFuture#get()} will block until {@link CompletableFuture#
+ * complete(Object) } has been called on the other thread.
+ */
+ private final CompletableFuture<NetworkWrapper> mFuture = new CompletableFuture<>();
+
+ public FutureNetworkRequestCallback(OmtpVvmCarrierConfigHelper config,
+ PhoneAccountHandle phoneAccount, VoicemailStatus.Editor status) {
+ super(config, phoneAccount, status);
+ }
+
+ public Future<NetworkWrapper> getFuture() {
+ return mFuture;
+ }
+
+ @Override
+ public void onAvailable(Network network) {
+ super.onAvailable(network);
+ mFuture.complete(new NetworkWrapper(network, this));
+ }
+
+ @Override
+ public void onFailed(String reason) {
+ super.onFailed(reason);
+ mFuture.complete(null);
+ }
+
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequestCallback.java b/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequestCallback.java
index 884bec9..787fdcd 100644
--- a/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequestCallback.java
+++ b/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequestCallback.java
@@ -23,14 +23,12 @@
import android.net.NetworkRequest;
import android.os.Handler;
import android.os.Looper;
-import android.provider.VoicemailContract;
-import android.provider.VoicemailContract.Status;
import android.telecom.PhoneAccountHandle;
-import android.util.Log;
-
import com.android.phone.PhoneUtils;
-import com.android.phone.VoicemailUtils;
+import com.android.phone.VoicemailStatus;
+import com.android.phone.vvm.omtp.OmtpEvents;
import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
/**
* Base class for network request call backs for visual voicemail syncing with the Imap server. This
@@ -52,17 +50,34 @@
private ConnectivityManager mConnectivityManager;
private final OmtpVvmCarrierConfigHelper mCarrierConfigHelper;
private final int mSubId;
+ private final VoicemailStatus.Editor mStatus;
private boolean mRequestSent = false;
private boolean mResultReceived = false;
- public VvmNetworkRequestCallback(Context context, PhoneAccountHandle phoneAccount) {
+ public VvmNetworkRequestCallback(Context context, PhoneAccountHandle phoneAccount,
+ VoicemailStatus.Editor status) {
mContext = context;
mPhoneAccount = phoneAccount;
mSubId = PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccount);
+ mStatus = status;
mCarrierConfigHelper = new OmtpVvmCarrierConfigHelper(context, mSubId);
mNetworkRequest = createNetworkRequest();
}
+ public VvmNetworkRequestCallback(OmtpVvmCarrierConfigHelper config,
+ PhoneAccountHandle phoneAccount, VoicemailStatus.Editor status) {
+ mContext = config.getContext();
+ mPhoneAccount = phoneAccount;
+ mSubId = config.getSubId();
+ mStatus = status;
+ mCarrierConfigHelper = config;
+ mNetworkRequest = createNetworkRequest();
+ }
+
+ public VoicemailStatus.Editor getVoicemailStatusEditor() {
+ return mStatus;
+ }
+
/**
* @return NetworkRequest for a proper transport type. Use only cellular network if the carrier
* requires it. Otherwise use whatever available.
@@ -73,11 +88,11 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
if (mCarrierConfigHelper.isCellularDataRequired()) {
- Log.d(TAG, "Transport type: CELLULAR");
+ VvmLog.d(TAG, "Transport type: CELLULAR");
builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.setNetworkSpecifier(Integer.toString(mSubId));
} else {
- Log.d(TAG, "Transport type: ANY");
+ VvmLog.d(TAG, "Transport type: ANY");
}
return builder.build();
}
@@ -89,7 +104,7 @@
@Override
@CallSuper
public void onLost(Network network) {
- Log.d(TAG, "onLost");
+ VvmLog.d(TAG, "onLost");
mResultReceived = true;
onFailed(NETWORK_REQUEST_FAILED_LOST);
}
@@ -110,7 +125,7 @@
public void requestNetwork() {
if (mRequestSent == true) {
- Log.e(TAG, "requestNetwork() called twice");
+ VvmLog.e(TAG, "requestNetwork() called twice");
return;
}
mRequestSent = true;
@@ -131,7 +146,7 @@
}
public void releaseNetwork() {
- Log.d(TAG, "releaseNetwork");
+ VvmLog.d(TAG, "releaseNetwork");
getConnectivityManager().unregisterNetworkCallback(this);
}
@@ -145,14 +160,12 @@
@CallSuper
public void onFailed(String reason) {
- Log.d(TAG, "onFailed: " + reason);
+ VvmLog.d(TAG, "onFailed: " + reason);
if (mCarrierConfigHelper.isCellularDataRequired()) {
- VoicemailUtils.setDataChannelState(
- mContext, mPhoneAccount,
- Status.DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED);
+ mCarrierConfigHelper
+ .handleEvent(mStatus, OmtpEvents.DATA_NO_CONNECTION_CELLULAR_REQUIRED);
} else {
- VoicemailUtils.setDataChannelState(
- mContext, mPhoneAccount, Status.DATA_CHANNEL_STATE_NO_CONNECTION);
+ mCarrierConfigHelper.handleEvent(mStatus, OmtpEvents.DATA_NO_CONNECTION);
}
releaseNetwork();
}
diff --git a/src/com/android/phone/vvm/omtp/utils/PhoneAccountHandleConverter.java b/src/com/android/phone/vvm/omtp/utils/PhoneAccountHandleConverter.java
new file mode 100644
index 0000000..ad4c423
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/utils/PhoneAccountHandleConverter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.utils;
+
+import android.annotation.Nullable;
+import android.telecom.PhoneAccountHandle;
+import android.telephony.SubscriptionManager;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.phone.PhoneUtils;
+import com.android.phone.vvm.omtp.VvmLog;
+
+/**
+ * Utility to convert between PhoneAccountHandle and subId, which is a common operation in OMTP
+ * client
+ *
+ * TODO(b/28977379): remove dependency on PhoneUtils and use public APIs
+ */
+public class PhoneAccountHandleConverter {
+
+ private static final String TAG = "PhoneAccountHndCvtr";
+
+ @Nullable
+ public static PhoneAccountHandle fromSubId(int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ VvmLog.e(TAG, "invalid subId " + subId);
+ return null;
+ }
+ // Calling PhoneUtils.makePstnPhoneAccountHandle() with a phoneId might throw a NPE if the
+ // phone object cannot be found, so the Phone object should be created and checked here.
+ Phone phone = PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
+ if (phone == null) {
+ VvmLog.e(TAG, "Unable to find Phone for subId " + subId);
+ return null;
+ }
+ return PhoneUtils.makePstnPhoneAccountHandle(phone);
+ }
+
+ public static int toSubId(PhoneAccountHandle handle) {
+ return PhoneUtils.getSubIdForPhoneAccountHandle(handle);
+ }
+
+ private PhoneAccountHandleConverter() {
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/utils/VvmDumpHandler.java b/src/com/android/phone/vvm/omtp/utils/VvmDumpHandler.java
new file mode 100644
index 0000000..227cf42
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/utils/VvmDumpHandler.java
@@ -0,0 +1,32 @@
+package com.android.phone.vvm.omtp.utils;
+
+import android.content.Context;
+import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
+
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
+import com.android.phone.vvm.omtp.VvmLog;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+public class VvmDumpHandler {
+
+ public static void dump(Context context, FileDescriptor fd, PrintWriter writer,
+ String[] args) {
+ IndentingPrintWriter indentedWriter = new IndentingPrintWriter(writer, " ");
+ indentedWriter.println("******* OmtpVvm *******");
+ indentedWriter.println("======= Configs =======");
+ indentedWriter.increaseIndent();
+ for (PhoneAccountHandle handle : TelecomManager.from(context)
+ .getCallCapablePhoneAccounts()) {
+ int subId = PhoneAccountHandleConverter.toSubId(handle);
+ OmtpVvmCarrierConfigHelper config = new OmtpVvmCarrierConfigHelper(context, subId);
+ indentedWriter.println(config.toString());
+ }
+ indentedWriter.decreaseIndent();
+ indentedWriter.println("======== Logs =========");
+ VvmLog.dump(fd, indentedWriter, args);
+ }
+}
diff --git a/src/com/android/phone/vvm/omtp/utils/XmlUtils.java b/src/com/android/phone/vvm/omtp/utils/XmlUtils.java
new file mode 100644
index 0000000..4eeb5ce
--- /dev/null
+++ b/src/com/android/phone/vvm/omtp/utils/XmlUtils.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.utils;
+
+import android.util.ArrayMap;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class XmlUtils {
+
+ public static final ArrayMap<String, ?> readThisArrayMapXml(XmlPullParser parser, String endTag,
+ String[] name, ReadMapCallback callback)
+ throws XmlPullParserException, java.io.IOException {
+ ArrayMap<String, Object> map = new ArrayMap<>();
+
+ int eventType = parser.getEventType();
+ do {
+ if (eventType == XmlPullParser.START_TAG) {
+ Object val = readThisValueXml(parser, name, callback, true);
+ map.put(name[0], val);
+ } else if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals(endTag)) {
+ return map;
+ }
+ throw new XmlPullParserException(
+ "Expected " + endTag + " end tag at: " + parser.getName());
+ }
+ eventType = parser.next();
+ } while (eventType != XmlPullParser.END_DOCUMENT);
+
+ throw new XmlPullParserException(
+ "Document ended before " + endTag + " end tag");
+ }
+
+ /**
+ * Read an ArrayList object from an XmlPullParser. The XML data could previously have been
+ * generated by writeListXml(). The XmlPullParser must be positioned <em>after</em> the tag
+ * that begins the list.
+ *
+ * @param parser The XmlPullParser from which to read the list data.
+ * @param endTag Name of the tag that will end the list, usually "list".
+ * @param name An array of one string, used to return the name attribute of the list's tag.
+ * @return HashMap The newly generated list.
+ */
+ public static final ArrayList readThisListXml(XmlPullParser parser, String endTag,
+ String[] name, ReadMapCallback callback, boolean arrayMap)
+ throws XmlPullParserException, java.io.IOException {
+ ArrayList list = new ArrayList();
+
+ int eventType = parser.getEventType();
+ do {
+ if (eventType == XmlPullParser.START_TAG) {
+ Object val = readThisValueXml(parser, name, callback, arrayMap);
+ list.add(val);
+ } else if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals(endTag)) {
+ return list;
+ }
+ throw new XmlPullParserException(
+ "Expected " + endTag + " end tag at: " + parser.getName());
+ }
+ eventType = parser.next();
+ } while (eventType != XmlPullParser.END_DOCUMENT);
+
+ throw new XmlPullParserException(
+ "Document ended before " + endTag + " end tag");
+ }
+
+ /**
+ * Read a String[] object from an XmlPullParser. The XML data could previously have been
+ * generated by writeStringArrayXml(). The XmlPullParser must be positioned <em>after</em> the
+ * tag that begins the list.
+ *
+ * @param parser The XmlPullParser from which to read the list data.
+ * @param endTag Name of the tag that will end the list, usually "string-array".
+ * @param name An array of one string, used to return the name attribute of the list's tag.
+ * @return Returns a newly generated String[].
+ */
+ public static String[] readThisStringArrayXml(XmlPullParser parser, String endTag,
+ String[] name) throws XmlPullParserException, java.io.IOException {
+
+ parser.next();
+
+ List<String> array = new ArrayList<>();
+
+ int eventType = parser.getEventType();
+ do {
+ if (eventType == XmlPullParser.START_TAG) {
+ if (parser.getName().equals("item")) {
+ try {
+ array.add(parser.getAttributeValue(null, "value"));
+ } catch (NullPointerException e) {
+ throw new XmlPullParserException("Need value attribute in item");
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException("Not a number in value attribute in item");
+ }
+ } else {
+ throw new XmlPullParserException("Expected item tag at: " + parser.getName());
+ }
+ } else if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals(endTag)) {
+ return array.toArray(new String[0]);
+ } else if (parser.getName().equals("item")) {
+
+ } else {
+ throw new XmlPullParserException("Expected " + endTag + " end tag at: " +
+ parser.getName());
+ }
+ }
+ eventType = parser.next();
+ } while (eventType != XmlPullParser.END_DOCUMENT);
+
+ throw new XmlPullParserException("Document ended before " + endTag + " end tag");
+ }
+
+ private static Object readThisValueXml(XmlPullParser parser, String[] name,
+ ReadMapCallback callback, boolean arrayMap)
+ throws XmlPullParserException, java.io.IOException {
+ final String valueName = parser.getAttributeValue(null, "name");
+ final String tagName = parser.getName();
+
+ Object res;
+
+ if (tagName.equals("null")) {
+ res = null;
+ } else if (tagName.equals("string")) {
+ String value = "";
+ int eventType;
+ while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals("string")) {
+ name[0] = valueName;
+ return value;
+ }
+ throw new XmlPullParserException(
+ "Unexpected end tag in <string>: " + parser.getName());
+ } else if (eventType == XmlPullParser.TEXT) {
+ value += parser.getText();
+ } else if (eventType == XmlPullParser.START_TAG) {
+ throw new XmlPullParserException(
+ "Unexpected start tag in <string>: " + parser.getName());
+ }
+ }
+ throw new XmlPullParserException(
+ "Unexpected end of document in <string>");
+ } else if ((res = readThisPrimitiveValueXml(parser, tagName)) != null) {
+ // all work already done by readThisPrimitiveValueXml
+ } else if (tagName.equals("string-array")) {
+ res = readThisStringArrayXml(parser, "string-array", name);
+ name[0] = valueName;
+ return res;
+ } else if (tagName.equals("list")) {
+ parser.next();
+ res = readThisListXml(parser, "list", name, callback, arrayMap);
+ name[0] = valueName;
+ return res;
+ } else if (callback != null) {
+ res = callback.readThisUnknownObjectXml(parser, tagName);
+ name[0] = valueName;
+ return res;
+ } else {
+ throw new XmlPullParserException("Unknown tag: " + tagName);
+ }
+
+ // Skip through to end tag.
+ int eventType;
+ while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
+ if (eventType == XmlPullParser.END_TAG) {
+ if (parser.getName().equals(tagName)) {
+ name[0] = valueName;
+ return res;
+ }
+ throw new XmlPullParserException(
+ "Unexpected end tag in <" + tagName + ">: " + parser.getName());
+ } else if (eventType == XmlPullParser.TEXT) {
+ throw new XmlPullParserException(
+ "Unexpected text in <" + tagName + ">: " + parser.getName());
+ } else if (eventType == XmlPullParser.START_TAG) {
+ throw new XmlPullParserException(
+ "Unexpected start tag in <" + tagName + ">: " + parser.getName());
+ }
+ }
+ throw new XmlPullParserException(
+ "Unexpected end of document in <" + tagName + ">");
+ }
+
+ private static final Object readThisPrimitiveValueXml(XmlPullParser parser, String tagName)
+ throws XmlPullParserException, java.io.IOException {
+ try {
+ if (tagName.equals("int")) {
+ return Integer.parseInt(parser.getAttributeValue(null, "value"));
+ } else if (tagName.equals("long")) {
+ return Long.valueOf(parser.getAttributeValue(null, "value"));
+ } else if (tagName.equals("float")) {
+ return Float.valueOf(parser.getAttributeValue(null, "value"));
+ } else if (tagName.equals("double")) {
+ return Double.valueOf(parser.getAttributeValue(null, "value"));
+ } else if (tagName.equals("boolean")) {
+ return Boolean.valueOf(parser.getAttributeValue(null, "value"));
+ } else {
+ return null;
+ }
+ } catch (NullPointerException e) {
+ throw new XmlPullParserException("Need value attribute in <" + tagName + ">");
+ } catch (NumberFormatException e) {
+ throw new XmlPullParserException(
+ "Not a number in value attribute in <" + tagName + ">");
+ }
+ }
+
+ public interface ReadMapCallback {
+
+ /**
+ * Called from readThisMapXml when a START_TAG is not recognized. The input stream is
+ * positioned within the start tag so that attributes can be read using in.getAttribute.
+ *
+ * @param in the XML input stream
+ * @param tag the START_TAG that was not recognized.
+ * @return the Object parsed from the stream which will be put into the map.
+ * @throws XmlPullParserException if the START_TAG is not recognized.
+ * @throws IOException on XmlPullParser serialization errors.
+ */
+ Object readThisUnknownObjectXml(XmlPullParser in, String tag)
+ throws XmlPullParserException, IOException;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/services/telephony/CdmaConferenceController.java b/src/com/android/services/telephony/CdmaConferenceController.java
index 9aee300..0a7c18b 100644
--- a/src/com/android/services/telephony/CdmaConferenceController.java
+++ b/src/com/android/services/telephony/CdmaConferenceController.java
@@ -90,6 +90,12 @@
private CdmaConference mConference;
void add(final CdmaConnection connection) {
+ if (mCdmaConnections.contains(connection)) {
+ // Adding a duplicate realistically shouldn't happen.
+ Log.w(this, "add - connection already tracked; connection=%s", connection);
+ return;
+ }
+
if (!mCdmaConnections.isEmpty() && connection.isOutgoing()) {
// There already exists a connection, so this will probably result in a conference once
// it is added. For outgoing connections which are added while another connection
@@ -127,7 +133,14 @@
recalculateConference();
}
- private void remove(CdmaConnection connection) {
+ void remove(CdmaConnection connection) {
+ if (!mCdmaConnections.contains(connection)) {
+ // Debug only since TelephonyConnectionService tries to clean up the connections tracked
+ // when the original connection changes. It does this proactively.
+ Log.d(this, "remove - connection not tracked; connection=%s", connection);
+ return;
+ }
+
connection.removeConnectionListener(mConnectionListener);
mCdmaConnections.remove(connection);
recalculateConference();
diff --git a/src/com/android/services/telephony/CdmaConnection.java b/src/com/android/services/telephony/CdmaConnection.java
index bfb0d23..8020996 100644
--- a/src/com/android/services/telephony/CdmaConnection.java
+++ b/src/com/android/services/telephony/CdmaConnection.java
@@ -26,6 +26,7 @@
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
+import com.android.internal.telephony.imsphone.ImsPhoneConnection;
import com.android.internal.telephony.Phone;
import com.android.phone.settings.SettingsConstants;
@@ -84,7 +85,9 @@
mAllowMute = allowMute;
mIsOutgoing = isOutgoing;
mIsCallWaiting = connection != null && connection.getState() == Call.State.WAITING;
- if (mIsCallWaiting) {
+ boolean isImsCall = getOriginalConnection() instanceof ImsPhoneConnection;
+ // Start call waiting timer for CDMA waiting call.
+ if (mIsCallWaiting && !isImsCall) {
startCallWaitingTimer();
}
}
diff --git a/src/com/android/services/telephony/ConferenceParticipantConnection.java b/src/com/android/services/telephony/ConferenceParticipantConnection.java
index 78f9ca3..ed7ad44 100644
--- a/src/com/android/services/telephony/ConferenceParticipantConnection.java
+++ b/src/com/android/services/telephony/ConferenceParticipantConnection.java
@@ -178,8 +178,19 @@
if (TextUtils.isEmpty(number)) {
return PhoneConstants.PRESENTATION_RESTRICTED;
}
+ // Per RFC3261, the host name portion can also potentially include extra information:
+ // E.g. sip:anonymous1@anonymous.invalid;legid=1
+ // In this case, hostName will be anonymous.invalid and there is an extra parameter for
+ // legid=1.
+ // Parameters are optional, and the address (e.g. test@test.com) will always be the first
+ // part, with any parameters coming afterwards.
+ String hostParts[] = number.split("[;]");
+ String addressPart = hostParts[0];
- String numberParts[] = number.split("[@]");
+ // Get the number portion from the address part.
+ // This will typically be formatted similar to: 6505551212@test.com
+ String numberParts[] = addressPart.split("[@]");
+
// If we can't parse the host name out of the URI, then there is probably other data
// present, and is likely a valid SIP URI.
if (numberParts.length != 2) {
@@ -292,6 +303,10 @@
sb.append(System.identityHashCode(this));
sb.append(" endPoint:");
sb.append(Log.pii(mEndpoint));
+ sb.append(" address:");
+ sb.append(Log.pii(getAddress()));
+ sb.append(" addressPresentation:");
+ sb.append(getAddressPresentation());
sb.append(" parentConnection:");
sb.append(Log.pii(mParentConnection.getAddress()));
sb.append(" state:");
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index d7db345..6eb4a4e 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -125,6 +125,10 @@
case android.telephony.DisconnectCause.DIAL_MODIFIED_TO_SS:
case android.telephony.DisconnectCause.DIAL_MODIFIED_TO_DIAL:
case android.telephony.DisconnectCause.ERROR_UNSPECIFIED:
+ case android.telephony.DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED:
+ case android.telephony.DisconnectCause.DATA_DISABLED:
+ case android.telephony.DisconnectCause.DATA_LIMIT_REACHED:
+ case android.telephony.DisconnectCause.DIALED_ON_WRONG_SLOT:
return DisconnectCause.ERROR;
case android.telephony.DisconnectCause.DIALED_MMI:
@@ -137,6 +141,12 @@
case android.telephony.DisconnectCause.NOT_DISCONNECTED:
return DisconnectCause.UNKNOWN;
+ case android.telephony.DisconnectCause.CALL_PULLED:
+ return DisconnectCause.CALL_PULLED;
+
+ case android.telephony.DisconnectCause.ANSWERED_ELSEWHERE:
+ return DisconnectCause.ANSWERED_ELSEWHERE;
+
default:
Log.w("DisconnectCauseUtil.toTelecomDisconnectCauseCode",
"Unrecognized Telephony DisconnectCause "
@@ -214,6 +224,22 @@
resourceId = R.string.callFailed_unobtainable_number;
break;
+ case android.telephony.DisconnectCause.CALL_PULLED:
+ resourceId = R.string.callEnded_pulled;
+ break;
+
+ case android.telephony.DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED:
+ resourceId = R.string.callFailed_maximum_reached;
+ break;
+
+ case android.telephony.DisconnectCause.DATA_DISABLED:
+ resourceId = R.string.callFailed_data_disabled;
+ break;
+
+ case android.telephony.DisconnectCause.DATA_LIMIT_REACHED:
+ resourceId = R.string.callFailed_data_limit_reached;
+ break;
+
default:
break;
}
@@ -281,7 +307,9 @@
// TODO: Offer the option to turn the radio on, and automatically retry the call
// once network registration is complete.
- if (ImsUtil.isWfcModeWifiOnly(context)) {
+ if (ImsUtil.shouldPromoteWfc(context)) {
+ resourceId = R.string.incall_error_promote_wfc;
+ } else if (ImsUtil.isWfcModeWifiOnly(context)) {
resourceId = R.string.incall_error_wfc_only_no_wireless_network;
} else if (ImsUtil.isWfcEnabled(context)) {
resourceId = R.string.incall_error_power_off_wfc;
@@ -303,7 +331,9 @@
case android.telephony.DisconnectCause.OUT_OF_SERVICE:
// No network connection.
- if (ImsUtil.isWfcModeWifiOnly(context)) {
+ if (ImsUtil.shouldPromoteWfc(context)) {
+ resourceId = R.string.incall_error_promote_wfc;
+ } else if (ImsUtil.isWfcModeWifiOnly(context)) {
resourceId = R.string.incall_error_wfc_only_no_wireless_network;
} else if (ImsUtil.isWfcEnabled(context)) {
resourceId = R.string.incall_error_out_of_service_wfc;
@@ -329,11 +359,28 @@
resourceId = R.string.callFailed_video_call_tty_enabled;
break;
+ case android.telephony.DisconnectCause.CALL_PULLED:
+ resourceId = R.string.callEnded_pulled;
+ break;
+
+ case android.telephony.DisconnectCause.MAXIMUM_NUMBER_OF_CALLS_REACHED:
+ resourceId = R.string.callFailed_maximum_reached;
+
case android.telephony.DisconnectCause.OUTGOING_CANCELED:
// We don't want to show any dialog for the canceled case since the call was
// either canceled by the user explicitly (end-call button pushed immediately)
// or some other app canceled the call and immediately issued a new CALL to
// replace it.
+ break;
+
+ case android.telephony.DisconnectCause.DATA_DISABLED:
+ resourceId = R.string.callFailed_data_disabled;
+ break;
+
+ case android.telephony.DisconnectCause.DATA_LIMIT_REACHED:
+ resourceId = R.string.callFailed_data_limit_reached_description;
+ break;
+
default:
break;
}
diff --git a/src/com/android/services/telephony/EmergencyCallHelper.java b/src/com/android/services/telephony/EmergencyCallHelper.java
index c64a649..295f4f7 100644
--- a/src/com/android/services/telephony/EmergencyCallHelper.java
+++ b/src/com/android/services/telephony/EmergencyCallHelper.java
@@ -17,18 +17,17 @@
package com.android.services.telephony;
import android.content.Context;
-
import android.content.Intent;
-import android.os.AsyncResult;
-import android.os.Handler;
-import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
-import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
-import com.android.internal.os.SomeArgs;
import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneFactory;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
/**
* Helper class that implements special behavior related to emergency calls. Specifically, this
@@ -36,220 +35,75 @@
* (i.e. the device is in airplane mode), by forcibly turning the radio back on, waiting for it to
* come up, and then retrying the emergency call.
*/
-public class EmergencyCallHelper {
-
- /**
- * Receives the result of the EmergencyCallHelper's attempt to turn on the radio.
- */
- interface Callback {
- void onComplete(boolean isRadioReady);
- }
-
- // Number of times to retry the call, and time between retry attempts.
- public static final int MAX_NUM_RETRIES = 5;
- public static final long TIME_BETWEEN_RETRIES_MILLIS = 5000; // msec
-
- // Handler message codes; see handleMessage()
- private static final int MSG_START_SEQUENCE = 1;
- private static final int MSG_SERVICE_STATE_CHANGED = 2;
- private static final int MSG_RETRY_TIMEOUT = 3;
+public class EmergencyCallHelper implements EmergencyCallStateListener.Callback {
private final Context mContext;
+ private EmergencyCallStateListener.Callback mCallback;
+ private List<EmergencyCallStateListener> mListeners;
+ private List<EmergencyCallStateListener> mInProgressListeners;
+ private boolean mIsEmergencyCallingEnabled;
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_START_SEQUENCE:
- SomeArgs args = (SomeArgs) msg.obj;
- Phone phone = (Phone) args.arg1;
- EmergencyCallHelper.Callback callback =
- (EmergencyCallHelper.Callback) args.arg2;
- args.recycle();
-
- startSequenceInternal(phone, callback);
- break;
- case MSG_SERVICE_STATE_CHANGED:
- onServiceStateChanged((ServiceState) ((AsyncResult) msg.obj).result);
- break;
- case MSG_RETRY_TIMEOUT:
- onRetryTimeout();
- break;
- default:
- Log.wtf(this, "handleMessage: unexpected message: %d.", msg.what);
- break;
- }
- }
- };
-
-
- private Callback mCallback; // The callback to notify upon completion.
- private Phone mPhone; // The phone that will attempt to place the call.
- private int mNumRetriesSoFar;
public EmergencyCallHelper(Context context) {
- Log.d(this, "EmergencyCallHelper constructor.");
mContext = context;
+ mInProgressListeners = new ArrayList<>(2);
}
+ private void setupListeners() {
+ if (mListeners != null) {
+ return;
+ }
+ mListeners = new ArrayList<>(2);
+ for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+ mListeners.add(new EmergencyCallStateListener());
+ }
+ }
/**
* Starts the "turn on radio" sequence. This is the (single) external API of the
* EmergencyCallHelper class.
*
* This method kicks off the following sequence:
- * - Power on the radio.
+ * - Power on the radio for each Phone
* - Listen for the service state change event telling us the radio has come up.
- * - Retry if we've gone {@link #TIME_BETWEEN_RETRIES_MILLIS} without any response from the
- * radio.
+ * - Retry if we've gone a significant amount of time without any response from the radio.
* - Finally, clean up any leftover state.
*
* This method is safe to call from any thread, since it simply posts a message to the
* EmergencyCallHelper's handler (thus ensuring that the rest of the sequence is entirely
- * serialized, and runs only on the handler thread.)
+ * serialized, and runs on the main looper.)
*/
- public void startTurnOnRadioSequence(Phone phone, Callback callback) {
- Log.d(this, "startTurnOnRadioSequence");
-
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = phone;
- args.arg2 = callback;
- mHandler.obtainMessage(MSG_START_SEQUENCE, args).sendToTarget();
- }
-
- /**
- * Actual implementation of startTurnOnRadioSequence(), guaranteed to run on the handler thread.
- * @see #startTurnOnRadioSequence
- */
- private void startSequenceInternal(Phone phone, Callback callback) {
- Log.d(this, "startSequenceInternal()");
-
- // First of all, clean up any state left over from a prior emergency call sequence. This
- // ensures that we'll behave sanely if another startTurnOnRadioSequence() comes in while
- // we're already in the middle of the sequence.
- cleanup();
-
- mPhone = phone;
+ public void enableEmergencyCalling(EmergencyCallStateListener.Callback callback) {
+ setupListeners();
mCallback = callback;
+ mInProgressListeners.clear();
+ mIsEmergencyCallingEnabled = false;
+ for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+ Phone phone = PhoneFactory.getPhone(i);
+ if (phone == null)
+ continue;
-
- // No need to check the current service state here, since the only reason to invoke this
- // method in the first place is if the radio is powered-off. So just go ahead and turn the
- // radio on.
-
- powerOnRadio(); // We'll get an onServiceStateChanged() callback
- // when the radio successfully comes up.
-
- // Next step: when the SERVICE_STATE_CHANGED event comes in, we'll retry the call; see
- // onServiceStateChanged(). But also, just in case, start a timer to make sure we'll retry
- // the call even if the SERVICE_STATE_CHANGED event never comes in for some reason.
- startRetryTimer();
- }
-
- /**
- * Handles the SERVICE_STATE_CHANGED event. Normally this event tells us that the radio has
- * finally come up. In that case, it's now safe to actually place the emergency call.
- */
- private void onServiceStateChanged(ServiceState state) {
- Log.d(this, "onServiceStateChanged(), new state = %s.", state);
-
- // Possible service states:
- // - STATE_IN_SERVICE // Normal operation
- // - STATE_OUT_OF_SERVICE // Still searching for an operator to register to,
- // // or no radio signal
- // - STATE_EMERGENCY_ONLY // Phone is locked; only emergency numbers are allowed
- // - STATE_POWER_OFF // Radio is explicitly powered off (airplane mode)
-
- if (isOkToCall(state.getState(), mPhone.getState())) {
- // Woo hoo! It's OK to actually place the call.
- Log.d(this, "onServiceStateChanged: ok to call!");
-
- onComplete(true);
- cleanup();
- } else {
- // The service state changed, but we're still not ready to call yet. (This probably was
- // the transition from STATE_POWER_OFF to STATE_OUT_OF_SERVICE, which happens
- // immediately after powering-on the radio.)
- //
- // So just keep waiting; we'll probably get to either STATE_IN_SERVICE or
- // STATE_EMERGENCY_ONLY very shortly. (Or even if that doesn't happen, we'll at least do
- // another retry when the RETRY_TIMEOUT event fires.)
- Log.d(this, "onServiceStateChanged: not ready to call yet, keep waiting.");
+ mInProgressListeners.add(mListeners.get(i));
+ mListeners.get(i).waitForRadioOn(phone, this);
}
+
+ powerOnRadio();
}
-
- private boolean isOkToCall(int serviceState, PhoneConstants.State phoneState) {
- // Once we reach either STATE_IN_SERVICE or STATE_EMERGENCY_ONLY, it's finally OK to place
- // the emergency call.
- return ((phoneState == PhoneConstants.State.OFFHOOK)
- || (serviceState == ServiceState.STATE_IN_SERVICE)
- || (serviceState == ServiceState.STATE_EMERGENCY_ONLY)) ||
-
- // Allow STATE_OUT_OF_SERVICE if we are at the max number of retries.
- (mNumRetriesSoFar == MAX_NUM_RETRIES &&
- serviceState == ServiceState.STATE_OUT_OF_SERVICE);
- }
-
/**
- * Handles the retry timer expiring.
- */
- private void onRetryTimeout() {
- PhoneConstants.State phoneState = mPhone.getState();
- int serviceState = mPhone.getServiceState().getState();
- Log.d(this, "onRetryTimeout(): phone state = %s, service state = %d, retries = %d.",
- phoneState, serviceState, mNumRetriesSoFar);
-
- // - If we're actually in a call, we've succeeded.
- // - Otherwise, if the radio is now on, that means we successfully got out of airplane mode
- // but somehow didn't get the service state change event. In that case, try to place the
- // call.
- // - If the radio is still powered off, try powering it on again.
-
- if (isOkToCall(serviceState, phoneState)) {
- Log.d(this, "onRetryTimeout: Radio is on. Cleaning up.");
-
- // Woo hoo -- we successfully got out of airplane mode.
- onComplete(true);
- cleanup();
- } else {
- // Uh oh; we've waited the full TIME_BETWEEN_RETRIES_MILLIS and the radio is still not
- // powered-on. Try again.
-
- mNumRetriesSoFar++;
- Log.d(this, "mNumRetriesSoFar is now " + mNumRetriesSoFar);
-
- if (mNumRetriesSoFar > MAX_NUM_RETRIES) {
- Log.w(this, "Hit MAX_NUM_RETRIES; giving up.");
- cleanup();
- } else {
- Log.d(this, "Trying (again) to turn on the radio.");
- powerOnRadio(); // Again, we'll (hopefully) get an onServiceStateChanged() callback
- // when the radio successfully comes up.
- startRetryTimer();
- }
- }
- }
-
- /**
- * Attempt to power on the radio (i.e. take the device out of airplane mode.)
- * Additionally, start listening for service state changes; we'll eventually get an
- * onServiceStateChanged() callback when the radio successfully comes up.
+ * Attempt to power on the radio (i.e. take the device out of airplane mode). We'll eventually
+ * get an onServiceStateChanged() callback when the radio successfully comes up.
*/
private void powerOnRadio() {
Log.d(this, "powerOnRadio().");
- // We're about to turn on the radio, so arrange to be notified when the sequence is
- // complete.
- registerForServiceStateChanged();
-
// If airplane mode is on, we turn it off the same way that the Settings activity turns it
// off.
if (Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0) > 0) {
+ Settings.Global.AIRPLANE_MODE_ON, 0) > 0) {
Log.d(this, "==> Turning off airplane mode.");
// Change the system setting
Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.AIRPLANE_MODE_ON, 0);
+ Settings.Global.AIRPLANE_MODE_ON, 0);
// Post the broadcast intend for change in airplane mode
// TODO: We really should not be in charge of sending this broadcast.
@@ -258,77 +112,19 @@
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", false);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- } else {
- // Otherwise, for some strange reason the radio is off (even though the Settings
- // database doesn't think we're in airplane mode.) In this case just turn the radio
- // back on.
- Log.d(this, "==> (Apparently) not in airplane mode; manually powering radio on.");
- mPhone.setRadioPower(true);
}
}
/**
- * Clean up when done with the whole sequence: either after successfully turning on the radio,
- * or after bailing out because of too many failures.
- *
- * The exact cleanup steps are:
- * - Notify callback if we still hadn't sent it a response.
- * - Double-check that we're not still registered for any telephony events
- * - Clean up any extraneous handler messages (like retry timeouts) still in the queue
- *
- * Basically this method guarantees that there will be no more activity from the
- * EmergencyCallHelper until someone kicks off the whole sequence again with another call to
- * {@link #startTurnOnRadioSequence}
- *
- * TODO: Do the work for the comment below:
- * Note we don't call this method simply after a successful call to placeCall(), since it's
- * still possible the call will disconnect very quickly with an OUT_OF_SERVICE error.
+ * This method is called from multiple Listeners on the Main Looper.
+ * Synchronization is not necessary.
*/
- private void cleanup() {
- Log.d(this, "cleanup()");
-
- // This will send a failure call back if callback has yet to be invoked. If the callback
- // was already invoked, it's a no-op.
- onComplete(false);
-
- unregisterForServiceStateChanged();
- cancelRetryTimer();
-
- // Used for unregisterForServiceStateChanged() so we null it out here instead.
- mPhone = null;
- mNumRetriesSoFar = 0;
- }
-
- private void startRetryTimer() {
- cancelRetryTimer();
- mHandler.sendEmptyMessageDelayed(MSG_RETRY_TIMEOUT, TIME_BETWEEN_RETRIES_MILLIS);
- }
-
- private void cancelRetryTimer() {
- mHandler.removeMessages(MSG_RETRY_TIMEOUT);
- }
-
- private void registerForServiceStateChanged() {
- // Unregister first, just to make sure we never register ourselves twice. (We need this
- // because Phone.registerForServiceStateChanged() does not prevent multiple registration of
- // the same handler.)
- unregisterForServiceStateChanged();
- mPhone.registerForServiceStateChanged(mHandler, MSG_SERVICE_STATE_CHANGED, null);
- }
-
- private void unregisterForServiceStateChanged() {
- // This method is safe to call even if we haven't set mPhone yet.
- if (mPhone != null) {
- mPhone.unregisterForServiceStateChanged(mHandler); // Safe even if unnecessary
- }
- mHandler.removeMessages(MSG_SERVICE_STATE_CHANGED); // Clean up any pending messages too
- }
-
- private void onComplete(boolean isRadioReady) {
- if (mCallback != null) {
- Callback tempCallback = mCallback;
- mCallback = null;
- tempCallback.onComplete(isRadioReady);
+ @Override
+ public void onComplete(EmergencyCallStateListener listener, boolean isRadioReady) {
+ mIsEmergencyCallingEnabled |= isRadioReady;
+ mInProgressListeners.remove(listener);
+ if (mCallback != null && mInProgressListeners.isEmpty()) {
+ mCallback.onComplete(null, mIsEmergencyCallingEnabled);
}
}
}
diff --git a/src/com/android/services/telephony/EmergencyCallStateListener.java b/src/com/android/services/telephony/EmergencyCallStateListener.java
new file mode 100644
index 0000000..036872d
--- /dev/null
+++ b/src/com/android/services/telephony/EmergencyCallStateListener.java
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2016 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 android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.telephony.ServiceState;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.SomeArgs;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.SubscriptionController;
+
+/**
+ * Helper class that listens to a Phone's radio state and sends a callback when the radio state of
+ * that Phone is either "in service" or "emergency calls only."
+ */
+public class EmergencyCallStateListener {
+
+ /**
+ * Receives the result of the EmergencyCallStateListener's attempt to turn on the radio.
+ */
+ interface Callback {
+ void onComplete(EmergencyCallStateListener listener, boolean isRadioReady);
+ }
+
+ // Number of times to retry the call, and time between retry attempts.
+ private static int MAX_NUM_RETRIES = 5;
+ private static long TIME_BETWEEN_RETRIES_MILLIS = 5000; // msec
+
+ // Handler message codes; see handleMessage()
+ @VisibleForTesting
+ public static final int MSG_START_SEQUENCE = 1;
+ @VisibleForTesting
+ public static final int MSG_SERVICE_STATE_CHANGED = 2;
+ @VisibleForTesting
+ public static final int MSG_RETRY_TIMEOUT = 3;
+
+ private final Handler mHandler = new Handler(Looper.getMainLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_START_SEQUENCE:
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ Phone phone = (Phone) args.arg1;
+ EmergencyCallStateListener.Callback callback =
+ (EmergencyCallStateListener.Callback) args.arg2;
+ startSequenceInternal(phone, callback);
+ } finally {
+ args.recycle();
+ }
+ break;
+ case MSG_SERVICE_STATE_CHANGED:
+ onServiceStateChanged((ServiceState) ((AsyncResult) msg.obj).result);
+ break;
+ case MSG_RETRY_TIMEOUT:
+ onRetryTimeout();
+ break;
+ default:
+ Log.wtf(this, "handleMessage: unexpected message: %d.", msg.what);
+ break;
+ }
+ }
+ };
+
+
+ private Callback mCallback; // The callback to notify upon completion.
+ private Phone mPhone; // The phone that will attempt to place the call.
+ private int mNumRetriesSoFar;
+
+ /**
+ * Starts the "wait for radio" sequence. This is the (single) external API of the
+ * EmergencyCallStateListener class.
+ *
+ * This method kicks off the following sequence:
+ * - Listen for the service state change event telling us the radio has come up.
+ * - Retry if we've gone {@link #TIME_BETWEEN_RETRIES_MILLIS} without any response from the
+ * radio.
+ * - Finally, clean up any leftover state.
+ *
+ * This method is safe to call from any thread, since it simply posts a message to the
+ * EmergencyCallStateListener's handler (thus ensuring that the rest of the sequence is entirely
+ * serialized, and runs only on the handler thread.)
+ */
+ public void waitForRadioOn(Phone phone, Callback callback) {
+ Log.d(this, "waitForRadioOn: Phone " + phone.getPhoneId());
+
+ if (mPhone != null) {
+ // If there already is an ongoing request, ignore the new one!
+ return;
+ }
+
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = phone;
+ args.arg2 = callback;
+ mHandler.obtainMessage(MSG_START_SEQUENCE, args).sendToTarget();
+ }
+
+ /**
+ * Actual implementation of waitForRadioOn(), guaranteed to run on the handler thread.
+ *
+ * @see #waitForRadioOn
+ */
+ private void startSequenceInternal(Phone phone, Callback callback) {
+ Log.d(this, "startSequenceInternal: Phone " + phone.getPhoneId());
+
+ // First of all, clean up any state left over from a prior emergency call sequence. This
+ // ensures that we'll behave sanely if another startTurnOnRadioSequence() comes in while
+ // we're already in the middle of the sequence.
+ cleanup();
+
+ mPhone = phone;
+ mCallback = callback;
+
+ registerForServiceStateChanged();
+ // Next step: when the SERVICE_STATE_CHANGED event comes in, we'll retry the call; see
+ // onServiceStateChanged(). But also, just in case, start a timer to make sure we'll retry
+ // the call even if the SERVICE_STATE_CHANGED event never comes in for some reason.
+ startRetryTimer();
+ }
+
+ /**
+ * Handles the SERVICE_STATE_CHANGED event. Normally this event tells us that the radio has
+ * finally come up. In that case, it's now safe to actually place the emergency call.
+ */
+ private void onServiceStateChanged(ServiceState state) {
+ Log.d(this, "onServiceStateChanged(), new state = %s, Phone = %s", state,
+ mPhone.getPhoneId());
+
+ // Possible service states:
+ // - STATE_IN_SERVICE // Normal operation
+ // - STATE_OUT_OF_SERVICE // Still searching for an operator to register to,
+ // // or no radio signal
+ // - STATE_EMERGENCY_ONLY // Phone is locked; only emergency numbers are allowed
+ // - STATE_POWER_OFF // Radio is explicitly powered off (airplane mode)
+
+ if (isOkToCall(state.getState())) {
+ // Woo hoo! It's OK to actually place the call.
+ Log.d(this, "onServiceStateChanged: ok to call!");
+
+ onComplete(true);
+ cleanup();
+ } else {
+ // The service state changed, but we're still not ready to call yet.
+ Log.d(this, "onServiceStateChanged: not ready to call yet, keep waiting.");
+ }
+ }
+
+ /**
+ * We currently only look to make sure that the radio is on before dialing. We should be able to
+ * make emergency calls at any time after the radio has been powered on and isn't in the
+ * UNAVAILABLE state, even if it is reporting the OUT_OF_SERVICE state.
+ */
+ private boolean isOkToCall(int serviceState) {
+ return (mPhone.getState() == PhoneConstants.State.OFFHOOK) ||
+ mPhone.getServiceStateTracker().isRadioOn();
+ }
+
+ /**
+ * Handles the retry timer expiring.
+ */
+ private void onRetryTimeout() {
+ int serviceState = mPhone.getServiceState().getState();
+ Log.d(this, "onRetryTimeout(): phone state = %s, service state = %d, retries = %d.",
+ mPhone.getState(), serviceState, mNumRetriesSoFar);
+
+ // - If we're actually in a call, we've succeeded.
+ // - Otherwise, if the radio is now on, that means we successfully got out of airplane mode
+ // but somehow didn't get the service state change event. In that case, try to place the
+ // call.
+ // - If the radio is still powered off, try powering it on again.
+
+ if (isOkToCall(serviceState)) {
+ Log.d(this, "onRetryTimeout: Radio is on. Cleaning up.");
+
+ // Woo hoo -- we successfully got out of airplane mode.
+ onComplete(true);
+ cleanup();
+ } else {
+ // Uh oh; we've waited the full TIME_BETWEEN_RETRIES_MILLIS and the radio is still not
+ // powered-on. Try again.
+
+ mNumRetriesSoFar++;
+ Log.d(this, "mNumRetriesSoFar is now " + mNumRetriesSoFar);
+
+ if (mNumRetriesSoFar > MAX_NUM_RETRIES) {
+ Log.w(this, "Hit MAX_NUM_RETRIES; giving up.");
+ cleanup();
+ } else {
+ Log.d(this, "Trying (again) to turn on the radio.");
+ mPhone.setRadioPower(true);
+ startRetryTimer();
+ }
+ }
+ }
+
+ /**
+ * Clean up when done with the whole sequence: either after successfully turning on the radio,
+ * or after bailing out because of too many failures.
+ *
+ * The exact cleanup steps are:
+ * - Notify callback if we still hadn't sent it a response.
+ * - Double-check that we're not still registered for any telephony events
+ * - Clean up any extraneous handler messages (like retry timeouts) still in the queue
+ *
+ * Basically this method guarantees that there will be no more activity from the
+ * EmergencyCallStateListener until someone kicks off the whole sequence again with another call
+ * to {@link #waitForRadioOn}
+ *
+ * TODO: Do the work for the comment below:
+ * Note we don't call this method simply after a successful call to placeCall(), since it's
+ * still possible the call will disconnect very quickly with an OUT_OF_SERVICE error.
+ */
+ private void cleanup() {
+ Log.d(this, "cleanup()");
+
+ // This will send a failure call back if callback has yet to be invoked. If the callback
+ // was already invoked, it's a no-op.
+ onComplete(false);
+
+ unregisterForServiceStateChanged();
+ cancelRetryTimer();
+
+ // Used for unregisterForServiceStateChanged() so we null it out here instead.
+ mPhone = null;
+ mNumRetriesSoFar = 0;
+ }
+
+ private void startRetryTimer() {
+ cancelRetryTimer();
+ mHandler.sendEmptyMessageDelayed(MSG_RETRY_TIMEOUT, TIME_BETWEEN_RETRIES_MILLIS);
+ }
+
+ private void cancelRetryTimer() {
+ mHandler.removeMessages(MSG_RETRY_TIMEOUT);
+ }
+
+ private void registerForServiceStateChanged() {
+ // Unregister first, just to make sure we never register ourselves twice. (We need this
+ // because Phone.registerForServiceStateChanged() does not prevent multiple registration of
+ // the same handler.)
+ unregisterForServiceStateChanged();
+ mPhone.registerForServiceStateChanged(mHandler, MSG_SERVICE_STATE_CHANGED, null);
+ }
+
+ private void unregisterForServiceStateChanged() {
+ // This method is safe to call even if we haven't set mPhone yet.
+ if (mPhone != null) {
+ mPhone.unregisterForServiceStateChanged(mHandler); // Safe even if unnecessary
+ }
+ mHandler.removeMessages(MSG_SERVICE_STATE_CHANGED); // Clean up any pending messages too
+ }
+
+ private void onComplete(boolean isRadioReady) {
+ if (mCallback != null) {
+ Callback tempCallback = mCallback;
+ mCallback = null;
+ tempCallback.onComplete(this, isRadioReady);
+ }
+ }
+
+ @VisibleForTesting
+ public Handler getHandler() {
+ return mHandler;
+ }
+
+ @VisibleForTesting
+ public void setMaxNumRetries(int retries) {
+ MAX_NUM_RETRIES = retries;
+ }
+
+ @VisibleForTesting
+ public void setTimeBetweenRetriesMillis(long timeMs) {
+ TIME_BETWEEN_RETRIES_MILLIS = timeMs;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || !getClass().equals(o.getClass())) return false;
+
+ EmergencyCallStateListener that = (EmergencyCallStateListener) o;
+
+ if (mNumRetriesSoFar != that.mNumRetriesSoFar) {
+ return false;
+ }
+ if (mCallback != null ? !mCallback.equals(that.mCallback) : that.mCallback != null) {
+ return false;
+ }
+ return mPhone != null ? mPhone.equals(that.mPhone) : that.mPhone == null;
+
+ }
+}
diff --git a/src/com/android/services/telephony/GsmConnection.java b/src/com/android/services/telephony/GsmConnection.java
index dd47e8d..c480baa 100644
--- a/src/com/android/services/telephony/GsmConnection.java
+++ b/src/com/android/services/telephony/GsmConnection.java
@@ -57,15 +57,36 @@
}
@Override
+ protected int buildConnectionProperties() {
+ int properties = super.buildConnectionProperties();
+ // PROPERTY_IS_DOWNGRADED_CONFERENCE is permanent on GSM connections -- once it is set, it
+ // should be retained.
+ if ((getConnectionProperties() & PROPERTY_IS_DOWNGRADED_CONFERENCE) != 0) {
+ properties |= PROPERTY_IS_DOWNGRADED_CONFERENCE;
+ }
+ return properties;
+ }
+
+ @Override
protected int buildConnectionCapabilities() {
int capabilities = super.buildConnectionCapabilities();
capabilities |= CAPABILITY_MUTE;
+ // Overwrites TelephonyConnection.buildConnectionCapabilities() and resets the hold options
+ // because all GSM calls should hold, even if the carrier config option is set to not show
+ // hold for IMS calls.
if (!shouldTreatAsEmergencyCall()) {
capabilities |= CAPABILITY_SUPPORT_HOLD;
if (getState() == STATE_ACTIVE || getState() == STATE_HOLDING) {
capabilities |= CAPABILITY_HOLD;
}
}
+
+ // For GSM connections, CAPABILITY_CONFERENCE_HAS_NO_CHILDREN should be applied whenever
+ // PROPERTY_IS_DOWNGRADED_CONFERENCE is true.
+ if ((getConnectionProperties() & PROPERTY_IS_DOWNGRADED_CONFERENCE) != 0) {
+ capabilities |= CAPABILITY_CONFERENCE_HAS_NO_CHILDREN;
+ }
+
return capabilities;
}
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 69d57d7..e33c351 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -20,6 +20,7 @@
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.telecom.Conference;
import android.telecom.ConferenceParticipant;
import android.telecom.Connection.VideoProvider;
@@ -29,22 +30,25 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.StatusHints;
import android.telecom.VideoProfile;
+import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
+import android.util.Pair;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
+import com.android.phone.PhoneGlobals;
import com.android.phone.PhoneUtils;
import com.android.phone.R;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
/**
* Represents an IMS conference call.
@@ -175,7 +179,10 @@
Log.d(this, "onConnectionCapabilitiesChanged: Connection: %s," +
" connectionCapabilities: %s", c, connectionCapabilities);
int capabilites = ImsConference.this.getConnectionCapabilities();
- setConnectionCapabilities(applyHostCapabilities(capabilites, connectionCapabilities));
+ boolean isVideoConferencingSupported = mConferenceHost == null ? false :
+ mConferenceHost.isCarrierVideoConferencingSupported();
+ setConnectionCapabilities(applyHostCapabilities(capabilites, connectionCapabilities,
+ isVideoConferencingSupported));
}
@Override
@@ -223,14 +230,15 @@
/**
* The address of the conference host.
*/
- private Uri mConferenceHostAddress;
+ private Uri[] mConferenceHostAddress;
/**
- * The known conference participant connections. The HashMap is keyed by endpoint Uri.
+ * The known conference participant connections. The HashMap is keyed by a Pair containing
+ * the handle and endpoint Uris.
* Access to the hashmap is protected by the {@link #mUpdateSyncRoot}.
*/
- private final HashMap<Uri, ConferenceParticipantConnection>
- mConferenceParticipantConnections = new HashMap<Uri, ConferenceParticipantConnection>();
+ private final HashMap<Pair<Uri, Uri>, ConferenceParticipantConnection>
+ mConferenceParticipantConnections = new HashMap<>();
/**
* Sychronization root used to ensure that updates to the
@@ -274,10 +282,14 @@
mTelephonyConnectionService = telephonyConnectionService;
setConferenceHost(conferenceHost);
- int capabilities = Connection.CAPABILITY_SUPPORT_HOLD | Connection.CAPABILITY_HOLD |
- Connection.CAPABILITY_MUTE | Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN;
+ int capabilities = Connection.CAPABILITY_MUTE |
+ Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN;
+ if (canHoldImsCalls()) {
+ capabilities |= Connection.CAPABILITY_SUPPORT_HOLD | Connection.CAPABILITY_HOLD;
+ }
capabilities = applyHostCapabilities(capabilities,
- mConferenceHost.getConnectionCapabilities());
+ mConferenceHost.getConnectionCapabilities(),
+ mConferenceHost.isCarrierVideoConferencingSupported());
setConnectionCapabilities(capabilities);
}
@@ -287,24 +299,36 @@
*
* @param conferenceCapabilities The current conference capabilities.
* @param capabilities The new conference host capabilities.
+ * @param isVideoConferencingSupported Whether video conferencing is supported.
* @return The merged capabilities to be applied to the conference.
*/
- private int applyHostCapabilities(int conferenceCapabilities, int capabilities) {
+ private int applyHostCapabilities(int conferenceCapabilities, int capabilities,
+ boolean isVideoConferencingSupported) {
+
conferenceCapabilities = changeBitmask(conferenceCapabilities,
Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
can(capabilities, Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
- conferenceCapabilities = changeBitmask(conferenceCapabilities,
+ if (isVideoConferencingSupported) {
+ conferenceCapabilities = changeBitmask(conferenceCapabilities,
Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
can(capabilities, Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL));
-
- conferenceCapabilities = changeBitmask(conferenceCapabilities,
- Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO,
- can(capabilities, Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO));
-
- conferenceCapabilities = changeBitmask(conferenceCapabilities,
+ conferenceCapabilities = changeBitmask(conferenceCapabilities,
Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO,
can(capabilities, Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO));
+ } else {
+ // If video conferencing is not supported, explicitly turn off the remote video
+ // capability and the ability to upgrade to video.
+ Log.v(this, "applyHostCapabilities : video conferencing not supported");
+ conferenceCapabilities = changeBitmask(conferenceCapabilities,
+ Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, false);
+ conferenceCapabilities = changeBitmask(conferenceCapabilities,
+ Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO, false);
+ }
+
+ conferenceCapabilities = changeBitmask(conferenceCapabilities,
+ Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO,
+ can(capabilities, Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO));
return conferenceCapabilities;
}
@@ -565,14 +589,35 @@
Phone imsPhone = mConferenceHost.getPhone();
mConferenceHostPhoneAccountHandle =
PhoneUtils.makePstnPhoneAccountHandle(imsPhone.getDefaultPhone());
- mConferenceHostAddress = TelecomAccountRegistry.getInstance(mTelephonyConnectionService)
+ Uri hostAddress = TelecomAccountRegistry.getInstance(mTelephonyConnectionService)
.getAddress(mConferenceHostPhoneAccountHandle);
+
+ ArrayList<Uri> hostAddresses = new ArrayList<>();
+
+ // add address from TelecomAccountRegistry
+ if (hostAddress != null) {
+ hostAddresses.add(hostAddress);
+ }
+
+ // add addresses from phone
+ if (imsPhone.getCurrentSubscriberUris() != null) {
+ hostAddresses.addAll(
+ new ArrayList<>(Arrays.asList(imsPhone.getCurrentSubscriberUris())));
+ }
+
+ mConferenceHostAddress = new Uri[hostAddresses.size()];
+ mConferenceHostAddress = hostAddresses.toArray(mConferenceHostAddress);
}
mConferenceHost.addConnectionListener(mConferenceHostListener);
mConferenceHost.addTelephonyConnectionListener(mTelephonyConnectionListener);
- setState(mConferenceHost.getState());
+ setConnectionCapabilities(applyHostCapabilities(getConnectionCapabilities(),
+ mConferenceHost.getConnectionCapabilities(),
+ mConferenceHost.isCarrierVideoConferencingSupported()));
+ setConnectionProperties(applyHostProperties(getConnectionProperties(),
+ mConferenceHost.getConnectionProperties()));
+ setState(mConferenceHost.getState());
updateStatusHints();
}
@@ -589,6 +634,8 @@
return;
}
+ Log.i(this, "handleConferenceParticipantsUpdate: size=%d", participants.size());
+
// Perform the update in a synchronized manner. It is possible for the IMS framework to
// trigger two onConferenceParticipantsChanged callbacks in quick succession. If the first
// update adds new participants, and the second does something like update the status of one
@@ -597,17 +644,18 @@
boolean newParticipantsAdded = false;
boolean oldParticipantsRemoved = false;
ArrayList<ConferenceParticipant> newParticipants = new ArrayList<>(participants.size());
- HashSet<Uri> participantUserEntities = new HashSet<>(participants.size());
+ HashSet<Pair<Uri,Uri>> participantUserEntities = new HashSet<>(participants.size());
// Add any new participants and update existing.
for (ConferenceParticipant participant : participants) {
- Uri userEntity = participant.getHandle();
+ Pair<Uri,Uri> userEntity = new Pair<>(participant.getHandle(),
+ participant.getEndpoint());
participantUserEntities.add(userEntity);
if (!mConferenceParticipantConnections.containsKey(userEntity)) {
// Some carriers will also include the conference host in the CEP. We will
// filter that out here.
- if (!isParticipantHost(mConferenceHostAddress, userEntity)) {
+ if (!isParticipantHost(mConferenceHostAddress, participant.getHandle())) {
createConferenceParticipantConnection(parent, participant);
newParticipants.add(participant);
newParticipantsAdded = true;
@@ -615,6 +663,8 @@
} else {
ConferenceParticipantConnection connection =
mConferenceParticipantConnections.get(userEntity);
+ Log.i(this, "handleConferenceParticipantsUpdate: updateState, participant = %s",
+ participant);
connection.updateState(participant.getState());
}
}
@@ -624,17 +674,20 @@
// Set the state of the new participants at once and add to the conference
for (ConferenceParticipant newParticipant : newParticipants) {
ConferenceParticipantConnection connection =
- mConferenceParticipantConnections.get(newParticipant.getHandle());
+ mConferenceParticipantConnections.get(new Pair<>(
+ newParticipant.getHandle(),
+ newParticipant.getEndpoint()));
connection.updateState(newParticipant.getState());
}
}
// Finally, remove any participants from the conference that no longer exist in the
// conference event package data.
- Iterator<Map.Entry<Uri, ConferenceParticipantConnection>> entryIterator =
+ Iterator<Map.Entry<Pair<Uri, Uri>, ConferenceParticipantConnection>> entryIterator =
mConferenceParticipantConnections.entrySet().iterator();
while (entryIterator.hasNext()) {
- Map.Entry<Uri, ConferenceParticipantConnection> entry = entryIterator.next();
+ Map.Entry<Pair<Uri, Uri>, ConferenceParticipantConnection> entry =
+ entryIterator.next();
if (!participantUserEntities.contains(entry.getKey())) {
ConferenceParticipantConnection participant = entry.getValue();
@@ -675,12 +728,12 @@
connection.addConnectionListener(mParticipantListener);
connection.setConnectTimeMillis(parent.getConnectTimeMillis());
- if (Log.VERBOSE) {
- Log.v(this, "createConferenceParticipantConnection: %s", connection);
- }
+ Log.i(this, "createConferenceParticipantConnection: participant=%s, connection=%s",
+ participant, connection);
synchronized(mUpdateSyncRoot) {
- mConferenceParticipantConnections.put(participant.getHandle(), connection);
+ mConferenceParticipantConnections.put(new Pair<>(participant.getHandle(),
+ participant.getEndpoint()), connection);
}
mTelephonyConnectionService.addExistingConnection(mConferenceHostPhoneAccountHandle,
connection);
@@ -693,7 +746,7 @@
* @param participant The participant to remove.
*/
private void removeConferenceParticipant(ConferenceParticipantConnection participant) {
- Log.d(this, "removeConferenceParticipant: %s", participant);
+ Log.i(this, "removeConferenceParticipant: %s", participant);
participant.removeConnectionListener(mParticipantListener);
synchronized(mUpdateSyncRoot) {
@@ -728,20 +781,14 @@
* 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 hostHandle The handle of the connection hosting the conference.
+ * @param hostHandles The handle(s) of the connection hosting the conference.
* @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 hostHandle, Uri handle) {
- // If host and participant handles are the same, bail early.
- if (Objects.equals(hostHandle, handle)) {
- Log.v(this, "isParticipantHost(Y) : uris equal");
- return true;
- }
-
- // If there is no host handle or not participant handle, bail early.
- if (hostHandle == null || handle == null) {
+ private 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");
return false;
}
@@ -768,18 +815,27 @@
}
number = numberParts[0];
- // The host number will be a tel: uri. Per RFC3966, the part after tel: is the phone
- // number.
- String hostNumber = hostHandle.getSchemeSpecificPart();
+ 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();
- // 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);
+ // 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.pii(hostNumber), Log.pii(number));
- return isHost;
+ Log.v(this, "isParticipantHost(%s) : host: %s, participant %s", (isHost ? "Y" : "N"),
+ Log.pii(hostNumber), Log.pii(number));
+
+ if (isHost) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -801,26 +857,34 @@
if (originalConnection != null &&
originalConnection.getPhoneType() != PhoneConstants.PHONE_TYPE_IMS) {
- if (Log.VERBOSE) {
- Log.v(this,
- "Original connection for conference host is no longer an IMS connection; " +
- "new connection: %s", originalConnection);
- }
+ Log.i(this,
+ "handleOriginalConnectionChange : handover from IMS connection to " +
+ "new connection: %s", originalConnection);
PhoneAccountHandle phoneAccountHandle = null;
- if (mConferenceHost.getPhone() != null &&
- mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
- Phone imsPhone = mConferenceHost.getPhone();
- // The phone account handle for an ImsPhone is based on the default phone (ie the
- // base GSM or CDMA phone, not on the ImsPhone itself).
- phoneAccountHandle =
- PhoneUtils.makePstnPhoneAccountHandle(imsPhone.getDefaultPhone());
+ if (mConferenceHost.getPhone() != null) {
+ if (mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
+ Phone imsPhone = mConferenceHost.getPhone();
+ // The phone account handle for an ImsPhone is based on the default phone (ie
+ // the base GSM or CDMA phone, not on the ImsPhone itself).
+ phoneAccountHandle =
+ PhoneUtils.makePstnPhoneAccountHandle(imsPhone.getDefaultPhone());
+ } else {
+ // In the case of SRVCC, we still need a phone account, so use the top level
+ // phone to create a phone account.
+ phoneAccountHandle = PhoneUtils.makePstnPhoneAccountHandle(
+ mConferenceHost.getPhone());
+ }
}
if (mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
+ Log.i(this,"handleOriginalConnectionChange : SRVCC to GSM");
GsmConnection c = new GsmConnection(originalConnection, getTelecomCallId());
// This is a newly created conference connection as a result of SRVCC
c.setConferenceSupported(true);
+ c.addCapability(Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN);
+ c.setConnectionProperties(
+ c.getConnectionProperties() | Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE);
c.updateState();
// Copy the connect time from the conferenceHost
c.setConnectTimeMillis(mConferenceHost.getConnectTimeMillis());
@@ -918,4 +982,22 @@
sb.append("]");
return sb.toString();
}
+
+ private boolean canHoldImsCalls() {
+ PersistableBundle b = getCarrierConfig();
+ // Return true if the CarrierConfig is unavailable
+ return b == null || b.getBoolean(CarrierConfigManager.KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL);
+ }
+
+ private PersistableBundle getCarrierConfig() {
+ if (mConferenceHost == null) {
+ return null;
+ }
+
+ Phone phone = mConferenceHost.getPhone();
+ if (phone == null) {
+ return null;
+ }
+ return PhoneGlobals.getInstance().getCarrierConfigForSubId(phone.getSubId());
+ }
}
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 0f9ae5d..6669482 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -29,8 +29,10 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.stream.Collectors;
/**
* Manages conferences for IMS connections.
@@ -78,6 +80,12 @@
Log.v(this, "onConferenceStarted");
recalculate();
}
+
+ @Override
+ public void onConferenceSupportedChanged(Connection c, boolean isConferenceSupported) {
+ Log.v(this, "onConferenceSupportedChanged");
+ recalculate();
+ }
};
/**
@@ -111,6 +119,19 @@
* @param connection
*/
void add(TelephonyConnection connection) {
+ // DO NOT add external calls; we don't want to consider them as a potential conference
+ // member.
+ if ((connection.getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL) ==
+ Connection.PROPERTY_IS_EXTERNAL_CALL) {
+ return;
+ }
+
+ if (mTelephonyConnections.contains(connection)) {
+ // Adding a duplicate realistically shouldn't happen.
+ Log.w(this, "add - connection already tracked; connection=%s", connection);
+ return;
+ }
+
// Note: Wrap in Log.VERBOSE to avoid calling connection.toString if we are not going to be
// outputting the value.
if (Log.VERBOSE) {
@@ -128,10 +149,24 @@
* @param connection
*/
void remove(Connection connection) {
+ // External calls are not part of the conference controller, so don't remove them.
+ if ((connection.getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL) ==
+ Connection.PROPERTY_IS_EXTERNAL_CALL) {
+ return;
+ }
+
+ if (!mTelephonyConnections.contains(connection)) {
+ // Debug only since TelephonyConnectionService tries to clean up the connections tracked
+ // when the original connection changes. It does this proactively.
+ Log.d(this, "remove - connection not tracked; connection=%s", connection);
+ return;
+ }
+
if (Log.VERBOSE) {
Log.v(this, "remove connection: %s", connection);
}
+ connection.removeConnectionListener(mConnectionListener);
mTelephonyConnections.remove(connection);
recalculateConferenceable();
}
@@ -150,8 +185,8 @@
*/
private void recalculateConferenceable() {
Log.v(this, "recalculateConferenceable : %d", mTelephonyConnections.size());
- List<Conferenceable> activeConnections = new ArrayList<>(mTelephonyConnections.size());
- List<Conferenceable> backgroundConnections = new ArrayList<>(mTelephonyConnections.size());
+ HashSet<Conferenceable> conferenceableSet = new HashSet<>(mTelephonyConnections.size() +
+ mImsConferences.size());
// Loop through and collect all calls which are active or holding
for (TelephonyConnection connection : mTelephonyConnections) {
@@ -172,22 +207,23 @@
// If this connection does not support being in a conference call, then it is not
// conferenceable with any other connection.
if (!connection.isConferenceSupported()) {
+ connection.setConferenceables(Collections.<Conferenceable>emptyList());
continue;
}
switch (connection.getState()) {
case Connection.STATE_ACTIVE:
- activeConnections.add(connection);
- continue;
+ // fall through
case Connection.STATE_HOLDING:
- backgroundConnections.add(connection);
+ conferenceableSet.add(connection);
continue;
default:
break;
}
- connection.setConferenceableConnections(Collections.<Connection>emptyList());
+ // This connection is not active or holding, so clear all conferencable connections
+ connection.setConferenceables(Collections.<Conferenceable>emptyList());
}
-
+ // Also loop through all active conferences and collect the ones that are ACTIVE or HOLDING.
for (ImsConference conference : mImsConferences) {
if (Log.DEBUG) {
Log.d(this, "recalc - %s %s", conference.getState(), conference);
@@ -202,62 +238,37 @@
switch (conference.getState()) {
case Connection.STATE_ACTIVE:
- activeConnections.add(conference);
- continue;
+ //fall through
case Connection.STATE_HOLDING:
- backgroundConnections.add(conference);
+ conferenceableSet.add(conference);
continue;
default:
break;
}
}
- Log.v(this, "active: %d, holding: %d", activeConnections.size(),
- backgroundConnections.size());
+ Log.v(this, "conferenceableSet size: " + conferenceableSet.size());
- // Go through all the active connections and set the background connections as
- // conferenceable.
- for (Conferenceable conferenceable : activeConnections) {
- if (conferenceable instanceof Connection) {
- Connection connection = (Connection) conferenceable;
- connection.setConferenceables(backgroundConnections);
+ for (Conferenceable c : conferenceableSet) {
+ if (c instanceof Connection) {
+ // Remove this connection from the Set and add all others
+ List<Conferenceable> conferenceables = conferenceableSet
+ .stream()
+ .filter(conferenceable -> c != conferenceable)
+ .collect(Collectors.toList());
+ ((Connection) c).setConferenceables(conferenceables);
+ } else if (c instanceof Conference) {
+ // Remove all conferences from the set, since we can not conference a conference
+ // to another conference.
+ List<Connection> connections = conferenceableSet
+ .stream()
+ .filter(conferenceable -> conferenceable instanceof Connection)
+ .map(conferenceable -> (Connection) conferenceable)
+ .collect(Collectors.toList());
+ // Conference equivalent to setConferenceables that only accepts Connections
+ ((Conference) c).setConferenceableConnections(connections);
}
}
-
- // Go through all the background connections and set the active connections as
- // conferenceable.
- for (Conferenceable conferenceable : backgroundConnections) {
- if (conferenceable instanceof Connection) {
- Connection connection = (Connection) conferenceable;
- connection.setConferenceables(activeConnections);
- }
-
- }
-
- // Set the conference as conferenceable with all the connections
- for (ImsConference conference : mImsConferences) {
- // If this conference is not being hosted on the current device, we cannot conference it
- // with any other connections.
- if (!conference.isConferenceHost()) {
- if (Log.VERBOSE) {
- Log.v(this, "skipping conference (not hosted on this device): %s",
- conference);
- }
- continue;
- }
-
- List<Connection> nonConferencedConnections =
- new ArrayList<>(mTelephonyConnections.size());
- for (TelephonyConnection c : mTelephonyConnections) {
- if (c.getConference() == null && c.isConferenceSupported()) {
- nonConferencedConnections.add(c);
- }
- }
- if (Log.VERBOSE) {
- Log.v(this, "conference conferenceable: %s", nonConferencedConnections);
- }
- conference.setConferenceableConnections(nonConferencedConnections);
- }
}
/**
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index b4733dd..47fac6a 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -312,6 +312,17 @@
Connection original = telephonyConnection.getOriginalConnection();
if (original != null && !original.isIncoming()
&& Objects.equals(original.getAddress(), unknown.getAddress())) {
+ // If the new unknown connection is an external connection, don't swap one with an
+ // actual connection. This means a call got pulled away. We want the actual connection
+ // to disconnect.
+ if (unknown instanceof ImsExternalConnection &&
+ !(telephonyConnection
+ .getOriginalConnection() instanceof ImsExternalConnection)) {
+ Log.v(this, "maybeSwapWithUnknownConnection - not swapping regular connection " +
+ "with external connection.");
+ return false;
+ }
+
telephonyConnection.setOriginalConnection(unknown);
return true;
}
diff --git a/src/com/android/services/telephony/PstnPhoneCapabilitiesNotifier.java b/src/com/android/services/telephony/PstnPhoneCapabilitiesNotifier.java
index f5b8719..eb6f7f6 100644
--- a/src/com/android/services/telephony/PstnPhoneCapabilitiesNotifier.java
+++ b/src/com/android/services/telephony/PstnPhoneCapabilitiesNotifier.java
@@ -91,25 +91,6 @@
try {
boolean isVideoCapable = (Boolean) ar.result;
Log.d(this, "handleVideoCapabilitesChanged. Video capability - " + isVideoCapable);
- PhoneAccountHandle accountHandle =
- PhoneUtils.makePstnPhoneAccountHandle(mPhone);
-
- TelecomManager telecomMgr = TelecomManager.from(mPhone.getContext());
- PhoneAccount oldPhoneAccount = telecomMgr.getPhoneAccount(accountHandle);
- PhoneAccount.Builder builder = new PhoneAccount.Builder(oldPhoneAccount);
-
- int oldCapabilities = oldPhoneAccount.getCapabilities();
- boolean wasVideoPresenceSupported =
- (oldCapabilities & PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE)
- != 0;
- int capabilites = newCapabilities(oldPhoneAccount.getCapabilities(),
- PhoneAccount.CAPABILITY_VIDEO_CALLING, isVideoCapable);
- if (wasVideoPresenceSupported && isVideoCapable) {
- capabilites |= PhoneAccount.CAPABILITY_VIDEO_CALLING_RELIES_ON_PRESENCE;
- }
-
- builder.setCapabilities(capabilites);
- telecomMgr.registerPhoneAccount(builder.build());
mListener.onVideoCapabilitiesChanged(isVideoCapable);
} catch (Exception e) {
Log.d(this, "handleVideoCapabilitesChanged. Exception=" + e);
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index 7534701..b2e9984 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -16,8 +16,11 @@
package com.android.services.telephony;
+import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -27,7 +30,8 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
-import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -41,7 +45,6 @@
import android.text.TextUtils;
import com.android.ims.ImsManager;
-import com.android.internal.telephony.IPhoneSubInfo;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.phone.PhoneGlobals;
@@ -51,6 +54,7 @@
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
+import java.util.Optional;
/**
* Owns all data we have registered with Telecom including handling dynamic addition and
@@ -62,19 +66,26 @@
// This icon is the one that is used when the Slot ID that we have for a particular SIM
// is not supported, i.e. SubscriptionManager.INVALID_SLOT_ID or the 5th SIM in a phone.
private final static int DEFAULT_SIM_ICON = R.drawable.ic_multi_sim;
+ private final static String GROUP_PREFIX = "group_";
final class AccountEntry implements PstnPhoneCapabilitiesNotifier.Listener {
private final Phone mPhone;
- private final PhoneAccount mAccount;
+ private PhoneAccount mAccount;
private final PstnIncomingCallNotifier mIncomingCallNotifier;
private final PstnPhoneCapabilitiesNotifier mPhoneCapabilitiesNotifier;
+ private boolean mIsEmergency;
+ private boolean mIsDummy;
private boolean mIsVideoCapable;
private boolean mIsVideoPresenceSupported;
private boolean mIsVideoPauseSupported;
private boolean mIsMergeCallSupported;
+ private boolean mIsVideoConferencingSupported;
+ private boolean mIsMergeOfWifiCallsAllowedWhenVoWifiOff;
AccountEntry(Phone phone, boolean isEmergency, boolean isDummy) {
mPhone = phone;
+ mIsEmergency = isEmergency;
+ mIsDummy = isDummy;
mAccount = registerPstnPhoneAccount(isEmergency, isDummy);
Log.i(this, "Registered phoneAccount: %s with handle: %s",
mAccount, mAccount.getAccountHandle());
@@ -101,6 +112,7 @@
// Populate the phone account data.
int subId = mPhone.getSubId();
+ String subscriberId = mPhone.getSubscriberId();
int color = PhoneAccount.NO_HIGHLIGHT_COLOR;
int slotId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
String line1Number = mTelephonyManager.getLine1Number(subId);
@@ -170,6 +182,12 @@
}
mIsVideoCapable = mPhone.isVideoEnabled();
+
+ if (!mIsPrimaryUser) {
+ Log.i(this, "Disabling video calling for secondary user.");
+ mIsVideoCapable = false;
+ }
+
if (mIsVideoCapable) {
capabilities |= PhoneAccount.CAPABILITY_VIDEO_CALLING;
}
@@ -196,6 +214,9 @@
instantLetteringExtras = getPhoneAccountExtras();
}
mIsMergeCallSupported = isCarrierMergeCallSupported();
+ mIsVideoConferencingSupported = isCarrierVideoConferencingSupported();
+ mIsMergeOfWifiCallsAllowedWhenVoWifiOff =
+ isCarrierMergeOfWifiCallsAllowedWhenVoWifiOff();
if (isEmergency && mContext.getResources().getBoolean(
R.bool.config_emergency_account_emergency_calls_only)) {
@@ -219,6 +240,23 @@
icon = Icon.createWithBitmap(bitmap);
}
+ // Check to see if the newly registered account should replace the old account.
+ String groupId = "";
+ String[] mergedImsis = mTelephonyManager.getMergedSubscriberIds();
+ boolean isMergedSim = false;
+ if (mergedImsis != null && subscriberId != null && !isEmergency) {
+ for (String imsi : mergedImsis) {
+ if (imsi.equals(subscriberId)) {
+ isMergedSim = true;
+ break;
+ }
+ }
+ }
+ if(isMergedSim) {
+ groupId = GROUP_PREFIX + line1Number;
+ Log.i(this, "Adding Merged Account with group: " + Log.pii(groupId));
+ }
+
PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, label)
.setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, line1Number, null))
.setSubscriptionAddress(
@@ -230,6 +268,7 @@
.setSupportedUriSchemes(Arrays.asList(
PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL))
.setExtras(instantLetteringExtras)
+ .setGroupId(groupId)
.build();
// Register with Telecom and put into the account entry.
@@ -251,7 +290,8 @@
// Check if IMS video pause is supported.
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL);
+ return b != null &&
+ b.getBoolean(CarrierConfigManager.KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL);
}
/**
@@ -263,7 +303,8 @@
private boolean isCarrierVideoPresenceSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b.getBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL);
+ return b != null &&
+ b.getBoolean(CarrierConfigManager.KEY_USE_RCS_PRESENCE_BOOL);
}
/**
@@ -274,7 +315,8 @@
private boolean isCarrierInstantLetteringSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b.getBoolean(CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL);
+ return b != null &&
+ b.getBoolean(CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL);
}
/**
@@ -285,7 +327,8 @@
private boolean isCarrierMergeCallSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_CONFERENCE_CALL_BOOL);
+ return b != null &&
+ b.getBoolean(CarrierConfigManager.KEY_SUPPORT_CONFERENCE_CALL_BOOL);
}
/**
@@ -296,11 +339,38 @@
private boolean isCarrierEmergencyVideoCallsAllowed() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL);
+ return b != null &&
+ b.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL);
}
/**
- * @return The {@linke PhoneAccount} extras associated with the current subscription.
+ * Determines from carrier config whether video conferencing is supported.
+ *
+ * @return {@code true} if video conferencing is supported, {@code false} otherwise.
+ */
+ private boolean isCarrierVideoConferencingSupported() {
+ PersistableBundle b =
+ PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ return b != null &&
+ b.getBoolean(CarrierConfigManager.KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL);
+ }
+
+ /**
+ * Determines from carrier config whether merging of wifi calls is allowed when VoWIFI is
+ * turned off.
+ *
+ * @return {@code true} merging of wifi calls when VoWIFI is disabled should be prevented,
+ * {@code false} otherwise.
+ */
+ private boolean isCarrierMergeOfWifiCallsAllowedWhenVoWifiOff() {
+ PersistableBundle b =
+ PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ return b != null && b.getBoolean(
+ CarrierConfigManager.KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL);
+ }
+
+ /**
+ * @return The {@link PhoneAccount} extras associated with the current subscription.
*/
private Bundle getPhoneAccountExtras() {
PersistableBundle b =
@@ -328,6 +398,16 @@
@Override
public void onVideoCapabilitiesChanged(boolean isVideoCapable) {
mIsVideoCapable = isVideoCapable;
+ synchronized (mAccountsLock) {
+ if (!mAccounts.contains(this)) {
+ // Account has already been torn down, don't try to register it again.
+ // This handles the case where teardown has already happened, and we got a video
+ // update that lost the race for the mAccountsLock. In such a scenario by the
+ // time we get here, the original phone account could have been torn down.
+ return;
+ }
+ mAccount = registerPstnPhoneAccount(mIsEmergency, mIsDummy);
+ }
}
/**
@@ -346,6 +426,22 @@
public boolean isMergeCallSupported() {
return mIsMergeCallSupported;
}
+
+ /**
+ * Indicates whether this account supports video conferencing.
+ * @return {@code true} if the account supports video conferencing, {@code false} otherwise.
+ */
+ public boolean isVideoConferencingSupported() {
+ return mIsVideoConferencingSupported;
+ }
+
+ /**
+ * Indicate whether this account allow merging of wifi calls when VoWIFI is off.
+ * @return {@code true} if allowed, {@code false} otherwise.
+ */
+ public boolean isMergeOfWifiCallsAllowedWhenVoWifiOff() {
+ return mIsMergeOfWifiCallsAllowedWhenVoWifiOff;
+ }
}
private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
@@ -358,6 +454,22 @@
}
};
+ private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i(this, "User changed, re-registering phone accounts.");
+
+ int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+ UserHandle currentUserHandle = new UserHandle(userHandleId);
+ mIsPrimaryUser = UserManager.get(mContext).getPrimaryUser().getUserHandle()
+ .equals(currentUserHandle);
+
+ // Any time the user changes, re-register the accounts.
+ tearDownAccounts();
+ setupAccounts();
+ }
+ };
+
private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
@Override
public void onServiceStateChanged(ServiceState serviceState) {
@@ -376,7 +488,9 @@
private final TelephonyManager mTelephonyManager;
private final SubscriptionManager mSubscriptionManager;
private List<AccountEntry> mAccounts = new LinkedList<AccountEntry>();
+ private Object mAccountsLock = new Object();
private int mServiceState = ServiceState.STATE_POWER_OFF;
+ private boolean mIsPrimaryUser = true;
// TODO: Remove back-pointer from app singleton to Service, since this is not a preferred
// pattern; redesign. This was added to fix a late release bug.
@@ -412,9 +526,11 @@
* @return {@code True} if video pausing is supported.
*/
boolean isVideoPauseSupported(PhoneAccountHandle handle) {
- for (AccountEntry entry : mAccounts) {
- if (entry.getPhoneAccountHandle().equals(handle)) {
- return entry.isVideoPauseSupported();
+ synchronized (mAccountsLock) {
+ for (AccountEntry entry : mAccounts) {
+ if (entry.getPhoneAccountHandle().equals(handle)) {
+ return entry.isVideoPauseSupported();
+ }
}
}
return false;
@@ -428,15 +544,55 @@
* @return {@code True} if merging calls is supported.
*/
boolean isMergeCallSupported(PhoneAccountHandle handle) {
- for (AccountEntry entry : mAccounts) {
- if (entry.getPhoneAccountHandle().equals(handle)) {
- return entry.isMergeCallSupported();
+ synchronized (mAccountsLock) {
+ for (AccountEntry entry : mAccounts) {
+ if (entry.getPhoneAccountHandle().equals(handle)) {
+ return entry.isMergeCallSupported();
+ }
}
}
return false;
}
/**
+ * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} supports
+ * video conferencing.
+ *
+ * @param handle The {@link PhoneAccountHandle}.
+ * @return {@code True} if video conferencing is supported.
+ */
+ boolean isVideoConferencingSupported(PhoneAccountHandle handle) {
+ synchronized (mAccountsLock) {
+ for (AccountEntry entry : mAccounts) {
+ if (entry.getPhoneAccountHandle().equals(handle)) {
+ return entry.isVideoConferencingSupported();
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determines if the {@link AccountEntry} associated with a {@link PhoneAccountHandle} allows
+ * merging of wifi calls when VoWIFI is disabled.
+ *
+ * @param handle The {@link PhoneAccountHandle}.
+ * @return {@code True} if merging of wifi calls is allowed when VoWIFI is disabled.
+ */
+ boolean isMergeOfWifiCallsAllowedWhenVoWifiOff(final PhoneAccountHandle handle) {
+ synchronized (mAccountsLock) {
+ Optional<AccountEntry> result = mAccounts.stream().filter(
+ entry -> entry.getPhoneAccountHandle().equals(handle)).findFirst();
+
+ if (result.isPresent()) {
+ return result.get().isMergeOfWifiCallsAllowedWhenVoWifiOff();
+ } else {
+ return false;
+ }
+ }
+ }
+
+ /**
* @return Reference to the {@code TelecomAccountRegistry}'s subscription manager.
*/
SubscriptionManager getSubscriptionManager() {
@@ -450,9 +606,11 @@
* @return The address.
*/
Uri getAddress(PhoneAccountHandle handle) {
- for (AccountEntry entry : mAccounts) {
- if (entry.getPhoneAccountHandle().equals(handle)) {
- return entry.mAccount.getAddress();
+ synchronized (mAccountsLock) {
+ for (AccountEntry entry : mAccounts) {
+ if (entry.getPhoneAccountHandle().equals(handle)) {
+ return entry.mAccount.getAddress();
+ }
}
}
return null;
@@ -475,6 +633,11 @@
// We also need to listen for changes to the service state (e.g. emergency -> in service)
// because this could signal a removal or addition of a SIM in a single SIM phone.
mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE);
+
+ // Listen for user switches. When the user switches, we need to ensure that if the current
+ // use is not the primary user we disable video calling.
+ mContext.registerReceiver(mUserSwitchedReceiver,
+ new IntentFilter(Intent.ACTION_USER_SWITCHED));
}
/**
@@ -485,9 +648,11 @@
* @return {@code True} if an entry exists.
*/
boolean hasAccountEntryForPhoneAccount(PhoneAccountHandle handle) {
- for (AccountEntry entry : mAccounts) {
- if (entry.getPhoneAccountHandle().equals(handle)) {
- return true;
+ synchronized (mAccountsLock) {
+ for (AccountEntry entry : mAccounts) {
+ if (entry.getPhoneAccountHandle().equals(handle)) {
+ return true;
+ }
}
}
return false;
@@ -526,28 +691,33 @@
final boolean phoneAccountsEnabled = mContext.getResources().getBoolean(
R.bool.config_pstn_phone_accounts_enabled);
- if (phoneAccountsEnabled) {
- for (Phone phone : phones) {
- int subscriptionId = phone.getSubId();
- Log.d(this, "Phone with subscription id %d", subscriptionId);
- if (subscriptionId >= 0) {
- mAccounts.add(new AccountEntry(phone, false /* emergency */,
- false /* isDummy */));
+ synchronized (mAccountsLock) {
+ if (phoneAccountsEnabled) {
+ for (Phone phone : phones) {
+ int subscriptionId = phone.getSubId();
+ Log.d(this, "Phone with subscription id %d", subscriptionId);
+ // setupAccounts can be called multiple times during service changes. Don't add an
+ // account if the Icc has not been set yet.
+ if (subscriptionId >= 0 && phone.getFullIccSerialNumber() != null) {
+ mAccounts.add(new AccountEntry(phone, false /* emergency */,
+ false /* isDummy */));
+ }
}
}
- }
- // If we did not list ANY accounts, we need to provide a "default" SIM account
- // for emergency numbers since no actual SIM is needed for dialing emergency
- // numbers but a phone account is.
- if (mAccounts.isEmpty()) {
- mAccounts.add(new AccountEntry(PhoneFactory.getDefaultPhone(), true /* emergency */,
- false /* isDummy */));
- }
+ // If we did not list ANY accounts, we need to provide a "default" SIM account
+ // for emergency numbers since no actual SIM is needed for dialing emergency
+ // numbers but a phone account is.
+ if (mAccounts.isEmpty()) {
+ mAccounts.add(new AccountEntry(PhoneFactory.getDefaultPhone(), true /* emergency */,
+ false /* isDummy */));
+ }
- // Add a fake account entry.
- if (DBG && phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
- mAccounts.add(new AccountEntry(phones[0], false /* emergency */, true /* isDummy */));
+ // Add a fake account entry.
+ if (DBG && phones.length > 0 && "TRUE".equals(System.getProperty("dummy_sim"))) {
+ mAccounts.add(new AccountEntry(phones[0], false /* emergency */,
+ true /* isDummy */));
+ }
}
// Clean up any PhoneAccounts that are no longer relevant
@@ -579,9 +749,11 @@
}
private void tearDownAccounts() {
- for (AccountEntry entry : mAccounts) {
- entry.teardown();
+ synchronized (mAccountsLock) {
+ for (AccountEntry entry : mAccounts) {
+ entry.teardown();
+ }
+ mAccounts.clear();
}
- mAccounts.clear();
}
}
diff --git a/src/com/android/services/telephony/TelephonyConferenceController.java b/src/com/android/services/telephony/TelephonyConferenceController.java
index 7da9ea5..5d59e17 100644
--- a/src/com/android/services/telephony/TelephonyConferenceController.java
+++ b/src/com/android/services/telephony/TelephonyConferenceController.java
@@ -23,6 +23,7 @@
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
import android.net.Uri;
import android.telecom.Conference;
@@ -83,12 +84,24 @@
}
void add(TelephonyConnection connection) {
+ if (mTelephonyConnections.contains(connection)) {
+ // Adding a duplicate realistically shouldn't happen.
+ Log.w(this, "add - connection already tracked; connection=%s", connection);
+ return;
+ }
+
mTelephonyConnections.add(connection);
connection.addConnectionListener(mConnectionListener);
recalculate();
}
void remove(Connection connection) {
+ if (!mTelephonyConnections.contains(connection)) {
+ // Debug only since TelephonyConnectionService tries to clean up the connections tracked
+ // when the original connection changes. It does this proactively.
+ Log.d(this, "remove - connection not tracked; connection=%s", connection);
+ return;
+ }
connection.removeConnectionListener(mConnectionListener);
mTelephonyConnections.remove(connection);
recalculate();
@@ -113,10 +126,7 @@
*/
private void recalculateConferenceable() {
Log.v(this, "recalculateConferenceable : %d", mTelephonyConnections.size());
-
- List<Connection> activeConnections = new ArrayList<>(mTelephonyConnections.size());
- List<Connection> backgroundConnections = new ArrayList<>(
- mTelephonyConnections.size());
+ HashSet<Connection> conferenceableConnections = new HashSet<>(mTelephonyConnections.size());
// Loop through and collect all calls which are active or holding
for (TelephonyConnection connection : mTelephonyConnections) {
@@ -126,10 +136,9 @@
if (connection.isConferenceSupported() && !participatesInFullConference(connection)) {
switch (connection.getState()) {
case Connection.STATE_ACTIVE:
- activeConnections.add(connection);
- continue;
+ //fall through
case Connection.STATE_HOLDING:
- backgroundConnections.add(connection);
+ conferenceableConnections.add(connection);
continue;
default:
break;
@@ -139,34 +148,30 @@
connection.setConferenceableConnections(Collections.<Connection>emptyList());
}
- Log.v(this, "active: %d, holding: %d",
- activeConnections.size(), backgroundConnections.size());
+ Log.v(this, "conferenceable: " + conferenceableConnections.size());
- // Go through all the active connections and set the background connections as
- // conferenceable.
- for (Connection connection : activeConnections) {
- connection.setConferenceableConnections(backgroundConnections);
+ // Go through all the conferenceable connections and add all other conferenceable
+ // connections that is not the connection itself
+ for (Connection c : conferenceableConnections) {
+ List<Connection> connections = conferenceableConnections
+ .stream()
+ // Filter out this connection from the list of connections
+ .filter(connection -> c != connection)
+ .collect(Collectors.toList());
+ c.setConferenceableConnections(connections);
}
- // Go through all the background connections and set the active connections as
- // conferenceable.
- for (Connection connection : backgroundConnections) {
- connection.setConferenceableConnections(activeConnections);
- }
-
- // Set the conference as conferenceable with all the connections
+ // Set the conference as conferenceable with all of the connections that are not in the
+ // conference.
if (mTelephonyConference != null && !isFullConference(mTelephonyConference)) {
- List<Connection> nonConferencedConnections =
- new ArrayList<>(mTelephonyConnections.size());
- for (TelephonyConnection c : mTelephonyConnections) {
- if (c.isConferenceSupported() && c.getConference() == null) {
- nonConferencedConnections.add(c);
- }
- }
- Log.v(this, "conference conferenceable: %s", nonConferencedConnections);
+ List<Connection> nonConferencedConnections = mTelephonyConnections
+ .stream()
+ // Only retrieve Connections that are not in a conference (but support
+ // conferences).
+ .filter(c -> c.isConferenceSupported() && c.getConference() == null)
+ .collect(Collectors.toList());
mTelephonyConference.setConferenceableConnections(nonConferencedConnections);
}
-
// TODO: Do not allow conferencing of already conferenced connections.
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 343f7e4..77f4077 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -23,15 +23,22 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.PersistableBundle;
import android.telecom.CallAudioState;
import android.telecom.ConferenceParticipant;
import android.telecom.Connection;
import android.telecom.PhoneAccount;
+import android.telecom.PhoneAccountHandle;
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
+import android.telecom.VideoProfile;
+import android.telephony.CarrierConfigManager;
+import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
import android.util.Pair;
+import com.android.ims.ImsCall;
import com.android.ims.ImsCallProfile;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
@@ -41,6 +48,11 @@
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
+import com.android.phone.ImsUtil;
+import com.android.phone.PhoneGlobals;
+import com.android.phone.PhoneUtils;
import com.android.phone.R;
import java.lang.Override;
@@ -79,6 +91,8 @@
private static final int MSG_CONNECTION_EXTRAS_CHANGED = 12;
private static final int MSG_SET_ORIGNAL_CONNECTION_CAPABILITIES = 13;
private static final int MSG_ON_HOLD_TONE = 14;
+ private static final int MSG_CDMA_VOICE_PRIVACY_ON = 15;
+ private static final int MSG_CDMA_VOICE_PRIVACY_OFF = 16;
private final Handler mHandler = new Handler() {
@Override
@@ -131,6 +145,7 @@
if (isMultiParty) {
notifyConferenceStarted();
}
+ break;
case MSG_CONFERENCE_MERGE_FAILED:
notifyConferenceMergeFailed();
break;
@@ -156,6 +171,13 @@
case MSG_SET_VIDEO_STATE:
int videoState = (int) msg.obj;
setVideoState(videoState);
+
+ // A change to the video state of the call can influence whether or not it
+ // can be part of a conference, whether another call can be added, and
+ // whether the call should have the HD audio property set.
+ refreshConferenceSupported();
+ refreshDisableAddCall();
+ updateConnectionProperties();
break;
case MSG_SET_VIDEO_PROVIDER:
@@ -206,17 +228,34 @@
}
}
break;
+
+ case MSG_CDMA_VOICE_PRIVACY_ON:
+ Log.d(this, "MSG_CDMA_VOICE_PRIVACY_ON received");
+ setCdmaVoicePrivacy(true);
+ break;
+ case MSG_CDMA_VOICE_PRIVACY_OFF:
+ Log.d(this, "MSG_CDMA_VOICE_PRIVACY_OFF received");
+ setCdmaVoicePrivacy(false);
+ break;
}
}
};
/**
+ * @return {@code true} if carrier video conferencing is supported, {@code false} otherwise.
+ */
+ public boolean isCarrierVideoConferencingSupported() {
+ return mIsCarrierVideoConferencingSupported;
+ }
+
+ /**
* A listener/callback mechanism that is specific communication from TelephonyConnections
* to TelephonyConnectionService (for now). It is more specific that Connection.Listener
* because it is only exposed in Telephony.
*/
public abstract static class TelephonyConnectionListener {
public void onOriginalConnectionConfigured(TelephonyConnection c) {}
+ public void onOriginalConnectionRetry(TelephonyConnection c) {}
}
private final PostDialListener mPostDialListener = new PostDialListener() {
@@ -333,6 +372,51 @@
public void onExitedEcmMode() {
handleExitedEcmMode();
}
+
+ /**
+ * Called from {@link ImsPhoneCallTracker} when a request to pull an external call has
+ * failed.
+ * @param externalConnection
+ */
+ @Override
+ public void onCallPullFailed(com.android.internal.telephony.Connection externalConnection) {
+ if (externalConnection == null) {
+ return;
+ }
+
+ Log.i(this, "onCallPullFailed - pull failed; swapping back to call: %s",
+ externalConnection);
+
+ // Inform the InCallService of the fact that the call pull failed (it may choose to
+ // display a message informing the user of the pull failure).
+ sendConnectionEvent(Connection.EVENT_CALL_PULL_FAILED, null);
+
+ // Swap the ImsPhoneConnection we used to do the pull for the ImsExternalConnection
+ // which originally represented the call.
+ setOriginalConnection(externalConnection);
+
+ // Set our state to active again since we're no longer pulling.
+ setActiveInternal();
+ }
+
+ /**
+ * Called from {@link ImsPhoneCallTracker} when a handover to WIFI has failed.
+ */
+ @Override
+ public void onHandoverToWifiFailed() {
+ sendConnectionEvent(TelephonyManager.EVENT_HANDOVER_TO_WIFI_FAILED, null);
+ }
+
+ /**
+ * Informs the {@link android.telecom.ConnectionService} of a connection event raised by the
+ * original connection.
+ * @param event The connection event.
+ * @param extras The extras.
+ */
+ @Override
+ public void onConnectionEvent(String event, Bundle extras) {
+ sendConnectionEvent(event, extras);
+ }
};
protected com.android.internal.telephony.Connection mOriginalConnection;
@@ -388,6 +472,18 @@
private boolean mIsConferenceSupported;
/**
+ * Indicates whether the carrier supports video conferencing; captures the current state of the
+ * carrier config
+ * {@link android.telephony.CarrierConfigManager#KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL}.
+ */
+ private boolean mIsCarrierVideoConferencingSupported;
+
+ /**
+ * Indicates whether or not this connection has CDMA Enhanced Voice Privacy enabled.
+ */
+ private boolean mIsCdmaVoicePrivacyEnabled;
+
+ /**
* Listeners to our TelephonyConnection specific callbacks
*/
private final Set<TelephonyConnectionListener> mTelephonyListeners = Collections.newSetFromMap(
@@ -612,12 +708,10 @@
if (mOriginalConnection != null && mOriginalConnection.isIncoming()) {
callCapabilities |= CAPABILITY_SPEED_UP_MT_AUDIO;
}
- if (isImsConnection()) {
- if (!shouldTreatAsEmergencyCall()) {
- callCapabilities |= CAPABILITY_SUPPORT_HOLD;
- if (getState() == STATE_ACTIVE || getState() == STATE_HOLDING) {
- callCapabilities |= CAPABILITY_HOLD;
- }
+ if (!shouldTreatAsEmergencyCall() && isImsConnection() && canHoldImsCalls()) {
+ callCapabilities |= CAPABILITY_SUPPORT_HOLD;
+ if (getState() == STATE_ACTIVE || getState() == STATE_HOLDING) {
+ callCapabilities |= CAPABILITY_HOLD;
}
}
@@ -646,7 +740,7 @@
// shown.
Phone phone = getPhone();
if (phone != null && phone.isInEcm()) {
- connectionProperties |= PROPERTY_SHOW_CALLBACK_NUMBER;
+ connectionProperties |= PROPERTY_EMERGENCY_CALLBACK_MODE;
}
return connectionProperties;
@@ -658,10 +752,13 @@
protected final void updateConnectionProperties() {
int newProperties = buildConnectionProperties();
- newProperties = changeBitmask(newProperties, PROPERTY_HIGH_DEF_AUDIO, mHasHighDefAudio);
+ newProperties = changeBitmask(newProperties, PROPERTY_HIGH_DEF_AUDIO,
+ hasHighDefAudioProperty());
newProperties = changeBitmask(newProperties, PROPERTY_WIFI, mIsWifi);
newProperties = changeBitmask(newProperties, PROPERTY_IS_EXTERNAL_CALL,
isExternalConnection());
+ newProperties = changeBitmask(newProperties, PROPERTY_HAS_CDMA_VOICE_PRIVACY,
+ mIsCdmaVoicePrivacyEnabled);
if (getConnectionProperties() != newProperties) {
setConnectionProperties(newProperties);
@@ -677,10 +774,13 @@
if (!Objects.equals(address, getAddress()) ||
presentation != getAddressPresentation()) {
Log.v(this, "updateAddress, address changed");
+ if ((getConnectionProperties() & PROPERTY_IS_DOWNGRADED_CONFERENCE) != 0) {
+ address = null;
+ }
setAddress(address, presentation);
}
- String name = mOriginalConnection.getCnapName();
+ String name = filterCnapName(mOriginalConnection.getCnapName());
int namePresentation = mOriginalConnection.getCnapNamePresentation();
if (!Objects.equals(name, getCallerDisplayName()) ||
namePresentation != getCallerDisplayNamePresentation()) {
@@ -691,6 +791,10 @@
if (PhoneNumberUtils.isEmergencyNumber(mOriginalConnection.getAddress())) {
mTreatAsEmergencyCall = true;
}
+
+ // Changing the address of the connection can change whether it is an emergency call or
+ // not, which can impact whether it can be part of a conference.
+ refreshConferenceSupported();
}
}
@@ -712,6 +816,8 @@
getPhone().registerForDisconnect(mHandler, MSG_DISCONNECT, null);
getPhone().registerForSuppServiceNotification(mHandler, MSG_SUPP_SERVICE_NOTIFY, null);
getPhone().registerForOnHoldTone(mHandler, MSG_ON_HOLD_TONE, null);
+ getPhone().registerForInCallVoicePrivacyOn(mHandler, MSG_CDMA_VOICE_PRIVACY_ON, null);
+ getPhone().registerForInCallVoicePrivacyOff(mHandler, MSG_CDMA_VOICE_PRIVACY_OFF, null);
mOriginalConnection.addPostDialListener(mPostDialListener);
mOriginalConnection.addListener(mOriginalConnectionListener);
@@ -740,6 +846,22 @@
}
mIsMultiParty = mOriginalConnection.isMultiparty();
+ Bundle extrasToPut = new Bundle();
+ List<String> extrasToRemove = new ArrayList<>();
+ if (mOriginalConnection.isActiveCallDisconnectedOnAnswer()) {
+ extrasToPut.putBoolean(Connection.EXTRA_ANSWERING_DROPS_FG_CALL, true);
+ } else {
+ extrasToRemove.add(Connection.EXTRA_ANSWERING_DROPS_FG_CALL);
+ }
+
+ if (shouldSetDisableAddCallExtra()) {
+ extrasToPut.putBoolean(Connection.EXTRA_DISABLE_ADD_CALL, true);
+ } else {
+ extrasToRemove.add(Connection.EXTRA_DISABLE_ADD_CALL);
+ }
+ putExtras(extrasToPut);
+ removeExtras(extrasToRemove);
+
// updateState can set mOriginalConnection to null if its state is DISCONNECTED, so this
// should be executed *after* the above setters have run.
updateState();
@@ -752,6 +874,33 @@
}
/**
+ * Filters the CNAP name to not include a list of names that are unhelpful to the user for
+ * Caller ID purposes.
+ */
+ private String filterCnapName(final String cnapName) {
+ if (cnapName == null) {
+ return null;
+ }
+ PersistableBundle carrierConfig = getCarrierConfig();
+ String[] filteredCnapNames = null;
+ if (carrierConfig != null) {
+ filteredCnapNames = carrierConfig.getStringArray(
+ CarrierConfigManager.FILTERED_CNAP_NAMES_STRING_ARRAY);
+ }
+ if (filteredCnapNames != null) {
+ long cnapNameMatches = Arrays.asList(filteredCnapNames)
+ .stream()
+ .filter(filteredCnapName -> filteredCnapName.equals(cnapName.toUpperCase()))
+ .count();
+ if (cnapNameMatches > 0) {
+ Log.i(this, "filterCnapName: Filtered CNAP Name: " + cnapName);
+ return "";
+ }
+ }
+ return cnapName;
+ }
+
+ /**
* Sets the EXTRA_CALL_TECHNOLOGY_TYPE extra on the connection to report back to Telecom.
*/
private void setTechnologyTypeExtra() {
@@ -760,6 +909,102 @@
}
}
+ private void refreshDisableAddCall() {
+ if (shouldSetDisableAddCallExtra()) {
+ putExtra(Connection.EXTRA_DISABLE_ADD_CALL, true);
+ } else {
+ removeExtras(Connection.EXTRA_DISABLE_ADD_CALL);
+ }
+ }
+
+ private boolean shouldSetDisableAddCallExtra() {
+ boolean carrierShouldAllowAddCall = mOriginalConnection.shouldAllowAddCallDuringVideoCall();
+ if (carrierShouldAllowAddCall) {
+ return false;
+ }
+ Phone phone = getPhone();
+ if (phone == null) {
+ return false;
+ }
+ boolean isCurrentVideoCall = false;
+ boolean wasVideoCall = false;
+ boolean isVowifiEnabled = false;
+ if (phone instanceof ImsPhone) {
+ ImsPhone imsPhone = (ImsPhone) phone;
+ if (imsPhone.getForegroundCall() != null
+ && imsPhone.getForegroundCall().getImsCall() != null) {
+ ImsCall call = imsPhone.getForegroundCall().getImsCall();
+ isCurrentVideoCall = call.isVideoCall();
+ wasVideoCall = call.wasVideoCall();
+ }
+
+ isVowifiEnabled = ImsUtil.isWfcEnabled(phone.getContext());
+ }
+
+ if (isCurrentVideoCall) {
+ return true;
+ } else if (wasVideoCall && mIsWifi && !isVowifiEnabled) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean hasHighDefAudioProperty() {
+ if (!mHasHighDefAudio) {
+ return false;
+ }
+
+ boolean isVideoCall = VideoProfile.isVideo(getVideoState());
+
+ PersistableBundle b = getCarrierConfig();
+ boolean canWifiCallsBeHdAudio =
+ b != null && b.getBoolean(CarrierConfigManager.KEY_WIFI_CALLS_CAN_BE_HD_AUDIO);
+ boolean canVideoCallsBeHdAudio =
+ b != null && b.getBoolean(CarrierConfigManager.KEY_VIDEO_CALLS_CAN_BE_HD_AUDIO);
+
+ if (isVideoCall && !canVideoCallsBeHdAudio) {
+ return false;
+ }
+
+ if (mIsWifi && !canWifiCallsBeHdAudio) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean canHoldImsCalls() {
+ PersistableBundle b = getCarrierConfig();
+ // Return true if the CarrierConfig is unavailable
+ return !doesDeviceRespectHoldCarrierConfig() || b == null ||
+ b.getBoolean(CarrierConfigManager.KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL);
+ }
+
+ private PersistableBundle getCarrierConfig() {
+ Phone phone = getPhone();
+ if (phone == null) {
+ return null;
+ }
+ return PhoneGlobals.getInstance().getCarrierConfigForSubId(phone.getSubId());
+ }
+
+ /**
+ * Determines if the device will respect the value of the
+ * {@link CarrierConfigManager#KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL} configuration option.
+ *
+ * @return {@code false} if the device always supports holding IMS calls, {@code true} if it
+ * will use {@link CarrierConfigManager#KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL} to determine if
+ * hold is supported.
+ */
+ private boolean doesDeviceRespectHoldCarrierConfig() {
+ Phone phone = getPhone();
+ if (phone == null) {
+ return true;
+ }
+ return phone.getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_device_respects_hold_carrier_config);
+ }
+
/**
* Whether the connection should be treated as an emergency.
* @return {@code true} if the connection should be treated as an emergency call based
@@ -781,6 +1026,8 @@
getPhone().unregisterForDisconnect(mHandler);
getPhone().unregisterForSuppServiceNotification(mHandler);
getPhone().unregisterForOnHoldTone(mHandler);
+ getPhone().unregisterForInCallVoicePrivacyOn(mHandler);
+ getPhone().unregisterForInCallVoicePrivacyOff(mHandler);
}
mOriginalConnection.removePostDialListener(mPostDialListener);
mOriginalConnection.removeListener(mOriginalConnectionListener);
@@ -811,6 +1058,19 @@
} catch (CallStateException e) {
Log.e(this, e, "Call to Connection.hangup failed with exception");
}
+ } else {
+ if (getState() == STATE_DISCONNECTED) {
+ Log.i(this, "hangup called on an already disconnected call!");
+ close();
+ } else {
+ // There are a few cases where mOriginalConnection has not been set yet. For
+ // example, when the radio has to be turned on to make an emergency call,
+ // mOriginalConnection could not be set for many seconds.
+ setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.LOCAL,
+ "Local Disconnect before connection established."));
+ close();
+ }
}
}
@@ -998,17 +1258,30 @@
break;
case DIALING:
case ALERTING:
- setDialing();
+ if (mOriginalConnection != null && mOriginalConnection.isPulledCall()) {
+ setPulling();
+ } else {
+ setDialing();
+ }
break;
case INCOMING:
case WAITING:
setRinging();
break;
case DISCONNECTED:
- setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
- mOriginalConnection.getDisconnectCause(),
- mOriginalConnection.getVendorDisconnectCause()));
- close();
+ // We can get into a situation where the radio wants us to redial the same
+ // emergency call on the other available slot. This will not set the state to
+ // disconnected and will instead tell the TelephonyConnectionService to create
+ // a new originalConnection using the new Slot.
+ if (mOriginalConnection.getDisconnectCause() ==
+ DisconnectCause.DIALED_ON_WRONG_SLOT) {
+ fireOnOriginalConnectionRetryDial();
+ } else {
+ setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
+ mOriginalConnection.getDisconnectCause(),
+ mOriginalConnection.getVendorDisconnectCause()));
+ close();
+ }
break;
case DISCONNECTING:
break;
@@ -1146,6 +1419,16 @@
}
/**
+ * Sets whether or not CDMA enhanced call privacy is enabled for this connection.
+ */
+ private void setCdmaVoicePrivacy(boolean isEnabled) {
+ if(mIsCdmaVoicePrivacyEnabled != isEnabled) {
+ mIsCdmaVoicePrivacyEnabled = isEnabled;
+ updateConnectionProperties();
+ }
+ }
+
+ /**
* Applies capabilities specific to conferences termination to the
* {@code ConnectionCapabilities} bit-mask.
*
@@ -1213,6 +1496,7 @@
mIsWifi = isWifi;
updateConnectionProperties();
updateStatusHints();
+ refreshDisableAddCall();
}
/**
@@ -1375,6 +1659,12 @@
}
}
+ private final void fireOnOriginalConnectionRetryDial() {
+ for (TelephonyConnectionListener l : mTelephonyListeners) {
+ l.onOriginalConnectionRetry(this);
+ }
+ }
+
/**
* Handles exiting ECM mode.
*/
@@ -1383,6 +1673,62 @@
}
/**
+ * Determines whether the connection supports conference calling. A connection supports
+ * conference calling if it:
+ * 1. Is not an emergency call.
+ * 2. Carrier supports conference calls.
+ * 3. If call is a video call, carrier supports video conference calls.
+ * 4. If call is a wifi call and VoWIFI is disabled and carrier supports merging these calls.
+ */
+ private void refreshConferenceSupported() {
+ boolean isVideoCall = VideoProfile.isVideo(getVideoState());
+ Phone phone = getPhone();
+ boolean isIms = phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS;
+ boolean isVoWifiEnabled = false;
+ if (isIms) {
+ ImsPhone imsPhone = (ImsPhone) phone;
+ isVoWifiEnabled = imsPhone.isWifiCallingEnabled();
+ }
+ PhoneAccountHandle phoneAccountHandle = isIms ? PhoneUtils
+ .makePstnPhoneAccountHandle(phone.getDefaultPhone())
+ : PhoneUtils.makePstnPhoneAccountHandle(phone);
+ TelecomAccountRegistry telecomAccountRegistry = TelecomAccountRegistry
+ .getInstance(getPhone().getContext());
+ boolean isConferencingSupported = telecomAccountRegistry
+ .isMergeCallSupported(phoneAccountHandle);
+ mIsCarrierVideoConferencingSupported = telecomAccountRegistry
+ .isVideoConferencingSupported(phoneAccountHandle);
+ boolean isMergeOfWifiCallsAllowedWhenVoWifiOff = telecomAccountRegistry
+ .isMergeOfWifiCallsAllowedWhenVoWifiOff(phoneAccountHandle);
+
+ Log.v(this, "refreshConferenceSupported : isConfSupp=%b, isVidConfSupp=%b, " +
+ "isMergeOfWifiAllowed=%b, isWifi=%b, isVoWifiEnabled=%b", isConferencingSupported,
+ mIsCarrierVideoConferencingSupported, isMergeOfWifiCallsAllowedWhenVoWifiOff,
+ isWifi(), isVoWifiEnabled);
+ boolean isConferenceSupported = true;
+ if (mTreatAsEmergencyCall) {
+ isConferenceSupported = false;
+ Log.d(this, "refreshConferenceSupported = false; emergency call");
+ } else if (!isConferencingSupported) {
+ isConferenceSupported = false;
+ Log.d(this, "refreshConferenceSupported = false; carrier doesn't support conf.");
+ } else if (isVideoCall && !mIsCarrierVideoConferencingSupported) {
+ isConferenceSupported = false;
+ Log.d(this, "refreshConferenceSupported = false; video conf not supported.");
+ } else if (!isMergeOfWifiCallsAllowedWhenVoWifiOff && isWifi() && !isVoWifiEnabled) {
+ isConferenceSupported = false;
+ Log.d(this,
+ "refreshConferenceSupported = false; can't merge wifi calls when voWifi off.");
+ } else {
+ Log.d(this, "refreshConferenceSupported = true.");
+ }
+
+ if (isConferenceSupported != isConferenceSupported()) {
+ setConferenceSupported(isConferenceSupported);
+ notifyConferenceSupportedChanged(isConferenceSupported);
+ }
+ }
+ /**
* Provides a mapping from extras keys which may be found in the
* {@link com.android.internal.telephony.Connection} to their equivalents defined in
* {@link android.telecom.Connection}.
@@ -1435,6 +1781,8 @@
} else {
sb.append("Y");
}
+ sb.append(" confSupported:");
+ sb.append(mIsConferenceSupported ? "Y" : "N");
sb.append("]");
return sb.toString();
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 2b2ed02..77a7cfb 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -33,10 +33,12 @@
import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
+import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.Pair;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
@@ -52,7 +54,11 @@
import com.android.phone.PhoneUtils;
import com.android.phone.R;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.regex.Pattern;
@@ -76,6 +82,13 @@
private EmergencyCallHelper mEmergencyCallHelper;
private EmergencyTonePlayer mEmergencyTonePlayer;
+ // 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
+ // call at one time. We also only access this cache from a TelephonyConnection that wishes to
+ // redial, so we use a WeakReference that will become stale once the TelephonyConnection is
+ // destroyed.
+ private Pair<WeakReference<TelephonyConnection>, List<Phone>> mEmergencyRetryCache;
+
/**
* A listener to actionable events specific to the TelephonyConnection.
*/
@@ -85,6 +98,11 @@
public void onOriginalConnectionConfigured(TelephonyConnection c) {
addConnectionToConferenceController(c);
}
+
+ @Override
+ public void onOriginalConnectionRetry(TelephonyConnection c) {
+ retryOutgoingOriginalConnection(c);
+ }
};
@Override
@@ -112,7 +130,7 @@
}
String scheme = handle.getScheme();
- final String number;
+ String number;
if (PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) {
// TODO: We don't check for SecurityException here (requires
// CALL_PRIVILEGED permission).
@@ -176,10 +194,137 @@
}
}
- boolean isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(this, number);
+ // Convert into emergency number if necessary
+ // This is required in some regions (e.g. Taiwan).
+ if (!PhoneNumberUtils.isLocalEmergencyNumber(this, number) &&
+ PhoneNumberUtils.isConvertToEmergencyNumberEnabled()) {
+ final Phone phone = getPhoneForAccount(request.getAccountHandle(), false);
+ // We only do the conversion if the phone is not in service. The un-converted
+ // emergency numbers will go to the correct destination when the phone is in-service,
+ // so they will only need the special emergency call setup when the phone is out of
+ // service.
+ if (phone == null || phone.getServiceState().getState()
+ != ServiceState.STATE_IN_SERVICE) {
+ String convertedNumber = PhoneNumberUtils.convertToEmergencyNumber(number);
+ if (!TextUtils.equals(convertedNumber, number)) {
+ Log.i(this, "onCreateOutgoingConnection, converted to emergency number");
+ number = convertedNumber;
+ handle = Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null);
+ }
+ }
+ }
+ final String numberToDial = number;
- // Get the right phone object from the account data passed in.
- final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber);
+ final boolean isEmergencyNumber =
+ PhoneNumberUtils.isLocalEmergencyNumber(this, numberToDial);
+
+ if (isEmergencyNumber && !isRadioOn()) {
+ final Uri emergencyHandle = handle;
+ // By default, Connection based on the default Phone, since we need to return to Telecom
+ // now.
+ final int defaultPhoneType = PhoneFactory.getDefaultPhone().getPhoneType();
+ final Connection emergencyConnection = getTelephonyConnection(request, numberToDial,
+ isEmergencyNumber, emergencyHandle, PhoneFactory.getDefaultPhone());
+ if (mEmergencyCallHelper == null) {
+ mEmergencyCallHelper = new EmergencyCallHelper(this);
+ }
+ mEmergencyCallHelper.enableEmergencyCalling(new EmergencyCallStateListener.Callback() {
+ @Override
+ public void onComplete(EmergencyCallStateListener listener, boolean isRadioReady) {
+ // Make sure the Call has not already been canceled by the user.
+ if (emergencyConnection.getState() == Connection.STATE_DISCONNECTED) {
+ Log.i(this, "Emergency call disconnected before the outgoing call was " +
+ "placed. Skipping emergency call placement.");
+ return;
+ }
+ if (isRadioReady) {
+ // Get the right phone object since the radio has been turned on
+ // successfully.
+ final Phone phone = getPhoneForAccount(request.getAccountHandle(),
+ isEmergencyNumber);
+ // If the PhoneType of the Phone being used is different than the Default
+ // Phone, then we need create a new Connection using that PhoneType and
+ // replace it in Telecom.
+ if (phone.getPhoneType() != defaultPhoneType) {
+ Connection repConnection = getTelephonyConnection(request, numberToDial,
+ isEmergencyNumber, emergencyHandle, phone);
+ // If there was a failure, the resulting connection will not be a
+ // TelephonyConnection, so don't place the call, just return!
+ if (repConnection instanceof TelephonyConnection) {
+ placeOutgoingConnection((TelephonyConnection) repConnection, phone,
+ request);
+ }
+ // Notify Telecom of the new Connection type.
+ // TODO: Switch out the underlying connection instead of creating a new
+ // one and causing UI Jank.
+ addExistingConnection(PhoneUtils.makePstnPhoneAccountHandle(phone),
+ repConnection);
+ // Remove the old connection from Telecom after.
+ emergencyConnection.setDisconnected(
+ DisconnectCauseUtil.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.OUTGOING_CANCELED,
+ "Reconnecting outgoing Emergency Call."));
+ emergencyConnection.destroy();
+ } else {
+ placeOutgoingConnection((TelephonyConnection) emergencyConnection,
+ phone, request);
+ }
+ } else {
+ Log.w(this, "onCreateOutgoingConnection, failed to turn on radio");
+ emergencyConnection.setDisconnected(
+ DisconnectCauseUtil.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.POWER_OFF,
+ "Failed to turn on radio."));
+ emergencyConnection.destroy();
+ }
+ }
+ });
+ // Return the still unconnected GsmConnection and wait for the Radios to boot before
+ // connecting it to the underlying Phone.
+ return emergencyConnection;
+ } else {
+ if (!canAddCall() && !isEmergencyNumber) {
+ Log.d(this, "onCreateOutgoingConnection, cannot add call .");
+ return Connection.createFailedConnection(
+ new DisconnectCause(DisconnectCause.ERROR,
+ getApplicationContext().getText(
+ R.string.incall_error_cannot_add_call),
+ getApplicationContext().getText(
+ R.string.incall_error_cannot_add_call),
+ "Add call restricted due to ongoing video call"));
+ }
+
+ // Get the right phone object from the account data passed in.
+ final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber);
+ Connection resultConnection = getTelephonyConnection(request, numberToDial,
+ isEmergencyNumber, handle, phone);
+ // If there was a failure, the resulting connection will not be a TelephonyConnection,
+ // so don't place the call!
+ if(resultConnection instanceof TelephonyConnection) {
+ placeOutgoingConnection((TelephonyConnection) resultConnection, phone, request);
+ }
+ return resultConnection;
+ }
+ }
+
+ /**
+ * @return {@code true} if any other call is disabling the ability to add calls, {@code false}
+ * otherwise.
+ */
+ private boolean canAddCall() {
+ Collection<Connection> connections = getAllConnections();
+ for (Connection connection : connections) {
+ if (connection.getExtras() != null &&
+ connection.getExtras().getBoolean(Connection.EXTRA_DISABLE_ADD_CALL, false)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private Connection getTelephonyConnection(final ConnectionRequest request, final String number,
+ boolean isEmergencyNumber, final Uri handle, Phone phone) {
+
if (phone == null) {
final Context context = getApplicationContext();
if (context.getResources().getBoolean(R.bool.config_checkSimStateBeforeOutgoingCall)) {
@@ -223,11 +368,12 @@
// when voice RAT is OOS but Data RAT is present.
int state = phone.getServiceState().getState();
if (state == ServiceState.STATE_OUT_OF_SERVICE) {
- if (phone.getServiceState().getDataNetworkType() == TelephonyManager.NETWORK_TYPE_LTE) {
+ int dataNetType = phone.getServiceState().getDataNetworkType();
+ if (dataNetType == TelephonyManager.NETWORK_TYPE_LTE ||
+ dataNetType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
state = phone.getServiceState().getDataRegState();
}
}
- boolean useEmergencyCallHelper = false;
// If we're dialing a non-emergency number and the phone is in ECM mode, reject the call if
// carrier configuration specifies that we cannot make non-emergency calls in ECM mode.
@@ -249,11 +395,7 @@
}
}
- if (isEmergencyNumber) {
- if (!phone.isRadioOn()) {
- useEmergencyCallHelper = true;
- }
- } else {
+ if (!isEmergencyNumber) {
switch (state) {
case ServiceState.STATE_IN_SERVICE:
case ServiceState.STATE_EMERGENCY_ONLY:
@@ -297,7 +439,7 @@
final TelephonyConnection connection =
createConnectionFor(phone, null, true /* isOutgoing */, request.getAccountHandle(),
- request.getTelecomCallId(), request.getAddress());
+ request.getTelecomCallId(), request.getAddress(), request.getVideoState());
if (connection == null) {
return Connection.createFailedConnection(
DisconnectCauseUtil.toTelecomDisconnectCause(
@@ -308,34 +450,6 @@
connection.setInitializing();
connection.setVideoState(request.getVideoState());
- if (useEmergencyCallHelper) {
- if (mEmergencyCallHelper == null) {
- mEmergencyCallHelper = new EmergencyCallHelper(this);
- }
- mEmergencyCallHelper.startTurnOnRadioSequence(phone,
- new EmergencyCallHelper.Callback() {
- @Override
- public void onComplete(boolean isRadioReady) {
- if (connection.getState() == Connection.STATE_DISCONNECTED) {
- // If the connection has already been disconnected, do nothing.
- } else if (isRadioReady) {
- connection.setInitialized();
- placeOutgoingConnection(connection, phone, request);
- } else {
- Log.d(this, "onCreateOutgoingConnection, failed to turn on radio");
- connection.setDisconnected(
- DisconnectCauseUtil.toTelecomDisconnectCause(
- android.telephony.DisconnectCause.POWER_OFF,
- "Failed to turn on radio."));
- connection.destroy();
- }
- }
- });
-
- } else {
- placeOutgoingConnection(connection, phone, request);
- }
-
return connection;
}
@@ -379,10 +493,15 @@
return Connection.createCanceledConnection();
}
+ // We should rely on the originalConnection to get the video state. The request coming
+ // from Telecom does not know the video state of the incoming call.
+ int videoState = originalConnection != null ? originalConnection.getVideoState() :
+ VideoProfile.STATE_AUDIO_ONLY;
+
Connection connection =
createConnectionFor(phone, originalConnection, false /* isOutgoing */,
request.getAccountHandle(), request.getTelecomCallId(),
- request.getAddress());
+ request.getAddress(), videoState);
if (connection == null) {
return Connection.createCanceledConnection();
} else {
@@ -479,11 +598,16 @@
return Connection.createCanceledConnection();
}
+ // We should rely on the originalConnection to get the video state. The request coming
+ // from Telecom does not know the video state of the unknown call.
+ int videoState = unknownConnection != null ? unknownConnection.getVideoState() :
+ VideoProfile.STATE_AUDIO_ONLY;
+
TelephonyConnection connection =
createConnectionFor(phone, unknownConnection,
!unknownConnection.isIncoming() /* isOutgoing */,
request.getAccountHandle(), request.getTelecomCallId(),
- request.getAddress());
+ request.getAddress(), videoState);
if (connection == null) {
return Connection.createCanceledConnection();
@@ -503,14 +627,86 @@
}
+ private boolean isRadioOn() {
+ boolean result = false;
+ for (Phone phone : PhoneFactory.getPhones()) {
+ result |= phone.isRadioOn();
+ }
+ return result;
+ }
+
+ private Pair<WeakReference<TelephonyConnection>, List<Phone>> makeCachedConnectionPhonePair(
+ TelephonyConnection c) {
+ List<Phone> phones = new ArrayList<>(Arrays.asList(PhoneFactory.getPhones()));
+ return new Pair<>(new WeakReference<>(c), phones);
+ }
+
+ // Check the mEmergencyRetryCache to see if it contains the TelephonyConnection. If it doesn't,
+ // then it is stale. Create a new one!
+ private void updateCachedConnectionPhonePair(TelephonyConnection c) {
+ if (mEmergencyRetryCache == null) {
+ Log.i(this, "updateCachedConnectionPhonePair, cache is null. Generating new cache");
+ mEmergencyRetryCache = makeCachedConnectionPhonePair(c);
+ } else {
+ // Check to see if old cache is stale. If it is, replace it
+ WeakReference<TelephonyConnection> cachedConnection = mEmergencyRetryCache.first;
+ if (cachedConnection.get() != c) {
+ Log.i(this, "updateCachedConnectionPhonePair, cache is stale. Regenerating.");
+ mEmergencyRetryCache = makeCachedConnectionPhonePair(c);
+ }
+ }
+ }
+
+ /**
+ * Returns the first Phone that has not been used yet to place the call. Any Phones that have
+ * been used to place a call will have already been removed from mEmergencyRetryCache.second.
+ * The phone that it excluded will be removed from mEmergencyRetryCache.second in this method.
+ * @param phoneToExclude The Phone object that will be removed from our cache of available
+ * phones.
+ * @return the first Phone that is available to be used to retry the call.
+ */
+ private Phone getPhoneForRedial(Phone phoneToExclude) {
+ List<Phone> cachedPhones = mEmergencyRetryCache.second;
+ if (cachedPhones.contains(phoneToExclude)) {
+ Log.i(this, "getPhoneForRedial, removing Phone[" + phoneToExclude.getPhoneId() +
+ "] from the available Phone cache.");
+ cachedPhones.remove(phoneToExclude);
+ }
+ return cachedPhones.isEmpty() ? null : cachedPhones.get(0);
+ }
+
+ private void retryOutgoingOriginalConnection(TelephonyConnection c) {
+ updateCachedConnectionPhonePair(c);
+ Phone newPhoneToUse = getPhoneForRedial(c.getPhone());
+ if (newPhoneToUse != null) {
+ int videoState = c.getVideoState();
+ Bundle connExtras = c.getExtras();
+ Log.i(this, "retryOutgoingOriginalConnection, redialing on Phone Id: " + newPhoneToUse);
+ c.clearOriginalConnection();
+ placeOutgoingConnection(c, newPhoneToUse, videoState, connExtras);
+ } else {
+ // We have run out of Phones to use. Disconnect the call and destroy the connection.
+ Log.i(this, "retryOutgoingOriginalConnection, no more Phones to use. Disconnecting.");
+ c.setDisconnected(new DisconnectCause(DisconnectCause.ERROR));
+ c.clearOriginalConnection();
+ c.destroy();
+ }
+ }
+
private void placeOutgoingConnection(
TelephonyConnection connection, Phone phone, ConnectionRequest request) {
+ placeOutgoingConnection(connection, phone, request.getVideoState(), request.getExtras());
+ }
+
+ private void placeOutgoingConnection(
+ TelephonyConnection connection, Phone phone, int videoState, Bundle extras) {
String number = connection.getAddress().getSchemeSpecificPart();
- com.android.internal.telephony.Connection originalConnection;
+ com.android.internal.telephony.Connection originalConnection = null;
try {
- originalConnection =
- phone.dial(number, null, request.getVideoState(), request.getExtras());
+ if (phone != null) {
+ originalConnection = phone.dial(number, null, videoState, extras);
+ }
} catch (CallStateException e) {
Log.e(this, e, "placeOutgoingConnection, phone.dial exception: " + e);
int cause = android.telephony.DisconnectCause.OUTGOING_FAILURE;
@@ -547,7 +743,8 @@
boolean isOutgoing,
PhoneAccountHandle phoneAccountHandle,
String telecomCallId,
- Uri address) {
+ Uri address,
+ int videoState) {
TelephonyConnection returnConnection = null;
int phoneType = phone.getPhoneType();
if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
@@ -563,11 +760,6 @@
returnConnection.setVideoPauseSupported(
TelecomAccountRegistry.getInstance(this).isVideoPauseSupported(
phoneAccountHandle));
- boolean isEmergencyCall = (address != null && PhoneNumberUtils.isEmergencyNumber(
- address.getSchemeSpecificPart()));
- returnConnection.setConferenceSupported(!isEmergencyCall
- && TelecomAccountRegistry.getInstance(this).isMergeCallSupported(
- phoneAccountHandle));
}
return returnConnection;
}
@@ -611,12 +803,11 @@
* list (for multi-SIM devices):
* 1) The User's SIM preference for Voice calling
* 2) The First Phone that is currently IN_SERVICE or is available for emergency calling
- * 3) The First Phone that has a SIM card in it (Starting from Slot 0...N)
- * 4) The Default Phone (Currently set as Slot 0)
+ * 3) The Phone with more Capabilities.
+ * 4) The First Phone that has a SIM card in it (Starting from Slot 0...N)
+ * 5) The Default Phone (Currently set as Slot 0)
*/
private Phone getFirstPhoneForEmergencyCall() {
- Phone firstPhoneWithSim = null;
-
// 1)
int phoneId = SubscriptionManager.getDefaultVoicePhoneId();
if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
@@ -626,32 +817,77 @@
}
}
- for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
+ Phone firstPhoneWithSim = null;
+ int phoneCount = TelephonyManager.getDefault().getPhoneCount();
+ List<Pair<Integer, Integer>> phoneNetworkType = new ArrayList<>(phoneCount);
+ for (int i = 0; i < phoneCount; i++) {
Phone phone = PhoneFactory.getPhone(i);
if (phone == null)
continue;
// 2)
if (isAvailableForEmergencyCalls(phone)) {
// the slot has the radio on & state is in service.
- Log.d(this, "getFirstPhoneForEmergencyCall, radio on & in service, Phone Id:" + i);
+ Log.i(this, "getFirstPhoneForEmergencyCall, radio on & in service, Phone Id:" + i);
return phone;
}
// 3)
+ // Store the RAF Capabilities for sorting later only if there are capabilities to sort.
+ int radioAccessFamily = phone.getRadioAccessFamily();
+ if(RadioAccessFamily.getHighestRafCapability(radioAccessFamily) != 0) {
+ phoneNetworkType.add(new Pair<>(i, radioAccessFamily));
+ Log.i(this, "getFirstPhoneForEmergencyCall, RAF:" +
+ Integer.toHexString(radioAccessFamily) + " saved for Phone Id:" + i);
+ }
+ // 4)
if (firstPhoneWithSim == null && TelephonyManager.getDefault().hasIccCard(i)) {
// The slot has a SIM card inserted, but is not in service, so keep track of this
// Phone. Do not return because we want to make sure that none of the other Phones
// are in service (because that is always faster).
- Log.d(this, "getFirstPhoneForEmergencyCall, SIM card inserted, Phone Id:" + i);
+ Log.i(this, "getFirstPhoneForEmergencyCall, SIM card inserted, Phone Id:" + i);
firstPhoneWithSim = phone;
}
}
- // 4)
- if (firstPhoneWithSim == null) {
+ // 5)
+ if (firstPhoneWithSim == null && phoneNetworkType.isEmpty()) {
// No SIMs inserted, get the default.
- Log.d(this, "getFirstPhoneForEmergencyCall, return default phone");
+ Log.i(this, "getFirstPhoneForEmergencyCall, return default phone");
return PhoneFactory.getDefaultPhone();
} else {
- return firstPhoneWithSim;
+ // 3)
+ final Phone firstOccupiedSlot = firstPhoneWithSim;
+ if (!phoneNetworkType.isEmpty()) {
+ // Only sort if there are enough elements to do so.
+ if(phoneNetworkType.size() > 1) {
+ Collections.sort(phoneNetworkType, (o1, o2) -> {
+ // First start by sorting by number of RadioAccessFamily Capabilities.
+ int compare = Integer.bitCount(o1.second) - Integer.bitCount(o2.second);
+ if (compare == 0) {
+ // Sort by highest RAF Capability if the number is the same.
+ compare = RadioAccessFamily.getHighestRafCapability(o1.second) -
+ RadioAccessFamily.getHighestRafCapability(o2.second);
+ if (compare == 0 && firstOccupiedSlot != null) {
+ // If the RAF capability is the same, choose based on whether or not
+ // any of the slots are occupied with a SIM card (if both are,
+ // always choose the first).
+ if (o1.first == firstOccupiedSlot.getPhoneId()) {
+ return 1;
+ } else if (o2.first == firstOccupiedSlot.getPhoneId()) {
+ return -1;
+ }
+ // Compare is still 0, return equal.
+ }
+ }
+ return compare;
+ });
+ }
+ int mostCapablePhoneId = phoneNetworkType.get(phoneNetworkType.size()-1).first;
+ Log.i(this, "getFirstPhoneForEmergencyCall, Using Phone Id: " + mostCapablePhoneId +
+ "with highest capability");
+ return PhoneFactory.getPhone(mostCapablePhoneId);
+ } else {
+ // 4)
+ return firstPhoneWithSim;
+ }
}
}
@@ -697,22 +933,32 @@
* @param connection The connection to be added to the controller
*/
public void addConnectionToConferenceController(TelephonyConnection connection) {
- // TODO: Do we need to handle the case of the original connection changing
- // and triggering this callback multiple times for the same connection?
- // If that is the case, we might want to remove this connection from all
- // conference controllers first before re-adding it.
+ // TODO: Need to revisit what happens when the original connection for the
+ // TelephonyConnection changes. If going from CDMA --> GSM (for example), the
+ // instance of TelephonyConnection will still be a CdmaConnection, not a GsmConnection.
+ // The CDMA conference controller makes the assumption that it will only have CDMA
+ // connections in it, while the other conference controllers aren't as restrictive. Really,
+ // when we go between CDMA and GSM we should replace the TelephonyConnection.
if (connection.isImsConnection()) {
Log.d(this, "Adding IMS connection to conference controller: " + connection);
mImsConferenceController.add(connection);
+ mTelephonyConferenceController.remove(connection);
+ if (connection instanceof CdmaConnection) {
+ mCdmaConferenceController.remove((CdmaConnection) connection);
+ }
} else {
int phoneType = connection.getCall().getPhone().getPhoneType();
if (phoneType == TelephonyManager.PHONE_TYPE_GSM) {
Log.d(this, "Adding GSM connection to conference controller: " + connection);
mTelephonyConferenceController.add(connection);
+ if (connection instanceof CdmaConnection) {
+ mCdmaConferenceController.remove((CdmaConnection) connection);
+ }
} else if (phoneType == TelephonyManager.PHONE_TYPE_CDMA &&
connection instanceof CdmaConnection) {
Log.d(this, "Adding CDMA connection to conference controller: " + connection);
- mCdmaConferenceController.add((CdmaConnection)connection);
+ mCdmaConferenceController.add((CdmaConnection) connection);
+ mTelephonyConferenceController.remove(connection);
}
Log.d(this, "Removing connection from IMS conference controller: " + connection);
mImsConferenceController.remove(connection);
diff --git a/tests/Android.mk b/tests/Android.mk
index 6cc0355..59cba42 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -25,6 +25,8 @@
LOCAL_MODULE_TAGS := tests
+LOCAL_JAVA_LIBRARIES := telephony-common android-support-test
+
LOCAL_INSTRUMENTATION_FOR := TeleService
LOCAL_STATIC_JAVA_LIBRARIES := \
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index 8900568..cae4c1b 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -62,17 +62,16 @@
</application>
<!--
- The prefered way is to use 'runtest':
- runtest phone-unit
+ To run all tests:
+ adb shell am instrument -w
+ com.android.phone.tests/android.support.test.runner.AndroidJUnitRunner
- runtest is a wrapper around 'adb shell'. The low level shell command is:
- adb shell am instrument -w com.android.phone.tests/android.test.InstrumentationTestRunner
+ To run a single class test:
+ adb shell am instrument -e class com.android.phone.unit.FooUnitTest
+ -w com.android.phone.tests/android.support.test.runner.AndroidJUnitRunner
- To run a single test case:
- adb shell am instrument -w com.android.phone.tests/android.test.InstrumentationTestRunner
- -e com.android.phone.unit.FooUnitTest
-->
- <instrumentation android:name="android.test.InstrumentationTestRunner"
+ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.phone"
android:label="Phone application tests." />
</manifest>
diff --git a/tests/src/com/android/TelephonyTestBase.java b/tests/src/com/android/TelephonyTestBase.java
new file mode 100644
index 0000000..6dee12b
--- /dev/null
+++ b/tests/src/com/android/TelephonyTestBase.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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 android.content.Context;
+import android.os.Handler;
+import android.support.test.InstrumentationRegistry;
+
+import com.android.phone.MockitoHelper;
+
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Helper class to load Mockito Resources into a test.
+ */
+public class TelephonyTestBase {
+
+ protected Context mContext;
+ MockitoHelper mMockitoHelper = new MockitoHelper();
+
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mMockitoHelper.setUp(mContext, getClass());
+ MockitoAnnotations.initMocks(this);
+ }
+
+ public void tearDown() throws Exception {
+ mMockitoHelper.tearDown();
+ }
+
+ protected final void waitForHandlerAction(Handler h, long timeoutMillis) {
+ final CountDownLatch lock = new CountDownLatch(1);
+ h.post(lock::countDown);
+ while (lock.getCount() > 0) {
+ try {
+ lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+ }
+
+ protected final void waitForHandlerActionDelayed(Handler h, long timeoutMillis, long delayMs) {
+ final CountDownLatch lock = new CountDownLatch(1);
+ h.postDelayed(lock::countDown, delayMs);
+ while (lock.getCount() > 0) {
+ try {
+ lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+ }
+}
diff --git a/tests/src/com/android/phone/MockitoHelper.java b/tests/src/com/android/phone/MockitoHelper.java
index 3da5d6e..7998030 100644
--- a/tests/src/com/android/phone/MockitoHelper.java
+++ b/tests/src/com/android/phone/MockitoHelper.java
@@ -16,6 +16,8 @@
package com.android.phone;
+import android.content.Context;
+
import com.android.services.telephony.Log;
/**
@@ -24,6 +26,7 @@
public final class MockitoHelper {
private static final String TAG = "MockitoHelper";
+ private static final String DEXCACHE = "dexmaker.dexcache";
private ClassLoader mOriginalClassLoader;
private Thread mContextThread;
@@ -34,7 +37,7 @@
*
* @param packageClass test case class
*/
- public void setUp(Class<?> packageClass) throws Exception {
+ public void setUp(Context context, Class<?> packageClass) throws Exception {
// makes a copy of the context classloader
mContextThread = Thread.currentThread();
mOriginalClassLoader = mContextThread.getContextClassLoader();
@@ -42,6 +45,9 @@
Log.v(TAG, "Changing context classloader from " + mOriginalClassLoader
+ " to " + newClassLoader);
mContextThread.setContextClassLoader(newClassLoader);
+ String dexCache = context.getCacheDir().toString();
+ Log.v(this, "Setting property %s to %s", DEXCACHE, dexCache);
+ System.setProperty(DEXCACHE, dexCache);
}
/**
@@ -50,5 +56,6 @@
public void tearDown() throws Exception {
Log.v(TAG, "Restoring context classloader to " + mOriginalClassLoader);
mContextThread.setContextClassLoader(mOriginalClassLoader);
+ System.clearProperty(DEXCACHE);
}
}
\ No newline at end of file
diff --git a/tests/src/com/android/phone/common/mail/MailTransportTest.java b/tests/src/com/android/phone/common/mail/MailTransportTest.java
index 6acd517..9eaef6b 100644
--- a/tests/src/com/android/phone/common/mail/MailTransportTest.java
+++ b/tests/src/com/android/phone/common/mail/MailTransportTest.java
@@ -61,7 +61,7 @@
@Override
public void setUp() throws Exception {
super.setUp();
- mMokitoHelper.setUp(getClass());
+ mMokitoHelper.setUp(getContext(), getClass());
MockitoAnnotations.initMocks(this);
}
diff --git a/tests/src/com/android/phone/common/mail/store/imap/DigestMd5UtilsTest.java b/tests/src/com/android/phone/common/mail/store/imap/DigestMd5UtilsTest.java
new file mode 100644
index 0000000..5534632
--- /dev/null
+++ b/tests/src/com/android/phone/common/mail/store/imap/DigestMd5UtilsTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 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.common.mail.store.imap;
+
+import junit.framework.TestCase;
+
+public class DigestMd5UtilsTest extends TestCase {
+
+ public void testGetResponse() {
+ // Example data from RFC 2831.4
+ DigestMd5Utils.Data data = new DigestMd5Utils.Data();
+ data.username = "chris";
+ data.password = "secret";
+ data.realm = "elwood.innosoft.com";
+ data.nonce = "OA6MG9tEQGm2hh";
+ data.cnonce = "OA6MHXh6VqTrRk";
+ data.nc = "00000001";
+ data.qop = "auth";
+ data.digestUri = "imap/elwood.innosoft.com";
+ String response = DigestMd5Utils.getResponse(data, false);
+ assertEquals("d388dad90d4bbd760a152321f2143af7", response);
+ }
+
+ public void testGetResponse_ResponseAuth() {
+ // Example data from RFC 2831.4
+ DigestMd5Utils.Data data = new DigestMd5Utils.Data();
+ data.username = "chris";
+ data.password = "secret";
+ data.realm = "elwood.innosoft.com";
+ data.nonce = "OA6MG9tEQGm2hh";
+ data.cnonce = "OA6MHXh6VqTrRk";
+ data.nc = "00000001";
+ data.qop = "auth";
+ data.digestUri = "imap/elwood.innosoft.com";
+ String response = DigestMd5Utils.getResponse(data, true);
+ assertEquals("ea40f60335c427b5527b84dbabcdfffd", response);
+ }
+
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiverTests.java b/tests/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiverTests.java
deleted file mode 100644
index 1924d9f..0000000
--- a/tests/src/com/android/phone/vvm/omtp/OmtpBootCompletedReceiverTests.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2016 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.vvm.omtp;
-
-import android.content.Context;
-import android.content.Intent;
-import android.preference.PreferenceManager;
-import android.test.AndroidTestCase;
-import android.util.ArraySet;
-
-import com.android.phone.vvm.omtp.OmtpBootCompletedReceiver.SubIdProcessor;
-
-import java.util.Set;
-
-public class OmtpBootCompletedReceiverTests extends AndroidTestCase {
- OmtpBootCompletedReceiver mReceiver = new OmtpBootCompletedReceiver();
- @Override
- public void setUp() {
- }
-
- @Override
- public void tearDown() {
- PreferenceManager
- .getDefaultSharedPreferences(getContext().createDeviceProtectedStorageContext())
- .edit().clear().apply();
- }
-
- public void testReadWriteList() {
- readWriteList(new int[] {1});
- }
-
- public void testReadWriteList_Multiple() {
- readWriteList(new int[] {1, 2});
- }
-
- public void testReadWriteList_Duplicate() {
- readWriteList(new int[] {1, 1});
- }
-
- private void readWriteList(int[] values) {
- for (int value : values) {
- OmtpBootCompletedReceiver.addDeferredSubId(getContext(), value);
- }
- TestSubIdProcessor processor = new TestSubIdProcessor(values);
- mReceiver.setSubIdProcessorForTest(processor);
- Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
- mReceiver.onReceive(getContext(), intent);
- processor.assertMatch();
- // after onReceive() is called the list should be empty
- TestSubIdProcessor emptyProcessor = new TestSubIdProcessor(new int[] {});
- mReceiver.setSubIdProcessorForTest(processor);
- mReceiver.onReceive(getContext(), intent);
- processor.assertMatch();
- }
-
- private static class TestSubIdProcessor implements SubIdProcessor {
- private final Set<Integer> mExpectedSubIds;
-
- public TestSubIdProcessor(int[] expectedSubIds) {
- mExpectedSubIds = new ArraySet<>();
- for(int subId : expectedSubIds){
- mExpectedSubIds.add(subId);
- }
- }
-
- @Override
- public void process(Context context, int subId){
- assertTrue(mExpectedSubIds.contains(subId));
- mExpectedSubIds.remove(subId);
- }
-
- public void assertMatch(){
- assertTrue(mExpectedSubIds.isEmpty());
- }
- }
-}
diff --git a/tests/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelperTest.java b/tests/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelperTest.java
new file mode 100644
index 0000000..bc0192c
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/OmtpVvmCarrierConfigHelperTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_CARRIER_VVM_PACKAGE_NAME_STRING;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_DESTINATION_NUMBER_STRING;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_PORT_NUMBER_INT;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_PREFETCH_BOOL;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_SSL_PORT_NUMBER_INT;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_TYPE_STRING;
+
+import android.os.PersistableBundle;
+import android.test.AndroidTestCase;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public class OmtpVvmCarrierConfigHelperTest extends AndroidTestCase {
+
+ private static final String CARRIER_TYPE = "omtp.carrier";
+ private static final String CARRIER_PACKAGE_NAME = "omtp.carrier.package";
+ private static final boolean CARRIER_CELLULAR_REQUIRED = false;
+ private static final boolean CARRIER_PREFETCH = true;
+ private static final String CARRIER_DESTINATION_NUMBER = "123";
+ private static final int CARRIER_APPLICATION_PORT = 456;
+ private static final int DEFAULT_SSL_PORT = 0;
+ private static final Set<String> DEFAULT_DISABLED_CAPABILITIES = null;
+
+ private static final String TELEPHONY_TYPE = "omtp.telephony";
+ private static final String[] TELEPHONY_PACKAGE_NAMES = {"omtp.telephony.package"};
+ private static final boolean TELEPHONY_CELLULAR_REQUIRED = true;
+ private static final boolean TELEPHONY_PREFETCH = false;
+ private static final String TELEPHONY_DESTINATION_NUMBER = "321";
+ private static final int TELEPHONY_APPLICATION_PORT = 654;
+ private static final int TELEPHONY_SSL_PORT = 997;
+ private static final String[] TELEPHONY_DISABLED_CAPABILITIES = {"foo"};
+
+ private OmtpVvmCarrierConfigHelper mHelper;
+
+ public void testCarrierConfig() {
+ mHelper = new OmtpVvmCarrierConfigHelper(getContext(), createCarrierConfig(), null);
+ verifyCarrierConfig();
+ verifyDefaultExtraConfig();
+ }
+
+ public void testTelephonyConfig() {
+ mHelper = new OmtpVvmCarrierConfigHelper(getContext(), null, createTelephonyConfig());
+ verifyTelephonyConfig();
+ verifyTelephonyExtraConfig();
+ }
+
+ public void testMixedConfig() {
+ mHelper = new OmtpVvmCarrierConfigHelper(getContext(), createCarrierConfig(),
+ createTelephonyConfig());
+ verifyCarrierConfig();
+ verifyTelephonyExtraConfig();
+ }
+
+ private PersistableBundle createCarrierConfig() {
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putString(KEY_VVM_TYPE_STRING, CARRIER_TYPE);
+ bundle.putString(KEY_CARRIER_VVM_PACKAGE_NAME_STRING,
+ CARRIER_PACKAGE_NAME);
+ bundle.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL,
+ CARRIER_CELLULAR_REQUIRED);
+ bundle.putBoolean(KEY_VVM_PREFETCH_BOOL,
+ CARRIER_PREFETCH);
+ bundle.putString(KEY_VVM_DESTINATION_NUMBER_STRING,
+ CARRIER_DESTINATION_NUMBER);
+ bundle.putInt(KEY_VVM_PORT_NUMBER_INT, CARRIER_APPLICATION_PORT);
+ return bundle;
+ }
+
+ private void verifyCarrierConfig() {
+ assertEquals(CARRIER_TYPE, mHelper.getVvmType());
+ assertEquals(new HashSet<>(Arrays.asList(CARRIER_PACKAGE_NAME)),
+ mHelper.getCarrierVvmPackageNames());
+ assertEquals(CARRIER_CELLULAR_REQUIRED, mHelper.isCellularDataRequired());
+ assertEquals(CARRIER_PREFETCH, mHelper.isPrefetchEnabled());
+ assertEquals(CARRIER_APPLICATION_PORT, mHelper.getApplicationPort());
+ assertEquals(CARRIER_DESTINATION_NUMBER, mHelper.getDestinationNumber());
+ }
+
+
+ private void verifyDefaultExtraConfig() {
+ assertEquals(DEFAULT_SSL_PORT, mHelper.getSslPort());
+ assertEquals(DEFAULT_DISABLED_CAPABILITIES, mHelper.getDisabledCapabilities());
+ }
+
+
+ private PersistableBundle createTelephonyConfig() {
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putString(KEY_VVM_TYPE_STRING, TELEPHONY_TYPE);
+ bundle.putStringArray(KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY,
+ TELEPHONY_PACKAGE_NAMES);
+ bundle.putBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL,
+ TELEPHONY_CELLULAR_REQUIRED);
+ bundle.putBoolean(KEY_VVM_PREFETCH_BOOL,
+ TELEPHONY_PREFETCH);
+ bundle.putString(KEY_VVM_DESTINATION_NUMBER_STRING,
+ TELEPHONY_DESTINATION_NUMBER);
+ bundle.putInt(KEY_VVM_PORT_NUMBER_INT, TELEPHONY_APPLICATION_PORT);
+ bundle.putInt(KEY_VVM_SSL_PORT_NUMBER_INT, TELEPHONY_SSL_PORT);
+ bundle.putStringArray(KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY,
+ TELEPHONY_DISABLED_CAPABILITIES);
+ return bundle;
+ }
+
+ private void verifyTelephonyConfig() {
+ assertEquals(TELEPHONY_TYPE, mHelper.getVvmType());
+ assertEquals(new HashSet<>(Arrays.asList(TELEPHONY_PACKAGE_NAMES)),
+ mHelper.getCarrierVvmPackageNames());
+ assertEquals(TELEPHONY_CELLULAR_REQUIRED, mHelper.isCellularDataRequired());
+ assertEquals(TELEPHONY_PREFETCH, mHelper.isPrefetchEnabled());
+ assertEquals(TELEPHONY_APPLICATION_PORT, mHelper.getApplicationPort());
+ assertEquals(TELEPHONY_DESTINATION_NUMBER, mHelper.getDestinationNumber());
+ }
+
+ private void verifyTelephonyExtraConfig() {
+ assertEquals(TELEPHONY_SSL_PORT, mHelper.getSslPort());
+ assertEquals(new HashSet<>(Arrays.asList(TELEPHONY_DISABLED_CAPABILITIES)),
+ mHelper.getDisabledCapabilities());
+ }
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/StatusMessageTest.java b/tests/src/com/android/phone/vvm/omtp/StatusMessageTest.java
new file mode 100644
index 0000000..707463a
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/StatusMessageTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.os.Bundle;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.phone.vvm.omtp.sms.StatusMessage;
+
+import junit.framework.TestCase;
+
+@VisibleForTesting
+public class StatusMessageTest extends TestCase {
+
+ public void testStatusMessage() {
+ Bundle bundle = new Bundle();
+ bundle.putString(OmtpConstants.PROVISIONING_STATUS, "status");
+ bundle.putString(OmtpConstants.RETURN_CODE, "code");
+ bundle.putString(OmtpConstants.SUBSCRIPTION_URL, "url");
+ bundle.putString(OmtpConstants.SERVER_ADDRESS, "address");
+ bundle.putString(OmtpConstants.TUI_ACCESS_NUMBER, "tui");
+ bundle.putString(OmtpConstants.CLIENT_SMS_DESTINATION_NUMBER, "sms");
+ bundle.putString(OmtpConstants.IMAP_PORT, "1234");
+ bundle.putString(OmtpConstants.IMAP_USER_NAME, "username");
+ bundle.putString(OmtpConstants.IMAP_PASSWORD, "password");
+ bundle.putString(OmtpConstants.SMTP_PORT, "s1234");
+ bundle.putString(OmtpConstants.SMTP_USER_NAME, "susername");
+ bundle.putString(OmtpConstants.SMTP_PASSWORD, "spassword");
+ bundle.putString(OmtpConstants.TUI_PASSWORD_LENGTH, "4-7");
+
+ StatusMessage message = new StatusMessage(bundle);
+ assertEquals("status", message.getProvisioningStatus());
+ assertEquals("code", message.getReturnCode());
+ assertEquals("url", message.getSubscriptionUrl());
+ assertEquals("address", message.getServerAddress());
+ assertEquals("tui", message.getTuiAccessNumber());
+ assertEquals("sms", message.getClientSmsDestinationNumber());
+ assertEquals("1234", message.getImapPort());
+ assertEquals("username", message.getImapUserName());
+ assertEquals("password", message.getImapPassword());
+ assertEquals("s1234", message.getSmtpPort());
+ assertEquals("susername", message.getSmtpUserName());
+ assertEquals("spassword", message.getSmtpPassword());
+ assertEquals("4-7", message.getTuiPasswordLength());
+ }
+
+ public void testSyncMessage_EmptyBundle() {
+ StatusMessage message = new StatusMessage(new Bundle());
+ assertEquals("", message.getProvisioningStatus());
+ assertEquals("", message.getReturnCode());
+ assertEquals("", message.getSubscriptionUrl());
+ assertEquals("", message.getServerAddress());
+ assertEquals("", message.getTuiAccessNumber());
+ assertEquals("", message.getClientSmsDestinationNumber());
+ assertEquals("", message.getImapPort());
+ assertEquals("", message.getImapUserName());
+ assertEquals("", message.getImapPassword());
+ assertEquals("", message.getSmtpPort());
+ assertEquals("", message.getSmtpUserName());
+ assertEquals("", message.getSmtpPassword());
+ assertEquals("", message.getTuiPasswordLength());
+ }
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/SyncMessageTest.java b/tests/src/com/android/phone/vvm/omtp/SyncMessageTest.java
new file mode 100644
index 0000000..61ae400
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/SyncMessageTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import android.os.Bundle;
+
+import com.android.phone.vvm.omtp.sms.SyncMessage;
+
+import junit.framework.TestCase;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+public class SyncMessageTest extends TestCase {
+
+ public void testSyncMessage() {
+ Bundle bundle = new Bundle();
+ bundle.putString(OmtpConstants.SYNC_TRIGGER_EVENT, "event");
+ bundle.putString(OmtpConstants.MESSAGE_UID, "uid");
+ bundle.putString(OmtpConstants.MESSAGE_LENGTH, "1");
+ bundle.putString(OmtpConstants.CONTENT_TYPE, "type");
+ bundle.putString(OmtpConstants.SENDER, "sender");
+ bundle.putString(OmtpConstants.NUM_MESSAGE_COUNT, "2");
+ bundle.putString(OmtpConstants.TIME, "29/08/1997 02:14 -0400");
+
+ SyncMessage message = new SyncMessage(bundle);
+ assertEquals("event", message.getSyncTriggerEvent());
+ assertEquals("uid", message.getId());
+ assertEquals(1, message.getLength());
+ assertEquals("type", message.getContentType());
+ assertEquals("sender", message.getSender());
+ assertEquals(2, message.getNewMessageCount());
+ try {
+ assertEquals(new SimpleDateFormat(
+ OmtpConstants.DATE_TIME_FORMAT, Locale.US)
+ .parse("29/08/1997 02:14 -0400").getTime(), message.getTimestampMillis());
+ } catch (ParseException e) {
+ throw new AssertionError(e.toString());
+ }
+ }
+
+ public void testSyncMessage_EmptyBundle() {
+ SyncMessage message = new SyncMessage(new Bundle());
+ assertEquals("", message.getSyncTriggerEvent());
+ assertEquals("", message.getId());
+ assertEquals(0, message.getLength());
+ assertEquals("", message.getContentType());
+ assertEquals("", message.getSender());
+ assertEquals(0, message.getNewMessageCount());
+ assertEquals(0, message.getTimestampMillis());
+ }
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/TelephonyVvmConfigManagerTest.java b/tests/src/com/android/phone/vvm/omtp/TelephonyVvmConfigManagerTest.java
new file mode 100644
index 0000000..8e7a0da
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/TelephonyVvmConfigManagerTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp;
+
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_DESTINATION_NUMBER_STRING;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_PORT_NUMBER_INT;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_PREFETCH_BOOL;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_SSL_PORT_NUMBER_INT;
+import static com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper.KEY_VVM_TYPE_STRING;
+
+import android.os.PersistableBundle;
+
+import junit.framework.TestCase;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.StringReader;
+import java.util.Arrays;
+
+public class TelephonyVvmConfigManagerTest extends TestCase {
+
+ private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+ + "<list name=\"carrier_config_list\">\n";
+ private static final String XML_FOOTER = "</list>";
+
+ private static final String CARRIER = " <pbundle_as_map>\n"
+ + " <string-array name=\"mccmnc\">\n"
+ + " <item value=\"12345\"/>\n"
+ + " <item value=\"67890\"/>\n"
+ + " </string-array>\n"
+ + " <int name=\"vvm_port_number_int\" value=\"54321\"/>\n"
+ + " <string name=\"vvm_destination_number_string\">11111</string>\n"
+ + " <string-array name=\"carrier_vvm_package_name_string_array\">\n"
+ + " <item value=\"com.android.phone\"/>\n"
+ + " </string-array>\n"
+ + " <string name=\"vvm_type_string\">vvm_type_omtp</string>\n"
+ + " <boolean name=\"vvm_cellular_data_required\" value=\"true\"/>\n"
+ + " <boolean name=\"vvm_prefetch\" value=\"true\"/>\n"
+ + " <int name=\"vvm_ssl_port_number_int\" value=\"997\"/>\n"
+ + " <string-array name=\"vvm_disabled_capabilities_string_array\">\n"
+ + " <item value =\"foo\"/>\n"
+ + " <item value =\"bar\"/>\n"
+ + " </string-array>\n"
+ + " </pbundle_as_map>\n";
+
+ private static final String CARRIER_EMPTY = "<pbundle_as_map></pbundle_as_map>\n";
+
+
+ public void testLoadConfigFromXml() {
+ TelephonyVvmConfigManager manager = createManager(XML_HEADER + CARRIER + XML_FOOTER);
+ verifyCarrier(manager.getConfig("12345"));
+ verifyCarrier(manager.getConfig("67890"));
+ }
+
+ public void testLoadConfigFromXml_Multiple() {
+ TelephonyVvmConfigManager manager =
+ createManager(XML_HEADER + CARRIER + CARRIER + XML_FOOTER);
+ verifyCarrier(manager.getConfig("12345"));
+ verifyCarrier(manager.getConfig("67890"));
+ }
+
+ public void testLoadConfigFromXml_Empty() {
+ createManager(XML_HEADER + CARRIER_EMPTY + XML_FOOTER);
+ }
+
+
+ private void verifyCarrier(PersistableBundle config) {
+ assertTrue(Arrays.equals(new String[]{"12345", "67890"},
+ config.getStringArray(TelephonyVvmConfigManager.KEY_MCCMNC)));
+ assertEquals(54321, config.getInt(KEY_VVM_PORT_NUMBER_INT));
+ assertEquals("11111", config.getString(KEY_VVM_DESTINATION_NUMBER_STRING));
+ assertTrue(Arrays.equals(new String[]{"com.android.phone"},
+ config.getStringArray(KEY_CARRIER_VVM_PACKAGE_NAME_STRING_ARRAY)));
+ assertEquals("vvm_type_omtp", config.getString(KEY_VVM_TYPE_STRING));
+ assertEquals(true, config.getBoolean(KEY_VVM_PREFETCH_BOOL));
+ assertEquals(true, config.getBoolean(KEY_VVM_CELLULAR_DATA_REQUIRED_BOOL));
+ assertEquals(997, config.getInt(KEY_VVM_SSL_PORT_NUMBER_INT));
+ assertTrue(Arrays.equals(new String[]{"foo", "bar"},
+ config.getStringArray(KEY_VVM_DISABLED_CAPABILITIES_STRING_ARRAY)));
+ }
+
+ private TelephonyVvmConfigManager createManager(String xml) {
+ try {
+ XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
+ parser.setInput(new StringReader(xml));
+ return new TelephonyVvmConfigManager(parser);
+ } catch (XmlPullParserException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/VisualVoicemailPreferencesTest.java b/tests/src/com/android/phone/vvm/omtp/VisualVoicemailPreferencesTest.java
new file mode 100644
index 0000000..1ae7899
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/VisualVoicemailPreferencesTest.java
@@ -0,0 +1,81 @@
+package com.android.phone.vvm.omtp;
+
+import android.content.ComponentName;
+import android.telecom.PhoneAccountHandle;
+import android.test.AndroidTestCase;
+import android.util.ArraySet;
+
+import java.util.Arrays;
+
+public class VisualVoicemailPreferencesTest extends AndroidTestCase {
+
+ public void testWriteRead() {
+ VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(getContext(),
+ createFakeHandle("testWriteRead"));
+ preferences.edit()
+ .putBoolean("boolean", true)
+ .putFloat("float", 0.5f)
+ .putInt("int", 123)
+ .putLong("long", 456)
+ .putString("string", "foo")
+ .putStringSet("stringset", new ArraySet<>(Arrays.asList("bar", "baz")))
+ .apply();
+
+ assertTrue(preferences.contains("boolean"));
+ assertTrue(preferences.contains("float"));
+ assertTrue(preferences.contains("int"));
+ assertTrue(preferences.contains("long"));
+ assertTrue(preferences.contains("string"));
+ assertTrue(preferences.contains("stringset"));
+
+ assertEquals(true, preferences.getBoolean("boolean", false));
+ assertEquals(0.5f, preferences.getFloat("float", 0));
+ assertEquals(123, preferences.getInt("int", 0));
+ assertEquals(456, preferences.getLong("long", 0));
+ assertEquals("foo", preferences.getString("string", null));
+ assertEquals(new ArraySet<>(Arrays.asList("bar", "baz")),
+ preferences.getStringSet("stringset", null));
+ }
+
+ public void testReadDefault() {
+ VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(getContext(),
+ createFakeHandle("testReadDefault"));
+
+ assertFalse(preferences.contains("boolean"));
+ assertFalse(preferences.contains("float"));
+ assertFalse(preferences.contains("int"));
+ assertFalse(preferences.contains("long"));
+ assertFalse(preferences.contains("string"));
+ assertFalse(preferences.contains("stringset"));
+
+ assertEquals(true, preferences.getBoolean("boolean", true));
+ assertEquals(2.5f, preferences.getFloat("float", 2.5f));
+ assertEquals(321, preferences.getInt("int", 321));
+ assertEquals(654, preferences.getLong("long", 654));
+ assertEquals("foo2", preferences.getString("string", "foo2"));
+ assertEquals(new ArraySet<>(Arrays.asList("bar2", "baz2")),
+ preferences.getStringSet(
+ "stringset", new ArraySet<>(Arrays.asList("bar2", "baz2"))));
+ }
+
+ public void testReadDefaultNull() {
+ VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(getContext(),
+ createFakeHandle("testReadDefaultNull"));
+ assertNull(preferences.getString("string", null));
+ assertNull(preferences.getStringSet("stringset", null));
+ }
+
+ public void testDifferentHandle() {
+ VisualVoicemailPreferences preferences1 = new VisualVoicemailPreferences(getContext(),
+ createFakeHandle("testDifferentHandle1"));
+ VisualVoicemailPreferences preferences2 = new VisualVoicemailPreferences(getContext(),
+ createFakeHandle("testDifferentHandle1"));
+
+ preferences1.edit().putString("string", "foo");
+ assertFalse(preferences2.contains("string"));
+ }
+
+ private PhoneAccountHandle createFakeHandle(String id) {
+ return new PhoneAccountHandle(new ComponentName(getContext(), this.getClass()), id);
+ }
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/scheduling/BaseTaskTest.java b/tests/src/com/android/phone/vvm/omtp/scheduling/BaseTaskTest.java
new file mode 100644
index 0000000..27dd87e
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/scheduling/BaseTaskTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.phone.vvm.omtp.scheduling.Task.TaskId;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class BaseTaskTest extends BaseTaskTestBase {
+
+
+ @Test
+ public void testBaseTask() {
+ DummyBaseTask task = (DummyBaseTask) submitTask(
+ BaseTask.createIntent(mTestContext, DummyBaseTask.class, 123));
+ assertTrue(task.getId().equals(new TaskId(1, 123)));
+ assertTrue(!task.hasStarted());
+ assertTrue(!task.hasRun);
+ mService.runNextTask();
+ assertTrue(task.hasStarted());
+ assertTrue(task.hasRun);
+ verify(task.policy).onBeforeExecute();
+ verify(task.policy).onCompleted();
+ }
+
+ @Test
+ public void testFail() {
+ FailingBaseTask task = (FailingBaseTask) submitTask(
+ BaseTask.createIntent(mTestContext, FailingBaseTask.class, 0));
+ mService.runNextTask();
+ verify(task.policy).onFail();
+ }
+
+ @Test
+ public void testDuplicated() {
+ DummyBaseTask task1 = (DummyBaseTask) submitTask(
+ BaseTask.createIntent(mTestContext, DummyBaseTask.class, 123));
+ verify(task1.policy, never()).onDuplicatedTaskAdded();
+
+ DummyBaseTask task2 = (DummyBaseTask) submitTask(
+ BaseTask.createIntent(mTestContext, DummyBaseTask.class, 123));
+ verify(task1.policy).onDuplicatedTaskAdded();
+
+ mService.runNextTask();
+ assertTrue(task1.hasRun);
+ assertTrue(!task2.hasRun);
+ }
+
+ @Test
+ public void testDuplicated_DifferentSubId() {
+ DummyBaseTask task1 = (DummyBaseTask) submitTask(
+ BaseTask.createIntent(mTestContext, DummyBaseTask.class, 123));
+ verify(task1.policy, never()).onDuplicatedTaskAdded();
+
+ DummyBaseTask task2 = (DummyBaseTask) submitTask(
+ BaseTask.createIntent(mTestContext, DummyBaseTask.class, 456));
+ verify(task1.policy, never()).onDuplicatedTaskAdded();
+ mService.runNextTask();
+ assertTrue(task1.hasRun);
+ assertTrue(!task2.hasRun);
+
+ mService.runNextTask();
+ assertTrue(task2.hasRun);
+ }
+
+ @Test
+ public void testReadyTime() {
+ BaseTask task = spy(new DummyBaseTask());
+ assertTrue(task.getReadyInMilliSeconds() == 0);
+ mTime = 500;
+ assertTrue(task.getReadyInMilliSeconds() == -500);
+ task.setExecutionTime(1000);
+ assertTrue(task.getReadyInMilliSeconds() == 500);
+ }
+
+ public static class DummyBaseTask extends BaseTask {
+
+ public Policy policy;
+ public boolean hasRun = false;
+
+ public DummyBaseTask() {
+ super(1);
+ policy = mock(Policy.class);
+ addPolicy(policy);
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ hasRun = true;
+ }
+ }
+
+ public static class FailingBaseTask extends BaseTask {
+
+ public Policy policy;
+ public FailingBaseTask() {
+ super(1);
+ policy = mock(Policy.class);
+ addPolicy(policy);
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ fail();
+ }
+ }
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/scheduling/BaseTaskTestBase.java b/tests/src/com/android/phone/vvm/omtp/scheduling/BaseTaskTestBase.java
new file mode 100644
index 0000000..1ffd3c4
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/scheduling/BaseTaskTestBase.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import com.android.phone.vvm.omtp.scheduling.BaseTask.Clock;
+
+import org.junit.After;
+import org.junit.Before;
+
+public class BaseTaskTestBase extends TaskSchedulerServiceTestBase {
+
+ /**
+ * "current time" of the deterministic clock.
+ */
+ public long mTime;
+
+ @Before
+ public void setUpBaseTaskTest() {
+ mTime = 0;
+ BaseTask.setClockForTesting(new TestClock());
+ }
+
+ @After
+ public void tearDownBaseTaskTest() {
+ BaseTask.setClockForTesting(new Clock());
+ }
+
+
+ private class TestClock extends Clock {
+
+ @Override
+ public long getTimeMillis() {
+ return mTime;
+ }
+ }
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/scheduling/PolicyTest.java b/tests/src/com/android/phone/vvm/omtp/scheduling/PolicyTest.java
new file mode 100644
index 0000000..9761d01
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/scheduling/PolicyTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class PolicyTest extends BaseTaskTestBase {
+
+ private static int sExecuteCounter;
+
+ @Before
+ public void setUpPolicyTest() {
+ sExecuteCounter = 0;
+ }
+
+ @Test
+ public void testPostponePolicy() {
+ Task task = submitTask(BaseTask.createIntent(mTestContext, PostponeTask.class, 0));
+ mService.runNextTask();
+ assertTrue(task.getReadyInMilliSeconds() == 1000);
+ submitTask(BaseTask.createIntent(mTestContext, PostponeTask.class, 0));
+ assertTrue(task.getReadyInMilliSeconds() == 1000);
+ mTime = 500;
+ submitTask(BaseTask.createIntent(mTestContext, PostponeTask.class, 0));
+ assertTrue(task.getReadyInMilliSeconds() == 1000);
+ mTime = 2500;
+ mService.runNextTask();
+ assertTrue(sExecuteCounter == 1);
+ }
+
+ @Test
+ public void testRetryPolicy() {
+ Task task = submitTask(BaseTask.createIntent(mTestContext, FailingRetryTask.class, 0));
+ mService.runNextTask();
+ // Should queue retry at 1000
+ assertTrue(sExecuteCounter == 1);
+ mService.runNextTask();
+ assertTrue(sExecuteCounter == 1);
+ mTime = 1500;
+ mService.runNextTask();
+ // Should queue retry at 2500
+ assertTrue(sExecuteCounter == 2);
+ mService.runNextTask();
+ assertTrue(sExecuteCounter == 2);
+ mTime = 2000;
+ mService.runNextTask();
+ assertTrue(sExecuteCounter == 2);
+ mTime = 3000;
+ mService.runNextTask();
+ // No more retries are queued.
+ assertTrue(sExecuteCounter == 3);
+ mService.runNextTask();
+ assertTrue(sExecuteCounter == 3);
+ mTime = 4500;
+ mService.runNextTask();
+ assertTrue(sExecuteCounter == 3);
+ }
+
+ @Test
+ public void testMinimalIntervalPolicy() {
+ MinimalIntervalPolicyTask task1 = (MinimalIntervalPolicyTask) submitTask(
+ BaseTask.createIntent(mTestContext, MinimalIntervalPolicyTask.class, 0));
+ mService.runNextTask();
+ assertTrue(task1.hasRan);
+ MinimalIntervalPolicyTask task2 = (MinimalIntervalPolicyTask) submitTask(
+ BaseTask.createIntent(mTestContext, MinimalIntervalPolicyTask.class, 0));
+ mService.runNextTask();
+ assertTrue(!task2.hasRan);
+
+ mTime = 1500;
+ mService.runNextTask();
+
+ MinimalIntervalPolicyTask task3 = (MinimalIntervalPolicyTask) submitTask(
+ BaseTask.createIntent(mTestContext, MinimalIntervalPolicyTask.class, 0));
+ mService.runNextTask();
+ assertTrue(task3.hasRan);
+ }
+
+ public abstract static class PolicyTestTask extends BaseTask {
+
+ public PolicyTestTask() {
+ super(1);
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ sExecuteCounter++;
+ }
+ }
+
+ public static class PostponeTask extends PolicyTestTask {
+
+ PostponeTask() {
+ addPolicy(new PostponePolicy(1000));
+ }
+ }
+
+ public static class FailingRetryTask extends PolicyTestTask {
+
+ public FailingRetryTask() {
+ addPolicy(new RetryPolicy(2, 1000));
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ super.onExecuteInBackgroundThread();
+ fail();
+ }
+ }
+
+ public static class MinimalIntervalPolicyTask extends PolicyTestTask {
+
+ boolean hasRan;
+
+ MinimalIntervalPolicyTask() {
+ addPolicy(new MinimalIntervalPolicy(1000));
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ super.onExecuteInBackgroundThread();
+ hasRan = true;
+ }
+ }
+
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerServiceTest.java b/tests/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerServiceTest.java
new file mode 100644
index 0000000..2dd4ecf
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerServiceTest.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.phone.vvm.omtp.scheduling.Task.TaskId;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class TaskSchedulerServiceTest extends TaskSchedulerServiceTestBase {
+
+ @Test
+ public void testTaskIdComparison() {
+ TaskId id1 = new TaskId(1, 1);
+ TaskId id2 = new TaskId(1, 1);
+ TaskId id3 = new TaskId(1, 2);
+ assertTrue(id1.equals(id2));
+ assertTrue(id1.equals(id1));
+ assertTrue(!id1.equals(id3));
+ }
+
+ @Test
+ public void testAddDuplicatedTask() throws TimeoutException {
+ TestTask task1 = (TestTask) submitTask(
+ TaskSchedulerService.createIntent(mTestContext, TestTask.class));
+ TestTask task2 = (TestTask) submitTask(
+ TaskSchedulerService.createIntent(mTestContext, TestTask.class));
+ assertTrue(task1.onDuplicatedTaskAddedCounter.invokedOnce());
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ verifyNotRan(task2);
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ verifyNotRan(task2);
+ }
+
+ @Test
+ public void testAddDuplicatedTaskAfterFirstCompleted() throws TimeoutException {
+ TestTask task1 = (TestTask) submitTask(
+ TaskSchedulerService.createIntent(mTestContext, TestTask.class));
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ TestTask task2 = (TestTask) submitTask(
+ TaskSchedulerService.createIntent(mTestContext, TestTask.class));
+ assertTrue(task1.onDuplicatedTaskAddedCounter.neverInvoked());
+ mService.runNextTask();
+ verifyRanOnce(task2);
+ }
+
+ @Test
+ public void testAddMultipleTask() {
+ TestTask task1 = (TestTask) submitTask(
+ putTaskId(TaskSchedulerService.createIntent(mTestContext, TestTask.class),
+ new TaskId(1, 0)));
+ TestTask task2 = (TestTask) submitTask(
+ putTaskId(TaskSchedulerService.createIntent(mTestContext, TestTask.class),
+ new TaskId(2, 0)));
+ TestTask task3 = (TestTask) submitTask(
+ putTaskId(TaskSchedulerService.createIntent(mTestContext, TestTask.class),
+ new TaskId(1, 1)));
+ assertTrue(task1.onDuplicatedTaskAddedCounter.neverInvoked());
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ verifyNotRan(task2);
+ verifyNotRan(task3);
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ verifyRanOnce(task2);
+ verifyNotRan(task3);
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ verifyRanOnce(task2);
+ verifyRanOnce(task3);
+ }
+
+ @Test
+ public void testNotReady() {
+ TestTask task1 = (TestTask) submitTask(
+ putTaskId(TaskSchedulerService.createIntent(mTestContext, TestTask.class),
+ new TaskId(1, 0)));
+ task1.readyInMilliseconds = 1000;
+ mService.runNextTask();
+ verifyNotRan(task1);
+ TestTask task2 = (TestTask) submitTask(
+ putTaskId(TaskSchedulerService.createIntent(mTestContext, TestTask.class),
+ new TaskId(2, 0)));
+ mService.runNextTask();
+ verifyNotRan(task1);
+ verifyRanOnce(task2);
+ task1.readyInMilliseconds = 50;
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ verifyRanOnce(task2);
+ }
+
+ @Test
+ public void testInvalidTaskId() {
+ Task task = mock(Task.class);
+ when(task.getId()).thenReturn(new TaskId(Task.TASK_INVALID, 0));
+ thrown.expect(AssertionError.class);
+ mService.addTask(task);
+ }
+
+ @Test
+ public void testDuplicatesAllowedTaskId() {
+ TestTask task1 = (TestTask) submitTask(
+ putTaskId(TaskSchedulerService.createIntent(mTestContext, TestTask.class),
+ new TaskId(Task.TASK_ALLOW_DUPLICATES, 0)));
+ TestTask task2 = (TestTask) submitTask(
+ putTaskId(TaskSchedulerService.createIntent(mTestContext, TestTask.class),
+ new TaskId(Task.TASK_ALLOW_DUPLICATES, 0)));
+ assertTrue(task1.onDuplicatedTaskAddedCounter.neverInvoked());
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ verifyNotRan(task2);
+ mService.runNextTask();
+ verifyRanOnce(task1);
+ verifyRanOnce(task2);
+ }
+}
diff --git a/tests/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerServiceTestBase.java b/tests/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerServiceTestBase.java
new file mode 100644
index 0000000..63f5c2f
--- /dev/null
+++ b/tests/src/com/android/phone/vvm/omtp/scheduling/TaskSchedulerServiceTestBase.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2016 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.vvm.omtp.scheduling;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.Message;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.rule.ServiceTestRule;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.phone.Assert;
+import com.android.phone.vvm.omtp.scheduling.Task.TaskId;
+import com.android.phone.vvm.omtp.scheduling.TaskSchedulerService.MainThreadHandler;
+import com.android.phone.vvm.omtp.scheduling.TaskSchedulerService.WorkerThreadHandler;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+public class TaskSchedulerServiceTestBase {
+
+ private static final String EXTRA_ID = "test_extra_id";
+ private static final String EXTRA_SUB_ID = "test_extra_sub_id";
+
+ public TaskSchedulerService mService;
+
+ @Rule
+ public final ExpectedException thrown = ExpectedException.none();
+
+ @Rule
+ public final ServiceTestRule mServiceRule = new ServiceTestRule();
+
+ public Context mTargetContext;
+ public Context mTestContext;
+
+ private static boolean sIsMainThread = true;
+
+ private final TestMessageSender mMessageSender = new TestMessageSender();
+
+ public static Intent putTaskId(Intent intent, TaskId taskId) {
+ intent.putExtra(EXTRA_ID, taskId.id);
+ intent.putExtra(EXTRA_SUB_ID, taskId.subId);
+ return intent;
+ }
+
+ public static TaskId getTaskId(Intent intent) {
+ return new TaskId(intent.getIntExtra(EXTRA_ID, 0), intent.getIntExtra(EXTRA_SUB_ID, 0));
+ }
+
+ @Before
+ public void setUp() throws TimeoutException {
+ Assert.setIsMainThreadForTesting(true);
+ mTargetContext = InstrumentationRegistry.getTargetContext();
+ IBinder binder = null;
+ // bindService() might returns null on 2nd invocation because the service is not unbinded
+ // yet. See https://code.google.com/p/android/issues/detail?id=180396
+ while (binder == null) {
+ binder = mServiceRule
+ .bindService(new Intent(mTargetContext, TaskSchedulerService.class));
+ }
+ mService = ((TaskSchedulerService.LocalBinder) binder).getService();
+ mTestContext = createTestContext(mTargetContext, mService);
+ mService.setMessageSenderForTest(mMessageSender);
+ mService.setTaskAutoRunDisabledForTest(true);
+ mService.setContextForTest(mTestContext);
+ }
+
+ @After
+ public void tearDown() {
+ Assert.setIsMainThreadForTesting(null);
+ mService.setTaskAutoRunDisabledForTest(false);
+ mService.clearTasksForTest();
+ mService.stopSelf();
+ }
+
+ public Task submitTask(Intent intent) {
+ Task task = mService.createTask(intent, 0, 0);
+ mService.addTask(task);
+ return task;
+ }
+
+ public static void verifyRanOnce(TestTask task) {
+ assertTrue(task.onBeforeExecuteCounter.invokedOnce());
+ assertTrue(task.executeCounter.invokedOnce());
+ assertTrue(task.onCompletedCounter.invokedOnce());
+ }
+
+ public static void verifyNotRan(TestTask task) {
+ assertTrue(task.onBeforeExecuteCounter.neverInvoked());
+ assertTrue(task.executeCounter.neverInvoked());
+ assertTrue(task.onCompletedCounter.neverInvoked());
+ }
+
+ public static class TestTask implements Task {
+
+ public int readyInMilliseconds;
+
+ private TaskId mId;
+
+ public final InvocationCounter onCreateCounter = new InvocationCounter();
+ public final InvocationCounter onBeforeExecuteCounter = new InvocationCounter();
+ public final InvocationCounter executeCounter = new InvocationCounter();
+ public final InvocationCounter onCompletedCounter = new InvocationCounter();
+ public final InvocationCounter onDuplicatedTaskAddedCounter = new InvocationCounter();
+
+ @Override
+ public void onCreate(Context context, Intent intent, int flags, int startId) {
+ onCreateCounter.invoke();
+ mId = getTaskId(intent);
+ }
+
+ @Override
+ public TaskId getId() {
+ return mId;
+ }
+
+ @Override
+ public long getReadyInMilliSeconds() {
+ Assert.isMainThread();
+ return readyInMilliseconds;
+ }
+
+ @Override
+ public void onBeforeExecute() {
+ Assert.isMainThread();
+ onBeforeExecuteCounter.invoke();
+ }
+
+ @Override
+ public void onExecuteInBackgroundThread() {
+ Assert.isNotMainThread();
+ executeCounter.invoke();
+ }
+
+ @Override
+ public void onCompleted() {
+ Assert.isMainThread();
+ onCompletedCounter.invoke();
+ }
+
+ @Override
+ public void onDuplicatedTaskAdded(Task task) {
+ Assert.isMainThread();
+ onDuplicatedTaskAddedCounter.invoke();
+ }
+ }
+
+ public static class InvocationCounter {
+
+ private int mCounter;
+
+ public void invoke() {
+ mCounter++;
+ }
+
+ public boolean invokedOnce() {
+ return mCounter == 1;
+ }
+
+ public boolean neverInvoked() {
+ return mCounter == 0;
+ }
+ }
+
+ private class TestMessageSender extends TaskSchedulerService.MessageSender {
+
+ @Override
+ public void send(Message message) {
+ if (message.getTarget() instanceof MainThreadHandler) {
+ Assert.setIsMainThreadForTesting(true);
+ } else if (message.getTarget() instanceof WorkerThreadHandler) {
+ Assert.setIsMainThreadForTesting(false);
+ } else {
+ throw new AssertionError("unexpected Handler " + message.getTarget());
+ }
+ message.getTarget().handleMessage(message);
+ }
+ }
+
+ public static void assertTrue(boolean condition) {
+ if (!condition) {
+ throw new AssertionError();
+ }
+ }
+
+ private static Context createTestContext(Context targetContext, TaskSchedulerService service) {
+ TestContext context = mock(TestContext.class);
+ when(context.getService()).thenReturn(service);
+ when(context.startService(any())).thenCallRealMethod();
+ when(context.getPackageName()).thenReturn(targetContext.getPackageName());
+ return context;
+ }
+
+ public abstract class TestContext extends Context {
+
+ @Override
+ public ComponentName startService(Intent service) {
+ getService().onStartCommand(service, 0, 0);
+ return null;
+ }
+
+ public abstract TaskSchedulerService getService();
+ }
+}
diff --git a/tests/src/com/android/services/telephony/EmergencyCallStateListenerTest.java b/tests/src/com/android/services/telephony/EmergencyCallStateListenerTest.java
new file mode 100644
index 0000000..64cf052
--- /dev/null
+++ b/tests/src/com/android/services/telephony/EmergencyCallStateListenerTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2016 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 android.os.AsyncResult;
+import android.os.Handler;
+import android.telephony.ServiceState;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.isNull;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.when;
+
+/**
+ * Tests the EmergencyCallStateListener, which listens to one Phone and waits until its service
+ * state changes to accepting emergency calls or in service. If it can not find a tower to camp onto
+ * for emergency calls, then it will fail after a timeout period.
+ */
+@RunWith(AndroidJUnit4.class)
+public class EmergencyCallStateListenerTest extends TelephonyTestBase {
+
+ private static final long TIMEOUT_MS = 100;
+
+ @Mock Phone mMockPhone;
+ @Mock EmergencyCallStateListener.Callback mCallback;
+ EmergencyCallStateListener mListener;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ mListener = new EmergencyCallStateListener();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mListener.getHandler().removeCallbacksAndMessages(null);
+ super.tearDown();
+ }
+
+ @Test
+ public void testRegisterForCallback() {
+ mListener.waitForRadioOn(mMockPhone, mCallback);
+
+ waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
+
+ verify(mMockPhone).unregisterForServiceStateChanged(any(Handler.class));
+ verify(mMockPhone).registerForServiceStateChanged(any(Handler.class),
+ eq(EmergencyCallStateListener.MSG_SERVICE_STATE_CHANGED), isNull());
+ }
+
+ @Test
+ public void testPhoneChangeState_InService() {
+ ServiceState state = new ServiceState();
+ state.setState(ServiceState.STATE_IN_SERVICE);
+ when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
+ mListener.waitForRadioOn(mMockPhone, mCallback);
+ waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
+
+ mListener.getHandler().obtainMessage(EmergencyCallStateListener.MSG_SERVICE_STATE_CHANGED,
+ new AsyncResult(null, state, null)).sendToTarget();
+
+ waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
+ verify(mCallback).onComplete(eq(mListener), eq(true));
+ }
+
+ @Test
+ public void testPhoneChangeState_EmergencyCalls() {
+ ServiceState state = new ServiceState();
+ state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+ state.setEmergencyOnly(true);
+ when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
+ when(mMockPhone.getServiceState()).thenReturn(state);
+ mListener.waitForRadioOn(mMockPhone, mCallback);
+ waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
+
+ mListener.getHandler().obtainMessage(EmergencyCallStateListener.MSG_SERVICE_STATE_CHANGED,
+ new AsyncResult(null, state, null)).sendToTarget();
+
+ waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
+ verify(mCallback).onComplete(eq(mListener), eq(true));
+ }
+
+ @Test
+ public void testPhoneChangeState_OutOfService() {
+ ServiceState state = new ServiceState();
+ state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
+ when(mMockPhone.getServiceState()).thenReturn(state);
+ mListener.waitForRadioOn(mMockPhone, mCallback);
+ waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
+
+ // Don't expect any answer, since it is not the one that we want and the timeout for giving
+ // up hasn't expired yet.
+ mListener.getHandler().obtainMessage(EmergencyCallStateListener.MSG_SERVICE_STATE_CHANGED,
+ new AsyncResult(null, state, null)).sendToTarget();
+
+ waitForHandlerAction(mListener.getHandler(), TIMEOUT_MS);
+ verify(mCallback, never()).onComplete(any(EmergencyCallStateListener.class), anyBoolean());
+ }
+
+ @Test
+ public void testTimeout_EmergencyCalls() {
+ ServiceState state = new ServiceState();
+ state.setState(ServiceState.STATE_OUT_OF_SERVICE);
+ state.setEmergencyOnly(true);
+ when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
+ when(mMockPhone.getServiceState()).thenReturn(state);
+ mListener.waitForRadioOn(mMockPhone, mCallback);
+ mListener.setTimeBetweenRetriesMillis(500);
+
+ // Wait for the timer to expire and check state manually in onRetryTimeout
+ waitForHandlerActionDelayed(mListener.getHandler(), TIMEOUT_MS, 600);
+
+ verify(mCallback).onComplete(eq(mListener), eq(true));
+ }
+
+ @Test
+ public void testTimeout_RetryFailure() {
+ ServiceState state = new ServiceState();
+ state.setState(ServiceState.STATE_POWER_OFF);
+ when(mMockPhone.getState()).thenReturn(PhoneConstants.State.IDLE);
+ when(mMockPhone.getServiceState()).thenReturn(state);
+ mListener.waitForRadioOn(mMockPhone, mCallback);
+ mListener.setTimeBetweenRetriesMillis(100);
+ mListener.setMaxNumRetries(2);
+
+ // Wait for the timer to expire and check state manually in onRetryTimeout
+ waitForHandlerActionDelayed(mListener.getHandler(), TIMEOUT_MS, 600);
+
+ verify(mCallback).onComplete(eq(mListener), eq(false));
+ verify(mMockPhone, times(2)).setRadioPower(eq(true));
+ }
+
+}