[automerger skipped] Use supported locale replace the result from sim info. am: e9360cd21d -s ours am: c9dcc092b7 -s ours am: b3d000c856 -s ours
am skip reason: Merged-In Id29bd66c14d7a5415b3d5b2905a2301846780c70 with SHA-1 0b59d2987c is already in history
Original change: https://android-review.googlesource.com/c/platform/packages/services/Telephony/+/2475766
Change-Id: I28418bc7cc5cf324f1369deba946e08ca60ddf45
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/Android.bp b/Android.bp
index dad0e6c..dc35c5d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,6 +43,7 @@
"PlatformProperties",
"modules-utils-os",
"nist-sip",
+ "service-entitlement"
],
srcs: [
@@ -79,6 +80,16 @@
},
}
+// Allow other applications to use public constants from SlicePurchaseController
+java_library {
+ name: "SlicePurchaseController",
+ srcs: ["src/com/android/phone/slice/*.java",],
+ libs: [
+ "telephony-common",
+ "service-entitlement"
+ ],
+}
+
platform_compat_config {
name: "TeleService-platform-compat-config",
src: ":TeleService",
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index a427bac..ecc4e0f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -19,8 +19,11 @@
package="com.android.phone"
coreApp="true"
android:sharedUserId="android.uid.phone"
- android:sharedUserLabel="@string/phoneAppLabel"
->
+ android:sharedUserLabel="@string/phoneAppLabel">
+
+ <!-- Allows broadcasting for SlicePurchaseController events. -->
+ <protected-broadcast android:name="com.android.phone.slice.action.START_SLICE_PURCHASE_APP" />
+ <protected-broadcast android:name="com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_TIMEOUT" />
<original-package android:name="com.android.phone" />
<!-- Allows granting runtime permissions to telephony related components. -->
@@ -132,6 +135,7 @@
<uses-permission android:name="android.permission.MANAGE_NETWORK_POLICY" />
<uses-permission android:name="android.permission.READ_NETWORK_USAGE_HISTORY" />
<uses-permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE" />
+ <uses-permission android:name="android.permission.BIND_SATELLITE_SERVICE" />
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" />
<uses-permission android:name="android.permission.MANAGE_ROLE_HOLDERS" />
@@ -153,13 +157,16 @@
<uses-permission android:name="android.permission.ACCESS_TELEPHONY_SIMINFO_DB"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+ <!-- Needed to block unwanted malicious pop up overlays -->
+ <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/>
+
+ <!-- Needed to set user association to a certain sim -->
+ <uses-permission android:name="android.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION"/>
+
<permission android:name="com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID"
android:label="Access last known cell identity."
android:protectionLevel="signature"/>
- <!-- Needed to block unwanted malicious pop up overlays -->
- <uses-permission android:name="android.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS"/>
-
<application android:name="PhoneApp"
android:persistent="true"
android:label="@string/phoneAppLabel"
@@ -418,6 +425,10 @@
"android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS" />
<action android:name=
"android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
+ <action android:name=
+ "android.telephony.euicc.action.TRANSFER_EMBEDDED_SUBSCRIPTIONS" />
+ <action android:name=
+ "android.telephony.euicc.action.CONVERT_TO_EMBEDDED_SUBSCRIPTION" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -567,6 +578,14 @@
android:configChanges="orientation|screenSize|keyboardHidden"
android:theme="@style/Theme.Transparent"/>
+ <activity
+ android:name="com.android.phone.ErrorDialogActivity"
+ android:exported="false"
+ android:excludeFromRecents="true"
+ android:launchMode="singleTop"
+ android:configChanges="orientation|screenSize|keyboardHidden"
+ android:theme="@style/Theme.Telephony.Transparent"/>
+
<service
android:name="com.android.phone.vvm.RemoteVvmTaskManager"
android:exported="false"/>
diff --git a/ecc/conversion_toolset_v1/proto/protobuf_ecc_data.proto b/ecc/conversion_toolset_v1/proto/protobuf_ecc_data.proto
index c1a826a..088b5b7 100644
--- a/ecc/conversion_toolset_v1/proto/protobuf_ecc_data.proto
+++ b/ecc/conversion_toolset_v1/proto/protobuf_ecc_data.proto
@@ -19,11 +19,27 @@
AIEC = 7;
}
+ enum Routing {
+ UNKNOWN = 0;
+ EMERGENCY = 1;
+ NORMAL= 2;
+ }
+
// Required: Every EccInfo shall contain a phone number.
optional string phone_number = 1;
// Extra rules: Every Ecc should have at least 1 valid type.
repeated Type types = 2 [packed=true];
+
+
+ //Optional: By default, routing is assumed to be 'UNKNOWN'
+ optional Routing routing = 3 [default = UNKNOWN];
+
+ //Optional: This field is evaluated only if routing is set to NORMAL
+ //If the field is empty, NORMAL routing is used for all MNCs
+ //Else normal routing is used only for list of MNCs specified
+ repeated string normal_routing_mncs = 4;
+
}
// CountryInfo represents available ECCs of a country/region, recognized
@@ -44,6 +60,13 @@
// Per http://www.etsi.org/deliver/etsi_ts/122100_122199/122101/09.01.00_60/ts_122101v090100p.pdf,
// 112 and 911 shall always be available.
optional string ecc_fallback = 3;
+
+ // Required: Every CountryInfo shall specify whether emergency numbers sourced from modem config
+ // should be ignored.
+ //
+ // If this value is set to true, we have a pretty good authority of emergency numbers in the
+ // android emergency number db for this country.
+ optional bool ignore_modem_config = 4 [default = false];
}
message AllInfo {
diff --git a/ecc/input/eccdata.txt b/ecc/input/eccdata.txt
index a8b021e..6988f14 100644
--- a/ecc/input/eccdata.txt
+++ b/ecc/input/eccdata.txt
@@ -129,10 +129,35 @@
countries {
iso_code: "AT"
eccs {
- phone_number: "112"
- types: POLICE
- types: AMBULANCE
- types: FIRE
+ phone_number: "112"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ }
+ eccs {
+ phone_number: "122"
+ types: FIRE
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "133"
+ types: POLICE
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "144"
+ types: AMBULANCE
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "128"
+ types: MOUNTAIN_RESCUE
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "140"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
}
ecc_fallback: "112"
}
@@ -215,6 +240,19 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "100"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "101"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
}
ecc_fallback: "112"
}
@@ -320,14 +358,22 @@
eccs {
phone_number: "190"
types: POLICE
+ routing: EMERGENCY
}
eccs {
phone_number: "192"
types: AMBULANCE
+ routing: NORMAL
}
eccs {
phone_number: "193"
types: FIRE
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "185"
+ types: MARINE_GUARD
+ routing: NORMAL
}
ecc_fallback: "911"
}
@@ -407,6 +453,12 @@
types: AMBULANCE
types: FIRE
}
+ eccs {
+ phone_number: "112"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ }
ecc_fallback: "911"
}
countries {
@@ -438,16 +490,57 @@
countries {
iso_code: "CH"
eccs {
+ phone_number: "112"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "911"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
phone_number: "117"
types: POLICE
+ routing: EMERGENCY
}
eccs {
phone_number: "144"
types: AMBULANCE
+ routing: EMERGENCY
}
eccs {
phone_number: "118"
types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "143"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "145"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "147"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "1414"
+ types: TYPE_UNSPECIFIED
+ }
+ eccs {
+ phone_number: "0800117117"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
}
ecc_fallback: "112"
}
@@ -482,6 +575,7 @@
eccs {
phone_number: "133"
types: POLICE
+ routing: EMERGENCY
}
eccs {
phone_number: "131"
@@ -627,6 +721,7 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -677,6 +772,7 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -719,6 +815,47 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "088"
+ types: POLICE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "085"
+ types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "1006"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "061"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "062"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "080"
+ types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "091"
+ types: POLICE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "092"
+ types: POLICE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -739,6 +876,7 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -792,26 +930,32 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
eccs {
phone_number: "15"
types: AMBULANCE
+ routing: NORMAL
}
eccs {
phone_number: "17"
types: POLICE
+ routing: NORMAL
}
eccs {
phone_number: "18"
types: FIRE
+ routing:NORMAL
}
eccs {
phone_number: "115"
types: TYPE_UNSPECIFIED
+ routing: NORMAL
}
eccs {
phone_number: "116000"
types: TYPE_UNSPECIFIED
+ routing: NORMAL
}
eccs {
phone_number: "114"
@@ -819,27 +963,33 @@
}
eccs {
phone_number: "191"
- types: TYPE_UNSPECIFIED
+ types: MOUNTAIN_RESCUE
+ routing: NORMAL
}
eccs {
phone_number: "196"
types: MARINE_GUARD
+ routing: NORMAL
}
eccs {
phone_number: "197"
types: TYPE_UNSPECIFIED
+ routing: NORMAL
}
eccs {
phone_number: "116117"
types: TYPE_UNSPECIFIED
- }
- eccs {
- phone_number: "116111"
- types: TYPE_UNSPECIFIED
+ routing: NORMAL
}
eccs {
phone_number: "119"
types: TYPE_UNSPECIFIED
+ routing: NORMAL
+ }
+ eccs {
+ phone_number: "116111"
+ types: TYPE_UNSPECIFIED
+ routing: NORMAL
}
ecc_fallback: "112"
}
@@ -860,6 +1010,7 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -1252,11 +1403,18 @@
eccs {
phone_number: "110"
types: POLICE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "118"
+ types: MARINE_GUARD
+ routing: EMERGENCY
}
eccs {
phone_number: "119"
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -1358,11 +1516,42 @@
eccs {
phone_number: "112"
types: POLICE
+ routing: EMERGENCY
}
eccs {
phone_number: "119"
- types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "122"
+ types: MARINE_GUARD
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "111"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "113"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "117"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "118"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "125"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -1497,6 +1686,7 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -1786,6 +1976,7 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "911"
}
@@ -1901,8 +2092,17 @@
eccs {
phone_number: "112"
types: POLICE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "113"
types: AMBULANCE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "110"
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -1955,6 +2155,21 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "112"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "911"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -1986,6 +2201,7 @@
eccs {
phone_number: "105"
types: POLICE
+ routing: EMERGENCY
}
eccs {
phone_number: "110"
@@ -2114,6 +2330,14 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "911"
+ types: POLICE
+ types: AMBULANCE
+ types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -2196,7 +2420,38 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
+ eccs {
+ phone_number: "101"
+ types: FIRE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "102"
+ types: POLICE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "103"
+ types: AMBULANCE
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "104"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "121"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
+ eccs {
+ phone_number: "123"
+ types: TYPE_UNSPECIFIED
+ routing: EMERGENCY
+ }
ecc_fallback: "112"
}
countries {
@@ -2274,6 +2529,7 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "112"
}
@@ -2694,6 +2950,7 @@
types: POLICE
types: AMBULANCE
types: FIRE
+ routing: EMERGENCY
}
ecc_fallback: "911"
}
diff --git a/ecc/output/eccdata b/ecc/output/eccdata
index 8427603..8b4f49b 100644
--- a/ecc/output/eccdata
+++ b/ecc/output/eccdata
Binary files differ
diff --git a/res/layout/radio_info.xml b/res/layout/radio_info.xml
index 2a2ad89..c414fe1 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -4,16 +4,16 @@
**
** Copyright 2006, 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
+** 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
+** 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
+** 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.
*/
-->
@@ -165,12 +165,6 @@
<TextView android:id="@+id/network_slicing_config" style="@style/info_value" />
</LinearLayout>
- <!-- Physical Channel Config -->
- <LinearLayout style="@style/RadioInfo_entry_layout">
- <TextView android:text="@string/radio_info_phy_chan_config" style="@style/info_label" />
- <TextView android:id="@+id/phy_chan_config" style="@style/info_value" />
- </LinearLayout>
-
<!-- Horizontal Rule -->
<View
android:layout_width="fill_parent"
@@ -204,6 +198,14 @@
android:layout_height="wrap_content"
android:text="@string/radio_info_radio_power"/>
+ <!-- Simulate out of service -->
+ <Switch android:id="@+id/simulate_out_of_service"
+ android:textSize="14sp"
+ android:layout_marginTop="8dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/simulate_out_of_service_string"/>
+
<!-- VoLTE provisioned -->
<Switch android:id="@+id/volte_provisioned_switch"
android:textSize="14sp"
@@ -281,7 +283,7 @@
android:layout_height="wrap_content"
android:text="@string/ping_test_label"
/>
-
+
<LinearLayout style="@style/RadioInfo_entry_layout">
<TextView android:text="@string/radio_info_ping_hostname_v4" style="@style/info_label" />
<TextView android:id="@+id/pingHostnameV4" style="@style/info_value" />
@@ -368,6 +370,12 @@
android:layout_height="wrap_content"
/>
+ <!-- Physical Channel Config -->
+ <LinearLayout style="@style/RadioInfo_entry_layout">
+ <TextView android:text="@string/radio_info_phy_chan_config" style="@style/info_label" />
+ <TextView android:id="@+id/phy_chan_config" style="@style/info_value" />
+ </LinearLayout>
+
<!-- CellInfo -->
<LinearLayout style="@style/RadioInfo_entry_layout">
<TextView android:text="@string/radio_info_cellinfo_label"
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index 0eda648..ac9bf5b 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Jy moet jou toestel herbegin om dié instelling te verander."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Herbegin"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Kanselleer"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Stel Verwyderbare-e-SIM as Verstek"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobieleradiokrag"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simuleer is nie beskikbaar nie (Slegs ontfoutingbou)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Bekyk SIM-adresboek"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Kyk na vaste skakelnommers"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Bekyk skakeldiensnommers"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Gekoppel"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Opgeskort"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Onbekend"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primêr"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"grepe"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Fooninligting"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Diensverskaffervoorsiening-inligting"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger-diensverskaffervoorsiening"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFO-geregtigheid-ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Dateer op"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Herlaai"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Jou bluetooth-sein is swak. Probeer om na luidsprekerfoon oor te skakel."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Kennisgewing oor oproepgehalte"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Opgeskorte SIP-rekeninge"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Kan nie boodskap van hierdie profiel af stuur nie"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Jou werkbeleid laat jou toe om boodskappe slegs van die werkprofiel af te stuur"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Kanselleer"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Skakel oor na werkprofiel"</string>
</resources>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 8450b7f..9b83d89 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -34,7 +34,7 @@
<string name="enter_input" msgid="6193628663039958990">"የUSSD መልዕክት በ<xliff:g id="MIN_LEN">%1$d</xliff:g> እና <xliff:g id="MAX_LEN">%2$d</xliff:g> ቁምፊዎች መካከል መሆን አለበት። እባክዎ እንደገና ይሞክሩ።"</string>
<string name="manageConferenceLabel" msgid="8415044818156353233">"የስብሰባስልክ ጥሪ አደራጅ"</string>
<string name="ok" msgid="7818974223666140165">"እሺ"</string>
- <string name="audio_mode_speaker" msgid="243689733219312360">"ድምጽ ማጉያ"</string>
+ <string name="audio_mode_speaker" msgid="243689733219312360">"ድምፅ ማጉያ"</string>
<string name="audio_mode_earpiece" msgid="2823700267171134282">"የስልክ እጀታ ጆሮማዳመጫ"</string>
<string name="audio_mode_wired_headset" msgid="5028010823105817443">"ባለ ገመድ የጆሮ ማዳመጫ"</string>
<string name="audio_mode_bluetooth" msgid="25732183428018809">"ብሉቱዝ"</string>
@@ -623,11 +623,11 @@
<string name="ota_title_activate_success" msgid="1272135024761004889">"ስልክ አግብረሃል!"</string>
<string name="ota_title_problem_with_activation" msgid="7019745985413368726">"ከአግብር ጋር ያለ ችግር"</string>
<string name="ota_listen" msgid="2772252405488894280">"አግብር መጠናቀቁን እስኪሰሙ የተነገሩትን መመሪያዎች ይከተሉ።"</string>
- <string name="ota_speaker" msgid="1086766980329820528">"ድምጽ ማጉያ"</string>
+ <string name="ota_speaker" msgid="1086766980329820528">"ድምፅ ማጉያ"</string>
<string name="ota_progress" msgid="8837259285255700132">"ስልክዎን ፕሮግራም በማድረግ ላይ…"</string>
<string name="ota_failure" msgid="5674217489921481576">"ስልክዎን ፕሮግራም ማድረግ አልተቻለም"</string>
<string name="ota_successful" msgid="1106825981548107774">"አሁን ስልክዎ አግብሯል።አገልግሎቱ ለመጀመር እስከ 15 ደቂቃዎች ሊፈጅ ይችላል።"</string>
- <string name="ota_unsuccessful" msgid="8531037653803955754">"ስልክህ አላገበረም።\n ጥሩ ሽፋን ያለበት አካባቢ ማግኘት ያስፈልግሃል (መስኮት፣ ወይም ውጪ አካባቢ)።ለበለጠ አማራጮች የደንበኞች አገልግሎት ደውል ወይም \n\nእንደገና ሞክር።"</string>
+ <string name="ota_unsuccessful" msgid="8531037653803955754">"ስልክህ አላገበረም።\n ጥሩ ሽፋን ያለበት አካባቢ ማግኘት ያስፈልግሃል (መስኮት፣ ወይም ውጭ አካባቢ)።ለበለጠ አማራጮች የደንበኞች አገልግሎት ደውል ወይም \n\nእንደገና ሞክር።"</string>
<string name="ota_spc_failure" msgid="904092035241370080">"ከልክ ያለፈ የSPC መታወክ"</string>
<string name="ota_call_end" msgid="8657746378290737034">"ተመለስ"</string>
<string name="ota_try_again" msgid="6914781945599998550">"በድጋሚ ሞክር"</string>
@@ -805,8 +805,8 @@
<string name="supp_service_outgoing_calls_barred" msgid="5205725332394087112">"ወጪ ጥሪዎች ተከልክለዋል።"</string>
<string name="supp_service_call_forwarding_active" msgid="7910162960395132464">"ጥሪ ማስተላለፍ ንቁ።"</string>
<string name="supp_service_additional_call_forwarded" msgid="8772753260008398632">"ተጨማሪ ጥሪ ተላልፏል።"</string>
- <string name="supp_service_additional_ect_connected" msgid="8525934162945220237">"ግልጽ የጥሪ ማስተላለፍ ተጠናቅቋል።"</string>
- <string name="supp_service_additional_ect_connecting" msgid="7046240728781222753">"ግልጽ የጥሪ ማስተላለፍ በሂደት ላይ።"</string>
+ <string name="supp_service_additional_ect_connected" msgid="8525934162945220237">"ግልፅ የጥሪ ማስተላለፍ ተጠናቅቋል።"</string>
+ <string name="supp_service_additional_ect_connecting" msgid="7046240728781222753">"ግልፅ የጥሪ ማስተላለፍ በሂደት ላይ።"</string>
<string name="supp_service_call_on_hold" msgid="2836811319594503059">"ጥሪ በይቆይ ላይ።"</string>
<string name="supp_service_call_resumed" msgid="3786864005920743546">"ጥሪ ከቆመበት ቀጥሏል።"</string>
<string name="supp_service_deflected_call" msgid="7565979024562921707">"ጥሪው አቅጣጫው ተቀይሯል።"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"ይህን ቅንብር ለመለወጥ መሣሪያዎትን ዳግም ማስጀመር ያስፈልግዎታል።"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ዳግም አስጀምር"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"ይቅር"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"የሚወገድን ኢሲም ነባሪ በሚል አቀናብር"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"የሞባይል ሬዲዮ ኃይል"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"ከአገልግሎት ውጭን አስመስል (የስህተት ማረሚያ ግንብ ብቻ)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"የሲም አድራሻ ደብተር አሳይ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"በቋሚነት የሚደወልባቸው ቁጥሮች"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"የአገልግሎት መደወያ ቁጥሮችን ተመልከት"</string>
@@ -847,7 +849,7 @@
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"አይገኝም"</string>
<string name="radio_info_ims_reg_status" msgid="25582845222446390">"የIMS ምዝገባ፦ <xliff:g id="STATUS">%1$s</xliff:g>\n የድምጽ ቅጂ LTE፡ <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nየድምጽ ቅጂ WiFi፡ <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nየቪድዮ ጥሪ፦ <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT በይነገጽ፡ <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"በአገልግሎት ውስጥ"</string>
- <string name="radioInfo_service_out" msgid="287972405416142312">"ከአገልግሎት ውጪ"</string>
+ <string name="radioInfo_service_out" msgid="287972405416142312">"ከአገልግሎት ውጭ"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"የአደጋ ጊዜ ጥሪዎች ብቻ"</string>
<string name="radioInfo_service_off" msgid="3456583511226783064">"ሬዲዮ ጠፍቷል"</string>
<string name="radioInfo_roaming_in" msgid="3156335577793145965">"በማዘዋወር ላይ"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"ተገናኝቷል"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"ታግዷል"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"ያልታወቀ"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ቀዳሚ"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ባይቶች"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"የስልክ መረጃ"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"የአገልግሎት አቅራቢ አቅርቦት መረጃ"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"የቀስቅሴ አገልግሎት አቅራቢ አቅርቦት"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC የባለመብትነት መታወቂያ፦"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"አዘምን"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"አድስ"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"የእርስዎ የብሉቱዝ ሲግናል ደካማ ነው። ወደ የስልክ ድምፅ ማጉያ ለመቀየር ይሞክሩ።"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"የጥሪ ጥራት ማሳወቂያ"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"የተቋረጡ የSIP መለያዎች"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ከዚህ መገለጫ መልዕክት መላክ አይቻልም"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"የሥራ መመሪያዎ እርስዎ ከሥራ መገለጫው ብቻ መልዕክት እንዲልኩ ይፈቅድልዎታል"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"ይቅር"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"ወደ የሥራ መገለጫ ቀይር"</string>
</resources>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 474db3c..5870858 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -566,7 +566,7 @@
<string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"جارٍ تفعيل اللاسلكي..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"لا تتوفر خدمة. جارٍ إعادة المحاولة…"</string>
<string name="radio_off_during_emergency_call" msgid="8011154134040481609">"لا يمكن دخول وضع الطيران أثناء إجراء مكالمة طوارئ."</string>
- <string name="dial_emergency_error" msgid="825822413209026039">"يتعذر الاتصال. لا يعد <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> رقم طوارئ."</string>
+ <string name="dial_emergency_error" msgid="825822413209026039">"يتعذر الاتصال. <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> ليس رقم طوارئ."</string>
<string name="dial_emergency_empty_error" msgid="2785803395047793634">"يتعذر الاتصال. يمكنك طلب رقم طوارئ."</string>
<string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"مكالمة الطوارئ غير متوفرة"</string>
<string name="pin_puk_system_user_only" msgid="1045147220686867922">"يمكن لمالك الجهاز فقط إدخال رمزَي PIN/PUK."</string>
@@ -575,7 +575,7 @@
<string name="fire_type_description" msgid="6565200468934914930">"حريق"</string>
<string name="description_concat_format" msgid="2014471565101724088">"%1$s، %2$s"</string>
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"استخدام لوحة المفاتيح للطلب"</string>
- <string name="onscreenHoldText" msgid="4025348842151665191">"تعليق"</string>
+ <string name="onscreenHoldText" msgid="4025348842151665191">"انتظار"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"الانتهاء"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"لوحة الاتصال"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"كتم الصوت"</string>
@@ -692,7 +692,7 @@
<string name="change_pin_enter_new_pin_header" msgid="4739465616733486118">"تعيين رقم تعريف شخصي جديد"</string>
<string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"ينبغي لرقم التعريف الشخصي أن يتكون من <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> أرقام."</string>
<string name="change_pin_confirm_pin_header" msgid="2606303906320705726">"تأكيد رقم التعريف الشخصي"</string>
- <string name="change_pin_confirm_pins_dont_match" msgid="305164501222587215">"أرقام التعريف الشخصي غير متطابقة"</string>
+ <string name="change_pin_confirm_pins_dont_match" msgid="305164501222587215">"رقما التعريف الشخصي غير متطابقَين"</string>
<string name="change_pin_succeeded" msgid="2504705600693014403">"تمّ تحديث رقم التعريف الشخصي للبريد الصوتي"</string>
<string name="change_pin_system_error" msgid="7772788809875146873">"يتعذر تعيين رقم التعريف الشخصي"</string>
<string name="mobile_data_status_roaming_turned_off_subtext" msgid="6840673347416227054">"تم إيقاف تجوال البيانات"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"عليك إعادة تشغيل جهازك لتغيير هذا الإعداد."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"إعادة التشغيل"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"إلغاء"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"ضبط شريحة eSIM القابلة للإزالة كشريحة تلقائية"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"طاقة اللاسلكي للجوّال"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"محاكاة الخطأ \"خارج الخدمة\" (الإصدار المخصص لتصحيح الأخطاء فقط)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"عرض دفتر عناوين SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"عرض أرقام الطلب الثابت"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"عرض أرقام طلب الخدمة"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"متّصل بالإنترنت"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"معلّق"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"غير معروف"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"أساسي"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"الحزم"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"بايت"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"بالديسيبل"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"معلومات الهاتف"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"معلومات توفير خدمة مشغّل شبكة الجوّال"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"توفير خدمة مشغّل شبكة الجوّال"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"معرّف التخويل لميزة \"الاتصال عبر Wi-Fi\":"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"تعديل"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"إعادة تحميل"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"إشارة البلوتوث ضعيفة. حاوِل التبديل إلى مكبّر الصوت."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"إشعار بشأن جودة المكالمة"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"حسابات SIP المتوقّفة"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"لا يمكن إرسال رسالة من هذا الملف الشخصي"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"تسمح لك سياسة العمل بإرسال الرسائل من الملف الشخصي للعمل فقط."</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"إلغاء"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"التبديل إلى الملف الشخصي للعمل"</string>
</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index ed39775..a250aca 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -144,7 +144,7 @@
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"SS অনুৰোধ USSD অনুৰোধলৈ সলনি কৰা হ’ল"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"নতুন SS অনুৰোধলৈ সলনি কৰা হ’ল"</string>
<string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"SS অনুৰোধ ভিডিঅ\' কললৈ সলনি কৰা হ’ল"</string>
- <string name="fdn_check_failure" msgid="1833769746374185247">"আপোনাৰ ফ\'ন এপটোৰ ফিক্সড্ ডায়েলিং নম্বৰ ছেটিঙটো অন কৰি থোৱা আছে। ফলস্বৰূপে, কল সম্পৰ্কীয় কিছুমান সুবিধাই কাম কৰা নাই।"</string>
+ <string name="fdn_check_failure" msgid="1833769746374185247">"আপোনাৰ ফ\'ন এপ্টোৰ ফিক্সড্ ডায়েলিং নম্বৰ ছেটিঙটো অন কৰি থোৱা আছে। ফলস্বৰূপে, কল সম্পৰ্কীয় কিছুমান সুবিধাই কাম কৰা নাই।"</string>
<string name="radio_off_error" msgid="8321564164914232181">"এই ছেটিংসমূহ চোৱাৰ আগতে ৰেডিঅ\' অন কৰক।"</string>
<string name="close_dialog" msgid="1074977476136119408">"ঠিক"</string>
<string name="enable" msgid="2636552299455477603">"অন কৰক"</string>
@@ -179,7 +179,7 @@
<string name="network_query_error" msgid="3862515805115145124">"নেটৱৰ্ক বিচাৰি পোৱা নগ\'ল। আকৌ চেষ্টা কৰক।"</string>
<string name="register_on_network" msgid="4194770527833960423">"<xliff:g id="NETWORK">%s</xliff:g>ৰ লগত পঞ্জীয়ন কৰি থকা হৈছে…"</string>
<string name="not_allowed" msgid="8541221928746104798">"আপোনাৰ ছিম কাৰ্ডখনে এই নেটৱৰ্কটোৰ সৈতে সংযোগ কৰিবলৈ অনুমতি নিদিয়ে।"</string>
- <string name="connect_later" msgid="1950138106010005425">"এই মুহূৰ্তত এই নেটৱৰ্কটোৰ সৈতে সংযোগ কৰিব নোৱাৰি। পিছত আকৌ চেষ্টা কৰক।"</string>
+ <string name="connect_later" msgid="1950138106010005425">"এই মুহূৰ্তত এই নেটৱৰ্কটোৰ সৈতে সংযোগ কৰিব নোৱাৰি। পাছত আকৌ চেষ্টা কৰক।"</string>
<string name="registration_done" msgid="5337407023566953292">"নেটৱৰ্কৰ লগত পঞ্জীয়ন কৰা হ’ল।"</string>
<string name="already_auto" msgid="8607068290733079336">"স্বয়ংক্ৰিয় বাছনিত ইতিমধ্যে আছে।"</string>
<string name="select_automatically" msgid="779750291257872651">"স্বয়ংক্ৰিয়ভাৱে নেটৱৰ্ক বাছনি কৰক"</string>
@@ -613,7 +613,7 @@
<string name="network_info_message" msgid="7599413947016532355">"নেটৱৰ্ক বাৰ্তা"</string>
<string name="network_error_message" msgid="4271579424089326618">"আসোঁৱাহ বাৰ্তা"</string>
<string name="ota_title_activate" msgid="4049645324841263423">"আপোনাৰ ফ\'নটো সক্ৰিয় কৰক"</string>
- <string name="ota_touch_activate" msgid="838764494319694754">"আপোনাৰ ফ\'নৰ সেৱা সক্ৰিয় কৰিবলৈ এটা বিশেষ কল কৰা প্ৰয়োজন। \n\nআপোনাৰ ফ\'নটো সক্ৰিয় কৰিবলৈ \"সক্ৰিয় কৰক\"ত টিপাৰ পিছত নিৰ্দেশনাসমূহ শুনক।"</string>
+ <string name="ota_touch_activate" msgid="838764494319694754">"আপোনাৰ ফ\'নৰ সেৱা সক্ৰিয় কৰিবলৈ এটা বিশেষ কল কৰা প্ৰয়োজন। \n\nআপোনাৰ ফ\'নটো সক্ৰিয় কৰিবলৈ \"সক্ৰিয় কৰক\"ত টিপাৰ পাছত নিৰ্দেশনাসমূহ শুনক।"</string>
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"সক্ৰিয় কৰি থকা হৈছে..."</string>
<string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"ফ\'নটোৱে আপোনাৰ ম’বাইল ডেটা সেৱা সক্ৰিয় কৰি আছে।\n\nএই কামটো সম্পূৰ্ণ হ\'বলৈ ৫ মিনিট পৰ্যন্ত সময় লাগিব পাৰে।"</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"সক্ৰিয়কৰণ এৰি যায় নেকি?"</string>
@@ -711,7 +711,7 @@
<string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"বাতিল কৰক"</string>
<string name="clh_card_title_call_ended_txt" msgid="5977978317527299698">"কল শেষ হ’ল"</string>
<string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"এয়াৰপ্লেইন ম\'ড অন হৈ আছে"</string>
- <string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"ছিম কাৰ্ডত প্ৰৱেশ কৰিব পৰা নাই"</string>
+ <string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"ছিম কাৰ্ড এক্সেছ কৰিব নোৱাৰি"</string>
<string name="clh_incall_error_out_of_service_txt" msgid="2736010617446749869">"ম’বাইল নেটৱৰ্ক উপলব্ধ নহয়"</string>
<string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"আপুনি ডায়েল কৰিব খোজা ফ\'ন নম্বৰত আসোঁৱাহ আছে। আসোঁৱাহ ক\'ড ১।"</string>
<string name="clh_callFailed_no_route_to_destination_txt" msgid="4805015149822352308">"কলটো সম্পূৰ্ণ কৰিব পৰা নগ\'ল। আসোঁৱাহ ক\'ড ৩।"</string>
@@ -794,7 +794,7 @@
<string name="call_barring_confirm_pwd" msgid="7552526161616461858">"পাছৱৰ্ড নিশ্চিত কৰক"</string>
<string name="messageCallBarring" msgid="5537730400652466912">"পাছৱৰ্ড দিয়ক"</string>
<string name="call_barring_settings" msgid="4616607285790258919">"কল প্ৰতিবন্ধক ছেটিংসমূহ"</string>
- <string name="callFailed_NetworkBusy" msgid="5437103975842913681">"নেটৱৰ্ক ব্যস্ত। অনুগ্ৰহ কৰি কিছুসময় পিছত আকৌ কল কৰাৰ চেষ্টা কৰক।"</string>
+ <string name="callFailed_NetworkBusy" msgid="5437103975842913681">"নেটৱৰ্ক ব্যস্ত। অনুগ্ৰহ কৰি কিছুসময় পাছত আকৌ কল কৰাৰ চেষ্টা কৰক।"</string>
<string name="callFailed_NetworkCongested" msgid="6801283142342775380">"নেটৱর্ক ব্যস্ত আছে। সহায়তাৰ বাবে আপোনাৰ ম\'বাইল অ\'পাৰেটৰৰ সৈতে যোগাযোগ কৰক।"</string>
<string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"কলটো বিচ্যুত কৰা হৈছে।"</string>
<string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"কলটো ফৰৱাৰ্ড কৰা হ’ল।"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"আপুনি এই ছেটিংটো সলনি কৰিবলৈ আপোনাৰ ডিভাইচটো ৰিষ্টার্ট কৰিব লাগিব।"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ৰিষ্টাৰ্ট কৰক"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"বাতিল কৰক"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"আঁতৰাব পৰা ই-ছিম ডিফ’ল্ট হিচাপে ছেট কৰক"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"ম’বাইলৰ ৰেডিঅ’ পাৱাৰ"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"সেৱাত নাই ছিমুলে’ট কৰক (কেৱল ডিবাগ বিল্ড)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ছিম ঠিকনা সূচী চাওক"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ফিক্সড্ ডায়েলিং নম্বৰসমূহ চাওক"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"সেৱা ডায়েলিং নম্বৰসমূহ চাওক"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"সংযোগ কৰা হ’ল"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"নিলম্বন কৰা হৈছে"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"অজ্ঞাত"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"প্ৰাথমিক"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"পিকেটিএছ"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"বাইটসমূহ"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"ডিবিএম"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ফ\'নৰ তথ্য"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"বাহকৰ প্ৰ’ভিজনিং তথ্য"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"বাহকৰ প্ৰ’ভিজনিং সূচনা কৰক"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC স্বত্ব আইডি:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"আপডে’ট কৰক"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ৰিফ্ৰেশ্ব কৰক"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"আপোনাৰ ব্লুটুথৰ ছিগনেল দুৰ্বল। স্পীকাৰফ’নলৈ সলনি কৰি চাওক।"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"কলৰ গুণগত মানৰ জাননী"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"বন্ধ হৈ যোৱা SIP একাউণ্ট"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"এই প্ৰ’ফাইলৰ পৰা বাৰ্তা পঠিয়াব নোৱাৰি"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"আপোনাৰ কৰ্মস্থানৰ নীতিয়ে আপোনাক কেৱল কৰ্মস্থানৰ প্ৰ’ফাইলৰ পৰা বাৰ্তা পঠিয়াবলৈ দিয়ে"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"বাতিল কৰক"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"কৰ্মস্থানৰ প্ৰ’ফাইললৈ সলনি কৰক"</string>
</resources>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 3902eb7..783c6ca 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -281,7 +281,7 @@
<string name="data_enabled" msgid="22525832097434368">"Data aktivdir"</string>
<string name="data_enable_summary" msgid="696860063456536557">"Data istifadəsinə icazə verin"</string>
<string name="dialog_alert_title" msgid="5260471806940268478">"Diqqət"</string>
- <string name="roaming" msgid="1576180772877858949">"Rominq"</string>
+ <string name="roaming" msgid="1576180772877858949">"Rouminq"</string>
<string name="roaming_enable" msgid="6853685214521494819">"Rominq zamanı data xidmətinə qoşulun"</string>
<string name="roaming_disable" msgid="8856224638624592681">"Rominq zamanı data xidmətinə qoşulun"</string>
<string name="roaming_reenable_message" msgid="1951802463885727915">"Data rominqi deaktivdir. Aktiv etmək üçün klikləyin."</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Bu ayarı dəyişmək üçün cihazı yenidən başlatmalısınız."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Yenidən başladın"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Ləğv edin"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Çıxarıla bilən eSIM\'i Defolt olaraq təyin edin"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobil Radio Enerjisi"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\"Xidmətdənkənar\" Simulyasiyası (yalnız Debaq Versiyası)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM Ünvan Kitabçasına Baxın"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Sabit Yığım Nömrələrinə Baxın"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Xidmət Yığım Nömrələrinə Baxın"</string>
@@ -850,7 +852,7 @@
<string name="radioInfo_service_out" msgid="287972405416142312">"Xidmətdən kənarda"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"Yalnız təcili zənglər"</string>
<string name="radioInfo_service_off" msgid="3456583511226783064">"Radio Deaktivdir"</string>
- <string name="radioInfo_roaming_in" msgid="3156335577793145965">"Rominq"</string>
+ <string name="radioInfo_roaming_in" msgid="3156335577793145965">"Rouminq"</string>
<string name="radioInfo_roaming_not" msgid="1904547918725478110">"Rominq Deyil"</string>
<string name="radioInfo_phone_idle" msgid="2191653783170757819">"Fəaliyyətsiz"</string>
<string name="radioInfo_phone_ringing" msgid="8100354169567413370">"Zəng"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Qoşuldu"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Dayandırılıb"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Naməlum"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"İlkin"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkt"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bayt"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -874,7 +877,7 @@
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobil məlumatın yenilənmə göstəricisi:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Operatorun bütün mobil ölçü məlumatı:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data Xidməti:"</string>
- <string name="radio_info_roaming_label" msgid="6636932886446857120">"Rominq:"</string>
+ <string name="radio_info_roaming_label" msgid="6636932886446857120">"Rouminq:"</string>
<string name="radio_info_imei_label" msgid="8947899706930120368">"IMEI:"</string>
<string name="radio_info_call_redirect_label" msgid="4526480903023362276">"Zəng Yönləndirməsi:"</string>
<string name="radio_info_ppp_resets_label" msgid="9131901102339077661">"Yükləmədən bəri sıfırlanan PPP sayı:"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefon məlumatı"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operator Təchizat Məlumatı"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Operator Təchizatlanmasını aktiv edin"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC İcazə ID-si:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Güncəlləyin"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Yeniləyin"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth siqnalı zəifdir. Telefon spikerinə keçin."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Zəng keyfiyyəti bildirişi"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Ləğv edilmiş SIP hesabları"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Bu profildən mesaj göndərmək mümkün deyil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"İş siyasətiniz yalnız iş profilindən mesaj göndərməyə icazə verir"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Ləğv edin"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"İş profilinə keçin"</string>
</resources>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 97c3607..7d900e4 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -305,7 +305,7 @@
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> – <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
<string name="mobile_data_settings_title" msgid="7228249980933944101">"Mobilni podaci"</string>
<string name="mobile_data_settings_summary" msgid="5012570152029118471">"Koristi podatke preko mobilne mreže"</string>
- <string name="data_usage_disable_mobile" msgid="5669109209055988308">"Želite li da isključite mobilne podatke?"</string>
+ <string name="data_usage_disable_mobile" msgid="5669109209055988308">"Želite da isključite mobilne podatke?"</string>
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Potrebno je da izaberete nešto"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"Da promenimo SIM za podatke?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Želite li da za mobilne podatke koristite <xliff:g id="NEW_SIM">%1$s</xliff:g> umesto <xliff:g id="OLD_SIM">%2$s</xliff:g>?"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Treba da restartujte uređaj da biste promenili ovo podešavanje."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Restartuj"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Otkaži"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Podesi prenosivi eSIM kao podrazumevani"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Napajanje za radio na mobilnim uređajima"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulacija ne funkcioniše (samo verzija sa otklonjenim greškama)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Prikaži adresar SIM-a"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Prikaži brojeve za fiksno biranje"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Prikaži brojeve za servisno biranje"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Povezano"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspendovano"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Nepoznato"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primarno"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pak."</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bajt(ov)a"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacije o telefonu"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informacije o dodeli mobilnog operatera"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Pokretanje dodele mobilnog operatera"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID prava na WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Ažuriraj"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Osveži"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth signal je slab. Probajte da pređete na spikerfon."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Obaveštenje o kvalitetu poziva"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Zastareli SIP nalozi"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Ne možete da pošaljete poruku sa ovog profila"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Smernice za posao vam omogućavaju da šaljete poruke samo sa poslovnog profila"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Otkaži"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Pređi na poslovni profil"</string>
</resources>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index d13be56..a2353ad 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -20,7 +20,7 @@
<string name="phoneAppLabel" product="default" msgid="130465039375347763">"Тэлефонныя службы"</string>
<string name="emergencyDialerIconLabel" msgid="8668005772339436680">"Экстраныя выклікі"</string>
<string name="phoneIconLabel" msgid="3015941229249651419">"Тэлефон"</string>
- <string name="fdnListLabel" msgid="4119121875004244097">"Спіс FDN"</string>
+ <string name="fdnListLabel" msgid="4119121875004244097">"Спіс дазволеных нумароў"</string>
<string name="unknown" msgid="8279698889921830815">"Невядомы"</string>
<string name="private_num" msgid="4487990167889159992">"Прыватны нумар"</string>
<string name="payphone" msgid="7936735771836716941">"Таксафон"</string>
@@ -438,18 +438,18 @@
<string name="carrier_settings_title" msgid="6292869148169850220">"Налады аператара"</string>
<string name="fdn" msgid="2545904344666098749">"Фіксаваныя нумары"</string>
<string name="fdn_with_label" msgid="6412087553365709494">"Нумары закрытай абаненцкай групы (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
- <string name="manage_fdn_list" msgid="3341716430375195441">"Спіс FDN"</string>
- <string name="fdn_list_with_label" msgid="1409655283510382556">"Спіс закрытай абаненцкай групы (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
- <string name="fdn_activation" msgid="2178637004710435895">"Актывацыя FDN"</string>
+ <string name="manage_fdn_list" msgid="3341716430375195441">"Спіс дазволеных нумароў"</string>
+ <string name="fdn_list_with_label" msgid="1409655283510382556">"Спіс дазволеных нумароў (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="fdn_activation" msgid="2178637004710435895">"Актывацыя дазволеных нумароў"</string>
<string name="fdn_enabled" msgid="7017355494808056447">"Фіксаваныя нумары ўключаны"</string>
<string name="fdn_disabled" msgid="6696468878037736600">"Фіксаваныя нумары адключаны"</string>
- <string name="enable_fdn" msgid="4830555730418033723">"Уключыць FDN"</string>
- <string name="disable_fdn" msgid="3918794950264647541">"Адключыць FDN"</string>
+ <string name="enable_fdn" msgid="4830555730418033723">"Уключыць дазволеныя нумары"</string>
+ <string name="disable_fdn" msgid="3918794950264647541">"Адключыць дазволеныя нумары"</string>
<string name="change_pin2" msgid="3110844547237754871">"Змяніць PIN2"</string>
- <string name="enable_fdn_ok" msgid="5080925177369329827">"Адключыць FDN"</string>
- <string name="disable_fdn_ok" msgid="3745475926874838676">"Уключыць FDN"</string>
+ <string name="enable_fdn_ok" msgid="5080925177369329827">"Адключыць дазволеныя нумары"</string>
+ <string name="disable_fdn_ok" msgid="3745475926874838676">"Уключыць дазволеныя нумары"</string>
<string name="sum_fdn" msgid="6152246141642323582">"Кіраванне зафіксаванымі нумарамі"</string>
- <string name="sum_fdn_change_pin" msgid="3510994280557335727">"Змяніць PIN-код для доступу FDN"</string>
+ <string name="sum_fdn_change_pin" msgid="3510994280557335727">"Змяніць PIN-код для доступу да дазволеных нумароў"</string>
<string name="sum_fdn_manage_list" msgid="3311397063233992907">"Кіраванне спісам тэлефонных нумароў"</string>
<string name="voice_privacy" msgid="7346935172372181951">"Палiтыка прыватнасцi Voice"</string>
<string name="voice_privacy_summary" msgid="3556460926168473346">"Уключыць пашыраны рэжым прыватнасці"</string>
@@ -475,10 +475,10 @@
<string name="delete_fdn_contact" msgid="7027405651994507077">"Выдаліць дазволены нумар"</string>
<string name="deleting_fdn_contact" msgid="6872320570844460428">"Выдаленне дазволенага нумару..."</string>
<string name="fdn_contact_deleted" msgid="1680714996763848838">"Дазволены нумар выдалены."</string>
- <string name="pin2_invalid" msgid="2313954262684494442">"FDN не быў абноўлены, таму што вы набралі няправільны PIN-код."</string>
- <string name="fdn_invalid_number" msgid="9067189814657840439">"Фіксаваны нумар не абноўлены, бо не можа складацца больш чым з <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> лічбаў."</string>
+ <string name="pin2_invalid" msgid="2313954262684494442">"Дазволены нумар не быў абноўлены, таму што вы набралі няправільны PIN-код."</string>
+ <string name="fdn_invalid_number" msgid="9067189814657840439">"Дазволены нумар не абноўлены, бо не можа складацца больш чым з <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> лічбаў."</string>
<string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"Cпiс дазволеных нумароў не адноўлены. PIN2 ўведзены няправiльна, або нумар быў адхiлены."</string>
- <string name="fdn_failed" msgid="216592346853420250">"Аперацыя ў закрытай абаненцкай групе не ўдалася."</string>
+ <string name="fdn_failed" msgid="216592346853420250">"Аперацыя з дазволеным нумарам не ўдалася."</string>
<string name="simContacts_emptyLoading" msgid="4989040293858675483">"Чытанне з SIM-карты..."</string>
<string name="simContacts_empty" msgid="1135632055473689521">"На вашай SIM-карце няма кантактаў."</string>
<string name="simContacts_title" msgid="2714029230160136647">"Выберыце кантакты для імпарту"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Каб змяніць гэту наладу, трэба перазапусціць прыладу."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Перазапусціць"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Скасаваць"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Зрабіць здымную eSIM-карту стандартнай"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Магутнасць радыёсігналу"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Мадэляванне знаходжання па-за сеткай (толькі ў зборцы для адладкі)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Праглядзець адрасную кнігу на SIM-карце"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Прагляд фіксаваных нумароў"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Паглядзець сэрвісныя нумары"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Падключана"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Прыпынена"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Невядома"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Асноўны"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"пак."</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"Б"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"дБм"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Звесткі аб тэлефоне"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Звесткі аб аператары"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Запусціць сінхранізацыю з аператарам"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Ідэнтыфікатар правоў WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Абнавіць"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Абнавіць"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Сігнал Bluetooth слабы. Паспрабуйце пераключыцца на гучную сувязь."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Апавяшчэнне пра якасць выкліку"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Састарэлыя ўліковыя запісы SIP"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Адпраўляць паведамленні з гэтага профілю нельга"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Згодна з палітыкай вашай арганізацыі адпраўляць паведамленні дазваляецца толькі з працоўнага профілю"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Скасаваць"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Пераключыцца на працоўны профіль"</string>
</resources>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index da48bfb..0e989f2 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"За да промените настройката, трябва да рестартирате устройството си."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Рестартиране"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Отказ"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Задаване на електронната SIM карта с изваждащ се чип като основна"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Мощност на мобилното радио"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Симулиране на липса на услуга (само в компилацията за отстраняване на грешки)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Преглед на указателя на SIM картата"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Преглед на номера за фиксирано набиране"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Преглед на номера за набиране на услуги"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Установена е връзка"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Спрени"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Неизвестно"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Основна"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"пакета"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"байта"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Информация за телефона"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Информация за обезпечаването от оператора"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Задействане на обезпечаването от оператора"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID на правото на достъп до WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Актуализиране"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Опресняване"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Сигналът ви за Bluetooth е слаб. Опитайте да превключите на високоговорител."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Известия за качеството на обаждането"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Оттеглени профили за SIP"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Съобщението не може да се изпрати от този потребителски профил"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Служебните ви правила позволяват да изпращате съобщения само от служебния потребителски профил"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Отказ"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Превключване към служебния потребителски профил"</string>
</resources>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index fd8cbaa..a5e5757 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"এই সেটিং পরিবর্তন করতে আপনার ডিভাইস রিস্টার্ট করতে হবে।"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"রিস্টার্ট করুন"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"বাদ দিন"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"সরিয়ে দেওয়া যায় এমন eSIM ডিফল্ট হিসেবে সেট করুন"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"মোবাইল রেডিওর গুণমান"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"আউট-অফ-সার্ভিস সিমুলেট করা (শুধুমাত্র ডিবাগ বিল্ডের জন্য)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"সিম অ্যাড্রেস বুক দেখুন"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"স্থায়ী ডায়াল নম্বরগুলি দেখুন"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"সার্ভিস ডায়াল নম্বরগুলি দেখুন"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"কানেক্ট করা হয়েছে"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"সাসপেন্ড করা হয়েছে"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"অজানা"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"প্রাথমিক"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"বাইট"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,13 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ফোনের তথ্য"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"পরিষেবা প্রদানকারীর ব্যবস্থামূলক তথ্য"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ট্রিগার পরিষেবা প্রদানকারীর ব্যবস্থা"</string>
- <!-- no translation found for provisioning_info_wfc_entitlement_id (8845188780811890910) -->
- <skip />
- <!-- no translation found for update_provisioning_info_wfc_entitlement_id (7044171908781134221) -->
- <skip />
- <!-- no translation found for refresh_provisioning_info_wfc_entitlement_id (738894335351353407) -->
- <skip />
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"আপনার ডিভাইসের ব্লুটুথ সিগনাল ভাল না। বদল করে স্পিকারফোন বেছে নিন।"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"ফোন কলের কোয়ালিটি সংক্রান্ত বিজ্ঞপ্তি"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"পুরনো SIP অ্যাকাউন্ট"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"এই প্রোফাইল থেকে মেসেজ পাঠানো যাচ্ছে না"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"কাজ সংক্রান্ত নীতি, আপনাকে শুধুমাত্র অফিস প্রোফাইল থেকে মেসেজ করার অনুমতি দেয়"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"বাতিল করুন"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"অফিস প্রোফাইলে পাল্টে নিন"</string>
</resources>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 910cc33..d682d7a 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Da promijenite ovu postavku, trebate ponovo pokrenuti uređaj."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Ponovo pokreni"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Otkaži"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Postavljanje uklonjive eSim kartice kao zadane"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Snaga mobilnog radija"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulacija ne radi (samo verzija za otklanjanje grešaka)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Prikaži SIM adresar"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Prikaži brojeve fiksnog biranja"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Prikaži brojeve biranja usluga"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Povezano"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Obustavljeno"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Nepoznato"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primarno"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"paketi"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bajtova"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacije o telefonu"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operater koji pruža informacije"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktiviranje dodjele resursa operatera"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID za WFC Entitlement:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Ažuriraj"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Osvježi"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Vaš Bluetooth signal je slab. Pokušajte prebaciti na zvučnik."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Obavještenje o kvalitetu poziva"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Zastarjeli SIP računi"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Slanje poruke s ovog profila nije moguće"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Vaša poslovna pravila dopuštaju vam da šaljete poruke samo s poslovnog profila"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Odustani"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Prelazak na poslovni profil"</string>
</resources>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 4d0b99c..ec85f7e 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Has de reiniciar el dispositiu per canviar aquesta opció."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Reinicia"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancel·la"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Defineix l\'eSIM extraïble com a opció predeterminada"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Potència del senyal mòbil"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simula que està fora de servei (només per a la compilació de depuració)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Mostra la llibreta d\'adreces de la SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Mostra els números de marcatge fix"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Mostra els números de marcatge de serveis"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Amb connexió"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"En suspensió"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Desconegut"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"paquets"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informació del telèfon"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informació de serveis de l\'operador"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Activa els serveis de l\'operador"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Identificador de dret per a WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Actualitza"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Actualitza"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"El senyal del Bluetooth és feble. Fes servir l\'altaveu."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notificació sobre la qualitat de la trucada"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Comptes SIP obsolets"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"No es pot enviar el missatge des d\'aquest perfil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"La teva política de treball et permet enviar missatges només des del perfil de treball"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancel·la"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Canvia al perfil de treball"</string>
</resources>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index fbfcb43..3ac8634 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Ke změně nastavení je nutné restartovat zařízení."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Restartovat"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Zrušit"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Nastavit vyjímatelnou eSIM jako výchozí"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Výkon mobilního přijímače"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulovat provoz mimo službu (pouze ladicí sestavení)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Zobrazit adresář SIM karty"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Zobrazit povolená telefonní čísla"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Zobrazit čísla volání služeb"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Připojeno"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Pozastaveno"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Neznámé"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primární"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pakety"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"B"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informace o telefonu"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informace o zprovoznění služby u operátora"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Spustit zprovoznění služby u operátora"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID nároku služby WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Aktualizovat"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Obnovit"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Signál sítě Bluetooth je slabý. Zkuste přepnout na hlasitý odposlech."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Oznámení o kvalitě hovoru"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Zastaralé účty SIP"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Z tohoto profilu nemůžete odeslat zprávu"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Vaše pracovní zásady vám umožňují odesílat zprávy jen z pracovního profilu"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Zrušit"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Přepnout na pracovní profil"</string>
</resources>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 02709d8..ac4d257 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -577,7 +577,7 @@
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Brug tastatur til at ringe op"</string>
<string name="onscreenHoldText" msgid="4025348842151665191">"Hold"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"Afslut"</string>
- <string name="onscreenShowDialpadText" msgid="658465753816164079">"Nummerblok"</string>
+ <string name="onscreenShowDialpadText" msgid="658465753816164079">"Opkaldstastatur"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Lyd fra"</string>
<string name="onscreenAddCallText" msgid="9075675082903611677">"Tilføj opkald"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"Slå opkald sammen"</string>
@@ -657,8 +657,8 @@
<string name="selectContact" msgid="1527612842599767382">"vælg kontakt"</string>
<string name="not_voice_capable" msgid="2819996734252084253">"Taleopkald understøttes ikke"</string>
<string name="description_dial_button" msgid="8614631902795087259">"ring op"</string>
- <string name="description_dialpad_button" msgid="7395114120463883623">"vis numerisk tastatur"</string>
- <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Numerisk tastatur til nødopkald"</string>
+ <string name="description_dialpad_button" msgid="7395114120463883623">"vis opkaldstastatur"</string>
+ <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Nødopkaldstastatur"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"Visuel telefonsvarer"</string>
<string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"Angiv pinkode"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Skift pinkode"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Genstart enheden for at skifte indstilling."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Genstart"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Annuller"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Konfigurer eSIM, der kan fjernes, som standard"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobilsendestyrke"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulering af enhed, der er ude af drift (kun i fejlretningsbuild)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Vis adressebog på SIM-kortet"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Vis numre til begrænset opkald"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Vis tjenestens faste opkaldsnumre"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Tilsluttet"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspenderet"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Ukendt"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primær"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pk."</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefonoplysninger"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Oplysninger om mobilselskab"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktivér mobilselskab"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC-berettigelses-id:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Opdater"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Opdater"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Dit Bluetooth-signal er svagt. Prøv at skifte til medhør."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notifikation om opkaldskvalitet"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Udfasede SIP-konti"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Du kan ikke sende beskeder fra denne profil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Din arbejdspolitik giver dig mulighed for kun at sende beskeder fra arbejdsprofilen"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Annuller"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Skift til arbejdsprofil"</string>
</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index a4d1feb..9bb7b23 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -655,7 +655,7 @@
<string name="contactPhoto" msgid="7885089213135154834">"Kontaktbild"</string>
<string name="goPrivate" msgid="4645108311382209551">"privat sprechen"</string>
<string name="selectContact" msgid="1527612842599767382">"Kontakt wählen"</string>
- <string name="not_voice_capable" msgid="2819996734252084253">"Audioanruf wird nicht unterstützt."</string>
+ <string name="not_voice_capable" msgid="2819996734252084253">"Sprachanruf wird nicht unterstützt."</string>
<string name="description_dial_button" msgid="8614631902795087259">"Wählen"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"Wähltasten anzeigen"</string>
<string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Wähltasten für Notruf"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Die Änderung erfordert einen Neustart des Geräts."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Neu starten"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Abbrechen"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Wechsel-eSIM als Standard festlegen"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobilfunkstärke"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"„Außer Betrieb“ simulieren (nur Debug-Build)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM-Adressbuch anzeigen"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Rufnummernbeschränkung ansehen"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Servicerufnummern anzeigen"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Verbunden"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Gesperrt"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Unbekannt"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primär"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"Pakete"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"Bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -882,7 +885,7 @@
<string name="radio_info_ppp_received_label" msgid="5753592451640644889">"Empfangene Daten:"</string>
<string name="radio_info_gsm_service_label" msgid="6443348321714241328">"Sprachdienst:"</string>
<string name="radio_info_signal_strength_label" msgid="5545444702102543260">"Signalstärke:"</string>
- <string name="radio_info_call_status_label" msgid="7693575431923095487">"Status für Audioanruf:"</string>
+ <string name="radio_info_call_status_label" msgid="7693575431923095487">"Status für Sprachanruf:"</string>
<string name="radio_info_ppp_sent_label" msgid="6542208429356199695">"Gesendete Daten:"</string>
<string name="radio_info_message_waiting_label" msgid="1886549432566952078">"Nachricht liegt vor:"</string>
<string name="radio_info_phone_number_label" msgid="2533852539562512203">"Telefonnummer:"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Über das Telefon"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informationen zur Nutzerverwaltung durch den Anbieter"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Nutzerverwaltung durch den Anbieter auslösen"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC-Berechtigungs-ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Aktualisieren"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Aktualisieren"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Das Bluetooth-Signal ist schwach. Verwende die Freisprechfunktion."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Benachrichtigung zu Anrufqualität"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Eingestellte SIP-Konten"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Du kannst über dieses Profil keine Nachrichten senden"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Gemäß den Arbeitsrichtlinien darfst du nur über dein Arbeitsprofil Nachrichten senden"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Abbrechen"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Zum Arbeitsprofil wechseln"</string>
</resources>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index b43d89a..cd38afb 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Πρέπει να επανεκκινηθεί η συσκευή για να αλλάξει η ρύθμιση."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Επανεκκίνηση"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Ακύρωση"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Ορισμός αφαιρούμενης eSIM ως προεπιλεγμένης"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Ισχύς πομπού κινητής τηλεφωνίας"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Η προσομοίωση δεν λειτουργεί (μόνο έκδοση εντοπισμού σφαλμάτων)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Προβολή βιβλίου διευθύνσεων κάρτας SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Προβολή προκαθορισμένων αριθμών κλήσης"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Προβολή αριθμών κλήσης υπηρεσίας"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Σε σύνδεση"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Σε αναστολή"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Άγνωστο"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Κύρια"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"byte"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Πληροφορίες τηλεφώνου"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Πληροφορίες παροχής εταιρείας κινητής τηλεφωνίας"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Ενεργοποίηση παροχής εταιρείας κινητής τηλεφωνίας"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Αναγνωριστικό δικαιώματος WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Ενημέρωση"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Ανανέωση"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Το σήμα bluetooth είναι ασθενές. Δοκιμάστε να αλλάξετε σε ανοιχτή ακρόαση."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Ειδοποίηση ποιότητας κλήσης"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Καταργημένοι λογαριασμοί SIP"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Δεν είναι δυνατή η αποστολή μηνύματος από αυτό το προφίλ"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Η πολιτική εργασίας σας επιτρέπει την αποστολή μηνυμάτων μόνο από το προφίλ εργασίας"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Ακύρωση"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Εναλλαγή σε προφίλ εργασίας"</string>
</resources>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index cede509..dd8cb49 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"You need to restart your device to change this setting."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Restart"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancel"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Set removable eSIM as default"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobile radio power"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulate out of service (debug build only)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"View SIM address book"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"View fixed dialling numbers"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"View service dialling numbers"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Connected"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspended"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Unknown"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primary"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operator provisioning info"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger operator provisioning"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Update"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Refresh"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Your Bluetooth signal is weak. Try switching to speakerphone."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Call quality notification"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Deprecated SIP accounts"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Can\'t send message from this profile"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Your work policy allows you to send messages only from the work profile"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancel"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Switch to work profile"</string>
</resources>
diff --git a/res/values-en-rCA/arrays.xml b/res/values-en-rCA/arrays.xml
index 08bac75..d8479e7 100644
--- a/res/values-en-rCA/arrays.xml
+++ b/res/values-en-rCA/arrays.xml
@@ -19,8 +19,8 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string-array name="preferred_network_mode_choices_world_mode">
<item msgid="8359756926680194770">"Global"</item>
- <item msgid="7497128470871581354">"LTE/CDMA"</item>
- <item msgid="1732367262765147258">"LTE/GSM/UMTS"</item>
+ <item msgid="7497128470871581354">"LTE / CDMA"</item>
+ <item msgid="1732367262765147258">"LTE / GSM / UMTS"</item>
</string-array>
<string-array name="preferred_network_mode_values_world_mode">
<item msgid="7956157363792248686">"10"</item>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 6e5e368..b8c32d9 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="phoneAppLabel" product="tablet" msgid="1916019789885839910">"Mobile Data"</string>
<string name="phoneAppLabel" product="default" msgid="130465039375347763">"Phone Services"</string>
- <string name="emergencyDialerIconLabel" msgid="8668005772339436680">"Emergency Dialler"</string>
+ <string name="emergencyDialerIconLabel" msgid="8668005772339436680">"Emergency Dialer"</string>
<string name="phoneIconLabel" msgid="3015941229249651419">"Phone"</string>
<string name="fdnListLabel" msgid="4119121875004244097">"FDN list"</string>
<string name="unknown" msgid="8279698889921830815">"Unknown"</string>
@@ -26,10 +26,10 @@
<string name="payphone" msgid="7936735771836716941">"Payphone"</string>
<string name="onHold" msgid="6132725550015899006">"On hold"</string>
<string name="carrier_mmi_msg_title" msgid="6050165242447507034">"<xliff:g id="MMICARRIER">%s</xliff:g> Message"</string>
- <string name="default_carrier_mmi_msg_title" msgid="7754317179938537213">"Operator message"</string>
+ <string name="default_carrier_mmi_msg_title" msgid="7754317179938537213">"Carrier Message"</string>
<string name="mmiStarted" msgid="9212975136944568623">"MMI code started"</string>
<string name="ussdRunning" msgid="1163586813106772717">"USSD code running…"</string>
- <string name="mmiCancelled" msgid="5339191899200678272">"MMI code cancelled"</string>
+ <string name="mmiCancelled" msgid="5339191899200678272">"MMI code canceled"</string>
<string name="cancel" msgid="8984206397635155197">"Cancel"</string>
<string name="enter_input" msgid="6193628663039958990">"USSD message must be between <xliff:g id="MIN_LEN">%1$d</xliff:g> and <xliff:g id="MAX_LEN">%2$d</xliff:g> characters. Please try again."</string>
<string name="manageConferenceLabel" msgid="8415044818156353233">"Manage conference call"</string>
@@ -47,7 +47,7 @@
<string name="no_vm_number" msgid="6623853880546176930">"Missing voicemail number"</string>
<string name="no_vm_number_msg" msgid="5165161462411372504">"No voicemail number is stored on the SIM card."</string>
<string name="add_vm_number_str" msgid="7368168964435881637">"Add number"</string>
- <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Voicemail settings can only be modified by the primary user."</string>
+ <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Voicemail Settings can only be modified by the Primary User."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Your SIM card has been unblocked. Your phone is unlocking…"</string>
<string name="label_ndp" msgid="7617392683877410341">"SIM network unlock PIN"</string>
<string name="label_phoneid" msgid="8775611434123577808">"SIM locked for operator"</string>
@@ -61,7 +61,7 @@
<string name="labelGsmMore_with_label" msgid="3206015314393246224">"GSM call settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCDMAMore" msgid="7937441382611224632">"CDMA call settings"</string>
<string name="labelCdmaMore_with_label" msgid="7759692829160238152">"CDMA call settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
- <string name="apn_settings" msgid="1978652203074756623">"Access point names"</string>
+ <string name="apn_settings" msgid="1978652203074756623">"Access Point Names"</string>
<string name="settings_label" msgid="9101778088412567956">"Network settings"</string>
<string name="phone_accounts" msgid="1216879437523774604">"Calling accounts"</string>
<string name="phone_accounts_make_calls_with" msgid="16747814788918145">"Make calls with"</string>
@@ -81,16 +81,16 @@
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Voicemail (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="voicemail_abbreviated" msgid="7746778673131551185">"VM:"</string>
<string name="make_and_receive_calls" msgid="4868913166494621109">"Make & receive calls"</string>
- <string name="smart_forwarding_settings_menu" msgid="8850429887958938540">"Smart forwarding"</string>
+ <string name="smart_forwarding_settings_menu" msgid="8850429887958938540">"Smart Forwarding"</string>
<string name="smart_forwarding_settings_menu_summary" msgid="5096947726032885325">"When one number isn\'t reachable, always forward calls to your other number"</string>
<string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"Notifications"</string>
<string name="cell_broadcast_settings" msgid="8135324242541809924">"Emergency broadcasts"</string>
<string name="call_settings" msgid="3677282690157603818">"Call settings"</string>
<string name="additional_gsm_call_settings" msgid="1561980168685658846">"Additional settings"</string>
<string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"Additional settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
- <string name="sum_gsm_call_settings" msgid="7964692601608878138">"Additional GSM-only call settings"</string>
+ <string name="sum_gsm_call_settings" msgid="7964692601608878138">"Additional GSM only call settings"</string>
<string name="additional_cdma_call_settings" msgid="2178016561980611304">"Additional CDMA call settings"</string>
- <string name="sum_cdma_call_settings" msgid="3185825305136993636">"Additional CDMA-only call settings"</string>
+ <string name="sum_cdma_call_settings" msgid="3185825305136993636">"Additional CDMA only call settings"</string>
<string name="labelNwService" msgid="6015891883487125120">"Network service settings"</string>
<string name="labelCallerId" msgid="2090540744550903172">"Caller ID"</string>
<string name="sum_loading_settings" msgid="434063780286688775">"Loading settings…"</string>
@@ -100,7 +100,7 @@
<string name="labelCW" msgid="8449327023861428622">"Call waiting"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"During a call, notify me of incoming calls"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"During a call, notify me of incoming calls"</string>
- <string name="call_forwarding_settings" msgid="8937130467468257671">"Call-forwarding settings"</string>
+ <string name="call_forwarding_settings" msgid="8937130467468257671">"Call forwarding settings"</string>
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"Call forwarding settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"Call forwarding"</string>
<string name="labelCFU" msgid="8870170873036279706">"Always forward"</string>
@@ -123,14 +123,14 @@
<string name="messageCFNRc" msgid="6980340731313007250">"Number when unreachable"</string>
<string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Forwarding to <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"Off"</string>
- <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Your operator doesn\'t support disabling call forwarding when your phone is unreachable."</string>
- <string name="registration_cf_forbidden" msgid="4386482610771190420">"Your operator doesn\'t support call forwarding."</string>
+ <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Your carrier doesn\'t support disabling call forwarding when your phone is unreachable."</string>
+ <string name="registration_cf_forbidden" msgid="4386482610771190420">"Your carrier doesn\'t support call forwarding."</string>
<string name="cdma_call_waiting" msgid="4565070960879673216">"Turn on call waiting?"</string>
<string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"During a call, you\'ll be notified about incoming calls"</string>
<string name="enable_cdma_cw" msgid="811047045863422232">"Turn on"</string>
<string name="disable_cdma_cw" msgid="7119290446496301734">"Cancel"</string>
- <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA call waiting under IMS on"</string>
- <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA call waiting under IMS off"</string>
+ <string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"CDMA Call Waiting under IMS On"</string>
+ <string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"CDMA Call Waiting under IMS Off"</string>
<string name="updating_title" msgid="6130548922615719689">"Call settings"</string>
<string name="call_settings_admin_user_only" msgid="7238947387649986286">"Call settings can only be changed by the admin user."</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"Settings (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -144,8 +144,8 @@
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"SS request changed to USSD request"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"Changed to new SS request"</string>
<string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"SS request changed to video call"</string>
- <string name="fdn_check_failure" msgid="1833769746374185247">"Your Phone app\'s fixed dialling numbers setting is turned on. As a result, some call-related features aren\'t working."</string>
- <string name="radio_off_error" msgid="8321564164914232181">"Please turn on the radio before viewing these settings."</string>
+ <string name="fdn_check_failure" msgid="1833769746374185247">"Your Phone app\'s Fixed Dialing Numbers setting is turned on. As a result, some call-related features aren\'t working."</string>
+ <string name="radio_off_error" msgid="8321564164914232181">"Turn on the radio before viewing these settings."</string>
<string name="close_dialog" msgid="1074977476136119408">"OK"</string>
<string name="enable" msgid="2636552299455477603">"Turn on"</string>
<string name="disable" msgid="1122698860799462116">"Turn off"</string>
@@ -156,22 +156,22 @@
<item msgid="9150034130629852635">"Show number"</item>
</string-array>
<string name="vm_changed" msgid="4739599044379692505">"Voicemail number changed."</string>
- <string name="vm_change_failed" msgid="7877733929455763566">"Couldn\'t change the voicemail number.\nContact your operator if this problem persists."</string>
- <string name="fw_change_failed" msgid="9179241823460192148">"Couldn\'t change the forwarding number.\nContact your operator if this problem persists."</string>
+ <string name="vm_change_failed" msgid="7877733929455763566">"Couldn\'t change the voicemail number.\nContact your carrier if this problem persists."</string>
+ <string name="fw_change_failed" msgid="9179241823460192148">"Couldn\'t change the forwarding number.\nContact your carrier if this problem persists."</string>
<string name="fw_get_in_vm_failed" msgid="2432678237218183844">"Couldn\'t retrieve and save current forwarding number settings.\nSwitch to the new provider anyway?"</string>
<string name="no_change" msgid="3737264882821031892">"No changes were made."</string>
<string name="sum_voicemail_choose_provider" msgid="6750824719081403773">"Choose voicemail service"</string>
- <string name="voicemail_default" msgid="6427575113775462077">"Your operator"</string>
+ <string name="voicemail_default" msgid="6427575113775462077">"Your carrier"</string>
<string name="vm_change_pin_old_pin" msgid="7154951790929009241">"Old PIN"</string>
<string name="vm_change_pin_new_pin" msgid="2656200418481288069">"New PIN"</string>
<string name="vm_change_pin_progress_message" msgid="626015184502739044">"Please wait."</string>
<string name="vm_change_pin_error_too_short" msgid="1789139338449945483">"The new PIN is too short."</string>
<string name="vm_change_pin_error_too_long" msgid="3634907034310018954">"The new PIN is too long."</string>
- <string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"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="5364847280026257331">"The old PIN doesn\'t match."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"The new PIN is too weak. A strong password should not have continuous sequence or repeated digits."</string>
+ <string name="vm_change_pin_error_mismatch" msgid="5364847280026257331">"The old PIN does not match."</string>
<string name="vm_change_pin_error_invalid" msgid="5230002671175580674">"The new PIN contains invalid characters."</string>
<string name="vm_change_pin_error_system_error" msgid="9116483527909681791">"Unable to change PIN"</string>
- <string name="vvm_unsupported_message_format" msgid="4206402558577739713">"Unsupported message type. Call <xliff:g id="NUMBER">%s</xliff:g> to listen."</string>
+ <string name="vvm_unsupported_message_format" msgid="4206402558577739713">"Unsupported message type, call <xliff:g id="NUMBER">%s</xliff:g> to listen."</string>
<string name="network_settings_title" msgid="7560807107123171541">"Mobile network"</string>
<string name="label_available" msgid="1316084116670821258">"Available networks"</string>
<string name="load_networks_progress" msgid="4051433047717401683">"Searching…"</string>
@@ -179,13 +179,13 @@
<string name="network_query_error" msgid="3862515805115145124">"Couldn\'t find networks. Try again."</string>
<string name="register_on_network" msgid="4194770527833960423">"Registering on <xliff:g id="NETWORK">%s</xliff:g>…"</string>
<string name="not_allowed" msgid="8541221928746104798">"Your SIM card doesn\'t allow a connection to this network."</string>
- <string name="connect_later" msgid="1950138106010005425">"Can\'t connect to this network at the moment. Try again later."</string>
+ <string name="connect_later" msgid="1950138106010005425">"Can\'t connect to this network right now. Try again later."</string>
<string name="registration_done" msgid="5337407023566953292">"Registered on network."</string>
<string name="already_auto" msgid="8607068290733079336">"Already in automatic selection."</string>
<string name="select_automatically" msgid="779750291257872651">"Automatically select network"</string>
<string name="manual_mode_disallowed_summary" msgid="3970048592179890197">"Unavailable when connected to %1$s"</string>
<string name="network_select_title" msgid="4117305053881611988">"Network"</string>
- <string name="register_automatically" msgid="3907580547590554834">"Automatic registration..."</string>
+ <string name="register_automatically" msgid="3907580547590554834">"Automatic registration…"</string>
<string name="preferred_network_mode_title" msgid="5253395265169539830">"Preferred network type"</string>
<string name="preferred_network_mode_summary" msgid="3787989000044330064">"Change the network operating mode"</string>
<string name="preferred_network_mode_dialogtitle" msgid="2781447433514459696">"Preferred network type"</string>
@@ -193,7 +193,7 @@
<string name="choose_network_title" msgid="5335832663422653082">"Choose network"</string>
<string name="network_disconnected" msgid="8844141106841160825">"Disconnected"</string>
<string name="network_connected" msgid="2760235679963580224">"Connected"</string>
- <string name="network_connecting" msgid="160901383582774987">"Connecting…"</string>
+ <string name="network_connecting" msgid="160901383582774987">"Connecting..."</string>
<string name="network_could_not_connect" msgid="6547460848093727998">"Couldn’t connect"</string>
<string-array name="preferred_network_mode_choices">
<item msgid="4531933377509551889">"GSM/WCDMA preferred"</item>
@@ -208,7 +208,7 @@
<item msgid="1694517610683571748">"GSM/WCDMA/LTE"</item>
<item msgid="2431844716050955858">"Global"</item>
<item msgid="8522859526931346931">"LTE"</item>
- <item msgid="7852977970279215000">"LTE/WCDMA"</item>
+ <item msgid="7852977970279215000">"LTE / WCDMA"</item>
<item msgid="5779210256161024981">"TDSCDMA only"</item>
<item msgid="611913646308951205">"TDSCDMA/WCDMA"</item>
<item msgid="1738977207573340604">"LTE/TDSCDMA"</item>
@@ -234,9 +234,9 @@
<string name="preferred_network_mode_wcdma_perf_summary" msgid="7851493369130750126">"Preferred network mode: WCDMA preferred"</string>
<string name="preferred_network_mode_gsm_only_summary" msgid="4323367929994392830">"Preferred network mode: GSM only"</string>
<string name="preferred_network_mode_wcdma_only_summary" msgid="3585482191951442207">"Preferred network mode: WCDMA only"</string>
- <string name="preferred_network_mode_gsm_wcdma_summary" msgid="2988950751948316810">"Preferred network mode: GSM/WCDMA"</string>
+ <string name="preferred_network_mode_gsm_wcdma_summary" msgid="2988950751948316810">"Preferred network mode: GSM / WCDMA"</string>
<string name="preferred_network_mode_cdma_summary" msgid="9127141320343936911">"Preferred network mode: CDMA"</string>
- <string name="preferred_network_mode_cdma_evdo_summary" msgid="3629440709757307077">"Preferred network mode: CDMA/EvDo"</string>
+ <string name="preferred_network_mode_cdma_evdo_summary" msgid="3629440709757307077">"Preferred network mode: CDMA / EvDo"</string>
<string name="preferred_network_mode_cdma_only_summary" msgid="211164451887102568">"Preferred network mode: CDMA only"</string>
<string name="preferred_network_mode_evdo_only_summary" msgid="939116631952132878">"Preferred network mode: EvDo only"</string>
<string name="preferred_network_mode_cdma_evdo_gsm_wcdma_summary" msgid="7891131456022601976">"Preferred network mode: CDMA/EvDo/GSM/WCDMA"</string>
@@ -245,13 +245,13 @@
<string name="preferred_network_mode_lte_cdma_evdo_summary" msgid="5559198623419981805">"Preferred network mode: CDMA+LTE/EVDO"</string>
<string name="preferred_network_mode_lte_cdma_evdo_gsm_wcdma_summary" msgid="6707224437925495615">"Preferred network mode: LTE/CDMA/EvDo/GSM/WCDMA"</string>
<string name="preferred_network_mode_global_summary" msgid="3847086258439582411">"Preferred network mode: Global"</string>
- <string name="preferred_network_mode_lte_wcdma_summary" msgid="7001804022020813865">"Preferred network mode: LTE/WCDMA"</string>
- <string name="preferred_network_mode_lte_gsm_umts_summary" msgid="6484203890156282179">"Preferred network mode: LTE/GSM/UMTS"</string>
- <string name="preferred_network_mode_lte_cdma_summary" msgid="8187929456614068518">"Preferred network mode: LTE/CDMA"</string>
+ <string name="preferred_network_mode_lte_wcdma_summary" msgid="7001804022020813865">"Preferred network mode: LTE / WCDMA"</string>
+ <string name="preferred_network_mode_lte_gsm_umts_summary" msgid="6484203890156282179">"Preferred network mode: LTE / GSM / UMTS"</string>
+ <string name="preferred_network_mode_lte_cdma_summary" msgid="8187929456614068518">"Preferred network mode: LTE / CDMA"</string>
<string name="preferred_network_mode_tdscdma_summary" msgid="3602127224234207206">"Preferred network mode: TDSCDMA"</string>
- <string name="preferred_network_mode_tdscdma_wcdma_summary" msgid="7076968749402201123">"Preferred network mode: TDSCDMA/WCDMA"</string>
- <string name="preferred_network_mode_lte_tdscdma_summary" msgid="3001058390866953624">"Preferred network mode: LTE/TDSCDMA"</string>
- <string name="preferred_network_mode_tdscdma_gsm_summary" msgid="1716983444872465309">"Preferred network mode: TDSCDMA/GSM"</string>
+ <string name="preferred_network_mode_tdscdma_wcdma_summary" msgid="7076968749402201123">"Preferred network mode: TDSCDMA / WCDMA"</string>
+ <string name="preferred_network_mode_lte_tdscdma_summary" msgid="3001058390866953624">"Preferred network mode: LTE / TDSCDMA"</string>
+ <string name="preferred_network_mode_tdscdma_gsm_summary" msgid="1716983444872465309">"Preferred network mode: TDSCDMA / GSM"</string>
<string name="preferred_network_mode_lte_tdscdma_gsm_summary" msgid="1349057007230669585">"Preferred network mode: LTE/GSM/TDSCDMA"</string>
<string name="preferred_network_mode_tdscdma_gsm_wcdma_summary" msgid="2092262901885164194">"Preferred network mode: TDSCDMA/GSM/WCDMA"</string>
<string name="preferred_network_mode_lte_tdscdma_wcdma_summary" msgid="56422129430744466">"Preferred network mode: LTE/TDSCDMA/WCDMA"</string>
@@ -259,7 +259,7 @@
<string name="preferred_network_mode_tdscdma_cdma_evdo_gsm_wcdma_summary" msgid="2779089629254220257">"Preferred network mode: TDSCDMA/CDMA/EvDo/GSM/WCDMA"</string>
<string name="preferred_network_mode_lte_tdscdma_cdma_evdo_gsm_wcdma_summary" msgid="9065672185435798587">"Preferred network mode: LTE/TDSCDMA/CDMA/EvDo/GSM/WCDMA"</string>
<string name="preferred_network_mode_nr_only_summary" msgid="1467452233297987391">"Preferred network mode: NR only"</string>
- <string name="preferred_network_mode_nr_lte_summary" msgid="5890170406507535976">"Preferred network mode: NR/LTE"</string>
+ <string name="preferred_network_mode_nr_lte_summary" msgid="5890170406507535976">"Preferred network mode: NR / LTE"</string>
<string name="preferred_network_mode_nr_lte_cdma_evdo_summary" msgid="5507940227264296616">"Preferred network mode: NR/LTE/CDMA/EvDo"</string>
<string name="preferred_network_mode_nr_lte_gsm_wcdma_summary" msgid="2811179121638665248">"Preferred network mode: NR/LTE/GSM/WCDMA"</string>
<string name="preferred_network_mode_nr_lte_cdma_evdo_gsm_wcdma_summary" msgid="7631365223836621902">"Preferred network mode: NR/LTE/CDMA/EvDo/GSM/WCDMA"</string>
@@ -295,13 +295,13 @@
<string name="limited_sim_function_with_phone_num_notification_message" msgid="5928988883403677610">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> calls and data services may be blocked while using <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>."</string>
<string name="limited_sim_function_notification_message" msgid="5338638075496721160">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> calls and data services may be blocked while using another SIM."</string>
<string name="sip_accounts_removed_notification_title" msgid="3528076957535736095">"Deprecated SIP accounts found and removed"</string>
- <string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"SIP calling is no longer supported by the Android platform.\nYour existing SIP accounts <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> have been removed.\nPlease confirm your default calling account setting."</string>
+ <string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"SIP calling is no longer supported by Android platform.\nYour existing SIP accounts <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> have been removed.\nPlease confirm your default calling account setting."</string>
<string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"Go to settings"</string>
<string name="data_usage_title" msgid="8438592133893837464">"App data usage"</string>
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_1">%1$s</xliff:g> mobile data used <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="advanced_options_title" msgid="9208195294513520934">"Advanced"</string>
<string name="carrier_settings_euicc" msgid="1190237227261337749">"Carrier"</string>
- <string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"operator, esim, sim, euicc, switch operators, add operator"</string>
+ <string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"carrier, esim, sim, euicc, switch carriers, add carrier"</string>
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> — <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
<string name="mobile_data_settings_title" msgid="7228249980933944101">"Mobile data"</string>
<string name="mobile_data_settings_summary" msgid="5012570152029118471">"Access data using mobile network"</string>
@@ -315,20 +315,20 @@
<string name="cdma_options" msgid="3669592472226145665">"CDMA Options"</string>
<string name="throttle_data_usage" msgid="1944145350660420711">"Data usage"</string>
<string name="throttle_current_usage" msgid="7483859109708658613">"Data used in current period"</string>
- <string name="throttle_time_frame" msgid="1813452485948918791">"Data usage period"</string>
+ <string name="throttle_time_frame" msgid="1813452485948918791">"Data use period"</string>
<string name="throttle_rate" msgid="7641913901133634905">"Data rate policy"</string>
<string name="throttle_help" msgid="2624535757028809735">"Learn more"</string>
<string name="throttle_status_subtext" msgid="1110276415078236687">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>٪) of <xliff:g id="USED_2">%3$s</xliff:g> period maximum\nNext period starts in <xliff:g id="USED_3">%4$d</xliff:g> days (<xliff:g id="USED_4">%5$s</xliff:g>)"</string>
<string name="throttle_data_usage_subtext" msgid="3185429653996709840">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>٪) of <xliff:g id="USED_2">%3$s</xliff:g> period maximum"</string>
<string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> maximum exceeded\nData rate reduced to <xliff:g id="USED_1">%2$d</xliff:g> Kb/s"</string>
<string name="throttle_time_frame_subtext" msgid="6462089615392402127">"<xliff:g id="USED_0">%1$d</xliff:g>٪ of cycle elapsed\nNext period starts in <xliff:g id="USED_1">%2$d</xliff:g> days (<xliff:g id="USED_2">%3$s</xliff:g>)"</string>
- <string name="throttle_rate_subtext" msgid="7221971817325779535">"Data rate reduced to <xliff:g id="USED">%1$d</xliff:g> Kb/s if data usage limit is exceeded"</string>
- <string name="throttle_help_subtext" msgid="2817114897095534807">"More information about your operator\'s mobile network data usage policy"</string>
- <string name="cell_broadcast_sms" msgid="4053449797289031063">"Mobile Broadcast SMS"</string>
- <string name="enable_disable_cell_bc_sms" msgid="4759958924031721350">"Mobile Broadcast SMS"</string>
- <string name="cell_bc_sms_enable" msgid="2019708772024632073">"Mobile Broadcast SMS enabled"</string>
- <string name="cell_bc_sms_disable" msgid="1214238639910875347">"Mobile Broadcast SMS disabled"</string>
- <string name="cb_sms_settings" msgid="6858093721831312036">"Mobile Broadcast SMS settings"</string>
+ <string name="throttle_rate_subtext" msgid="7221971817325779535">"Data rate reduced to <xliff:g id="USED">%1$d</xliff:g> Kb/s if data use limit is exceeded"</string>
+ <string name="throttle_help_subtext" msgid="2817114897095534807">"More information about your carrier\'s mobile network data use policy"</string>
+ <string name="cell_broadcast_sms" msgid="4053449797289031063">"Cell Broadcast SMS"</string>
+ <string name="enable_disable_cell_bc_sms" msgid="4759958924031721350">"Cell Broadcast SMS"</string>
+ <string name="cell_bc_sms_enable" msgid="2019708772024632073">"Cell Broadcast SMS enabled"</string>
+ <string name="cell_bc_sms_disable" msgid="1214238639910875347">"Cell Broadcast SMS disabled"</string>
+ <string name="cb_sms_settings" msgid="6858093721831312036">"Cell Broadcast SMS settings"</string>
<string name="enable_disable_emergency_broadcast" msgid="6325655044472196496">"Emergency Broadcast"</string>
<string name="emergency_broadcast_enable" msgid="5759610647771102442">"Emergency Broadcast enabled"</string>
<string name="emergency_broadcast_disable" msgid="2844904734469323266">"Emergency Broadcast disabled"</string>
@@ -396,15 +396,15 @@
<string name="enable_disable_advertisements" msgid="8704125663718797151">"Advertisements"</string>
<string name="advertisements_enable" msgid="8651409664217899145">"Advertisements enabled"</string>
<string name="advertisements_disable" msgid="2999957360508271492">"Advertisements disabled"</string>
- <string name="enable_disable_stock_quotes" msgid="631498357725951825">"Share Quotes"</string>
- <string name="stock_quotes_enable" msgid="5104318195579771947">"Share Quotes enabled"</string>
- <string name="stock_quotes_disable" msgid="3126423481704498278">"Share Quotes disabled"</string>
+ <string name="enable_disable_stock_quotes" msgid="631498357725951825">"Stock Quotes"</string>
+ <string name="stock_quotes_enable" msgid="5104318195579771947">"Stock Quotes enabled"</string>
+ <string name="stock_quotes_disable" msgid="3126423481704498278">"Stock Quotes disabled"</string>
<string name="enable_disable_eo" msgid="5730223317238970819">"Employment Opportunities"</string>
<string name="eo_enable" msgid="107713355461019817">"Employment Opportunities enabled"</string>
<string name="eo_disable" msgid="3955421278929647485">"Employment Opportunities disabled"</string>
- <string name="enable_disable_mhh" msgid="715930476289202466">"Medical, Health and Hospital"</string>
- <string name="mhh_enable" msgid="7224396815285147008">"Medical, Health and Hospital enabled"</string>
- <string name="mhh_disable" msgid="5503643028885686265">"Medical, Health and Hospital disabled"</string>
+ <string name="enable_disable_mhh" msgid="715930476289202466">"Medical, Health, and Hospital"</string>
+ <string name="mhh_enable" msgid="7224396815285147008">"Medical, Health, and Hospital enabled"</string>
+ <string name="mhh_disable" msgid="5503643028885686265">"Medical, Health, and Hospital disabled"</string>
<string name="enable_disable_technology_news" msgid="2794845609698078400">"Technology News"</string>
<string name="technology_news_enable" msgid="1908991199492598311">"Technology News enabled"</string>
<string name="technology_news_disable" msgid="8388582607149800889">"Technology News disabled"</string>
@@ -435,20 +435,20 @@
</string-array>
<string name="cdma_activate_device" msgid="5914720276140097632">"Activate device"</string>
<string name="cdma_lte_data_service" msgid="359786441782404562">"Set up data service"</string>
- <string name="carrier_settings_title" msgid="6292869148169850220">"Provider settings"</string>
- <string name="fdn" msgid="2545904344666098749">"Fixed dialling numbers"</string>
- <string name="fdn_with_label" msgid="6412087553365709494">"Fixed dialling numbers (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="carrier_settings_title" msgid="6292869148169850220">"Carrier settings"</string>
+ <string name="fdn" msgid="2545904344666098749">"Fixed Dialing Numbers"</string>
+ <string name="fdn_with_label" msgid="6412087553365709494">"Fixed Dialing Numbers (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="manage_fdn_list" msgid="3341716430375195441">"FDN list"</string>
<string name="fdn_list_with_label" msgid="1409655283510382556">"FDN list (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="fdn_activation" msgid="2178637004710435895">"FDN activation"</string>
- <string name="fdn_enabled" msgid="7017355494808056447">"Fixed dialling numbers are enabled"</string>
- <string name="fdn_disabled" msgid="6696468878037736600">"Fixed dialling numbers are disabled"</string>
+ <string name="fdn_enabled" msgid="7017355494808056447">"Fixed Dialing Numbers are enabled"</string>
+ <string name="fdn_disabled" msgid="6696468878037736600">"Fixed Dialing Numbers are disabled"</string>
<string name="enable_fdn" msgid="4830555730418033723">"Enable FDN"</string>
<string name="disable_fdn" msgid="3918794950264647541">"Disable FDN"</string>
<string name="change_pin2" msgid="3110844547237754871">"Change PIN2"</string>
<string name="enable_fdn_ok" msgid="5080925177369329827">"Disable FDN"</string>
<string name="disable_fdn_ok" msgid="3745475926874838676">"Enable FDN"</string>
- <string name="sum_fdn" msgid="6152246141642323582">"Manage fixed dialling numbers"</string>
+ <string name="sum_fdn" msgid="6152246141642323582">"Manage Fixed Dialing Numbers"</string>
<string name="sum_fdn_change_pin" msgid="3510994280557335727">"Change PIN for FDN access"</string>
<string name="sum_fdn_manage_list" msgid="3311397063233992907">"Manage phone number list"</string>
<string name="voice_privacy" msgid="7346935172372181951">"Voice privacy"</string>
@@ -466,18 +466,18 @@
<string name="name" msgid="1347432469852527784">"Name"</string>
<string name="number" msgid="1564053487748491000">"Number"</string>
<string name="save" msgid="983805790346099749">"Save"</string>
- <string name="add_fdn_contact" msgid="1169713422306640887">"Add fixed dialling number"</string>
- <string name="adding_fdn_contact" msgid="3112531600824361259">"Adding fixed dialling number…"</string>
- <string name="fdn_contact_added" msgid="2840016151693394596">"Fixed dialling number added."</string>
- <string name="edit_fdn_contact" msgid="6030829994819587408">"Edit fixed dialling number"</string>
- <string name="updating_fdn_contact" msgid="6989341376868227150">"Updating fixed dialling number…"</string>
- <string name="fdn_contact_updated" msgid="6876330243323118937">"Fixed dialling number updated."</string>
- <string name="delete_fdn_contact" msgid="7027405651994507077">"Delete fixed dialling number"</string>
- <string name="deleting_fdn_contact" msgid="6872320570844460428">"Deleting fixed dialling number…"</string>
- <string name="fdn_contact_deleted" msgid="1680714996763848838">"Fixed dialling number deleted."</string>
+ <string name="add_fdn_contact" msgid="1169713422306640887">"Add fixed dialing number"</string>
+ <string name="adding_fdn_contact" msgid="3112531600824361259">"Adding fixed dialing number…"</string>
+ <string name="fdn_contact_added" msgid="2840016151693394596">"Fixed dialing number added."</string>
+ <string name="edit_fdn_contact" msgid="6030829994819587408">"Edit fixed dialing number"</string>
+ <string name="updating_fdn_contact" msgid="6989341376868227150">"Updating fixed dialing number…"</string>
+ <string name="fdn_contact_updated" msgid="6876330243323118937">"Fixed dialing number updated."</string>
+ <string name="delete_fdn_contact" msgid="7027405651994507077">"Delete fixed dialing number"</string>
+ <string name="deleting_fdn_contact" msgid="6872320570844460428">"Deleting fixed dialing number…"</string>
+ <string name="fdn_contact_deleted" msgid="1680714996763848838">"Fixed dialing number deleted."</string>
<string name="pin2_invalid" msgid="2313954262684494442">"FDN wasn\'t updated because you typed an incorrect PIN."</string>
<string name="fdn_invalid_number" msgid="9067189814657840439">"FDN wasn\'t updated because the number exceeds <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> digits."</string>
- <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"FDN wasn\'t updated. The PIN2 was incorrect or the phone number was rejected."</string>
+ <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"FDN wasn\'t updated. The PIN2 was incorrect, or the phone number was rejected."</string>
<string name="fdn_failed" msgid="216592346853420250">"FDN operation failed."</string>
<string name="simContacts_emptyLoading" msgid="4989040293858675483">"Reading from SIM card…"</string>
<string name="simContacts_empty" msgid="1135632055473689521">"No contacts on your SIM card."</string>
@@ -489,8 +489,8 @@
<string name="oldPinLabel" msgid="8618515202411987721">"Old PIN"</string>
<string name="newPinLabel" msgid="3585899083055354732">"New PIN"</string>
<string name="confirmPinLabel" msgid="7783531218662473778">"Confirm new PIN"</string>
- <string name="badPin" msgid="4549286285015892321">"The old PIN that you typed isn\'t correct. Try again."</string>
- <string name="mismatchPin" msgid="1467254768290323845">"The PINs that you typed don\'t match. Try again."</string>
+ <string name="badPin" msgid="4549286285015892321">"The old PIN you typed isn\'t correct. Try again."</string>
+ <string name="mismatchPin" msgid="1467254768290323845">"The PINs you typed don\'t match. Try again."</string>
<string name="invalidPin" msgid="7363723429414001979">"Type a PIN that is 4 to 8 numbers."</string>
<string name="disable_sim_pin" msgid="3112303905548613752">"Clear SIM PIN"</string>
<string name="enable_sim_pin" msgid="445461050748318980">"Set SIM PIN"</string>
@@ -520,8 +520,8 @@
<string name="pin2_error_exception" msgid="8116103864600823641">"Network or SIM card error"</string>
<string name="doneButton" msgid="7371209609238460207">"Done"</string>
<string name="voicemail_settings_number_label" msgid="1265118640154688162">"Voicemail number"</string>
- <string name="card_title_dialing" msgid="8742182654254431781">"Dialling"</string>
- <string name="card_title_redialing" msgid="18130232613559964">"Redialling"</string>
+ <string name="card_title_dialing" msgid="8742182654254431781">"Dialing"</string>
+ <string name="card_title_redialing" msgid="18130232613559964">"Redialing"</string>
<string name="card_title_conf_call" msgid="901197309274457427">"Conference call"</string>
<string name="card_title_incoming_call" msgid="881424648458792430">"Incoming call"</string>
<string name="card_title_call_ended" msgid="650223980095026340">"Call ended"</string>
@@ -541,10 +541,10 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Exit emergency callback mode to make a non-emergency call."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Not registered on network."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobile network not available."</string>
- <string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobile network isn\'t available. Connect to a wireless network to make a call."</string>
+ <string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobile network is not available. Connect to a wireless network to make a call."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"To place a call, enter a valid number."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Call failed."</string>
- <string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Call cannot be added at this time. You can try to get in touch by sending a message."</string>
+ <string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Call cannot be added at this time. You can try to reach out by sending a message."</string>
<string name="incall_error_supp_service_unknown" msgid="8751177117194592623">"Service not supported"</string>
<string name="incall_error_supp_service_switch" msgid="5272822448189448479">"Can\'t switch calls."</string>
<string name="incall_error_supp_service_resume" msgid="1276861499306817035">"Can\'t resume call."</string>
@@ -577,7 +577,7 @@
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Use keyboard to dial"</string>
<string name="onscreenHoldText" msgid="4025348842151665191">"Hold"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"End"</string>
- <string name="onscreenShowDialpadText" msgid="658465753816164079">"Dial pad"</string>
+ <string name="onscreenShowDialpadText" msgid="658465753816164079">"Dialpad"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Mute"</string>
<string name="onscreenAddCallText" msgid="9075675082903611677">"Add call"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"Merge calls"</string>
@@ -593,14 +593,14 @@
<string name="singleContactImportedMsg" msgid="3619804066300998934">"Imported contact"</string>
<string name="failedToImportSingleContactMsg" msgid="228095510489830266">"Failed to import contact"</string>
<string name="hac_mode_title" msgid="4127986689621125468">"Hearing aids"</string>
- <string name="hac_mode_summary" msgid="7774989500136009881">"Turn on hearing-aid compatibility"</string>
+ <string name="hac_mode_summary" msgid="7774989500136009881">"Turn on hearing aid compatibility"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Real-time text (RTT) call"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"Allow messaging within a voice call"</string>
- <string name="rtt_mode_more_information" msgid="587500128658756318">"RTT assists callers who are deaf, hard of hearing, have a speech disability or need more than voice alone.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Learn more</a>\n <br><br> – RTT calls are saved as a message transcript\n <br> – RTT is not available for video calls"</string>
+ <string name="rtt_mode_more_information" msgid="587500128658756318">"RTT assists callers who are deaf, hard of hearing, have a speech disability, or need more than voice alone.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Learn more</a>\n <br><br> - RTT calls are saved as a message transcript\n <br> - RTT is not available for video calls"</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"Note: RTT is not available while roaming"</string>
<string-array name="tty_mode_entries">
- <item msgid="3238070884803849303">"TTY off"</item>
- <item msgid="1449091874731375214">"TTY full"</item>
+ <item msgid="3238070884803849303">"TTY Off"</item>
+ <item msgid="1449091874731375214">"TTY Full"</item>
<item msgid="1044179293199519425">"TTY HCO"</item>
<item msgid="2131559553795606483">"TTY VCO"</item>
</string-array>
@@ -617,7 +617,7 @@
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Activating..."</string>
<string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"The phone is activating your mobile data service.\n\nThis can take up to 5 minutes."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Skip activation?"</string>
- <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"If you skip activation, you can\'t place calls or connect to mobile data networks (though you can connect to Wi-Fi networks). Until you activate your phone, you are asked to activate it each time that you turn it on."</string>
+ <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"If you skip activation, you can\'t place calls or connect to mobile data networks (though you can connect to Wi-Fi networks). Until you activate your phone, you are asked to activate it each time you turn it on."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Skip"</string>
<string name="ota_activate" msgid="7939695753665438357">"Activate"</string>
<string name="ota_title_activate_success" msgid="1272135024761004889">"Phone is activated."</string>
@@ -625,9 +625,9 @@
<string name="ota_listen" msgid="2772252405488894280">"Follow the spoken instructions until you hear that activation is complete."</string>
<string name="ota_speaker" msgid="1086766980329820528">"Speaker"</string>
<string name="ota_progress" msgid="8837259285255700132">"Programming your phone…"</string>
- <string name="ota_failure" msgid="5674217489921481576">"Couldn\'t programme your phone"</string>
+ <string name="ota_failure" msgid="5674217489921481576">"Couldn\'t program your phone"</string>
<string name="ota_successful" msgid="1106825981548107774">"Your phone is now activated. It may take up to 15 minutes for service to start."</string>
- <string name="ota_unsuccessful" msgid="8531037653803955754">"Your phone didn\'t activate. \nYou may need to find an area with better coverage (near a window or outside). \n\nTry again or call customer service for more options."</string>
+ <string name="ota_unsuccessful" msgid="8531037653803955754">"Your phone didn\'t activate. \nYou may need to find an area with better coverage (near a window, or outside). \n\nTry again or call customer service for more options."</string>
<string name="ota_spc_failure" msgid="904092035241370080">"EXCESS SPC FAILURES"</string>
<string name="ota_call_end" msgid="8657746378290737034">"Back"</string>
<string name="ota_try_again" msgid="6914781945599998550">"Try again"</string>
@@ -637,9 +637,9 @@
<string name="phone_in_ecm_notification_title" msgid="6825016389926367946">"Emergency Callback Mode"</string>
<string name="phone_in_ecm_call_notification_text" msgid="653972232922670335">"Data connection disabled"</string>
<string name="phone_in_ecm_notification_complete_time" msgid="7341624337163082759">"No data connection until <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
- <string name="alert_dialog_exit_ecm" msgid="7661603870224398025">"{count,plural, =1{The phone will be in emergency callback mode for one minute. While in this mode, no apps using a data connection can be used. Do you want to exit now?}other{The phone will be in emergency callback mode for %s minutes. While in this mode, no applications using a data connection can be used. Do you want to exit now?}}"</string>
- <string name="alert_dialog_not_avaialble_in_ecm" msgid="8717711120099503279">"{count,plural, =1{The selected action isn\'t available while in the emergency callback mode. The phone will be in this mode for one minute. Do you want to exit now?}other{The selected action isn\'t available while in the emergency callback mode. The phone will be in this mode for %s minutes. Do you want to exit now?}}"</string>
- <string name="alert_dialog_in_ecm_call" msgid="1207545603149771978">"The action selected isn\'t available during an emergency call."</string>
+ <string name="alert_dialog_exit_ecm" msgid="7661603870224398025">"{count,plural, =1{The phone will be in Emergency Callback mode for one minute. While in this mode no apps using a data connection can be used. Do you want to exit now?}other{The phone will be in Emergency Callback mode for %s minutes. While in this mode no applications using a data connection can be used. Do you want to exit now?}}"</string>
+ <string name="alert_dialog_not_avaialble_in_ecm" msgid="8717711120099503279">"{count,plural, =1{The selected action isn\'t available while in the Emergency Callback mode. The phone will be in this mode for one minute. Do you want to exit now?}other{The selected action isn\'t available while in the Emergency Callback mode. The phone will be in this mode for %s minutes. Do you want to exit now?}}"</string>
+ <string name="alert_dialog_in_ecm_call" msgid="1207545603149771978">"The selected action isn\'t available while in an emergency call."</string>
<string name="progress_dialog_exiting_ecm" msgid="9159080081676927217">"Exiting Emergency Callback mode"</string>
<string name="alert_dialog_yes" msgid="3532525979632841417">"Yes"</string>
<string name="alert_dialog_no" msgid="1075632654085988420">"No"</string>
@@ -657,8 +657,8 @@
<string name="selectContact" msgid="1527612842599767382">"select contact"</string>
<string name="not_voice_capable" msgid="2819996734252084253">"Voice calling not supported"</string>
<string name="description_dial_button" msgid="8614631902795087259">"dial"</string>
- <string name="description_dialpad_button" msgid="7395114120463883623">"show dial pad"</string>
- <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Emergency dial pad"</string>
+ <string name="description_dialpad_button" msgid="7395114120463883623">"show dialpad"</string>
+ <string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Emergency Dialpad"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"Visual Voicemail"</string>
<string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"Set PIN"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Change PIN"</string>
@@ -677,7 +677,7 @@
<string name="message_decode_error" msgid="1061856591500290887">"There was an error while decoding the message."</string>
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"A SIM card has activated your service and updated your phone\'s roaming capabilities."</string>
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"There are too many active calls. Please end or merge existing calls before placing a new one."</string>
- <string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Unable to connect. Please insert a valid SIM card."</string>
+ <string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Unable to connect, please insert a valid SIM card."</string>
<string name="callFailed_wifi_lost" msgid="1788036730589163141">"Wi-Fi connection lost. Call ended."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"Your video call cannot be placed due to low battery."</string>
<string name="callFailed_low_battery" msgid="4056828320214416182">"Video call ended due to low battery."</string>
@@ -686,11 +686,11 @@
<string name="change_pin_title" msgid="3564254326626797321">"Change Voicemail PIN"</string>
<string name="change_pin_continue_label" msgid="5177011752453506371">"Continue"</string>
<string name="change_pin_cancel_label" msgid="2301711566758827936">"Cancel"</string>
- <string name="change_pin_ok_label" msgid="6861082678817785330">"OK"</string>
+ <string name="change_pin_ok_label" msgid="6861082678817785330">"Ok"</string>
<string name="change_pin_enter_old_pin_header" msgid="853151335217594829">"Confirm your old PIN"</string>
<string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"Enter your voicemail PIN to continue."</string>
<string name="change_pin_enter_new_pin_header" msgid="4739465616733486118">"Set a new PIN"</string>
- <string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"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_enter_new_pin_hint" msgid="2326038476516364210">"PIN must be <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g> digits."</string>
<string name="change_pin_confirm_pin_header" msgid="2606303906320705726">"Confirm your PIN"</string>
<string name="change_pin_confirm_pins_dont_match" msgid="305164501222587215">"PINs don\'t match"</string>
<string name="change_pin_succeeded" msgid="2504705600693014403">"Voicemail PIN updated"</string>
@@ -787,14 +787,14 @@
<string name="call_barring_change_pwd_description" msgid="1274245130382054227">"Change call barring password"</string>
<string name="call_barring_change_pwd_description_disabled" msgid="2911647051915343920">"Cannot change call barring password"</string>
<string name="call_barring_pwd_not_match" msgid="7638198747579019826">"Passwords do not match"</string>
- <string name="call_barring_right_pwd_number" msgid="3860630926460851330">"Enter a password with four numbers"</string>
+ <string name="call_barring_right_pwd_number" msgid="3860630926460851330">"Enter a password with 4 numbers"</string>
<string name="call_barring_change_pwd_success" msgid="1837437691277936903">"Password changed"</string>
<string name="call_barring_old_pwd" msgid="5500085633281388281">"Old password"</string>
<string name="call_barring_new_pwd" msgid="2515524903813227732">"New password"</string>
<string name="call_barring_confirm_pwd" msgid="7552526161616461858">"Confirm password"</string>
<string name="messageCallBarring" msgid="5537730400652466912">"Enter password"</string>
<string name="call_barring_settings" msgid="4616607285790258919">"Call barring settings"</string>
- <string name="callFailed_NetworkBusy" msgid="5437103975842913681">"Network is busy. Please try placing your call again later."</string>
+ <string name="callFailed_NetworkBusy" msgid="5437103975842913681">"Network is busy. Please try your call again later."</string>
<string name="callFailed_NetworkCongested" msgid="6801283142342775380">"Network is congested. Contact your mobile operator for assistance."</string>
<string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"Call deflected."</string>
<string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"Call forwarded."</string>
@@ -814,111 +814,115 @@
<string name="supp_service_conference_call" msgid="4004193534408317148">"Joining conference call."</string>
<string name="supp_service_held_call_released" msgid="2847835124639112410">"Held call has been released."</string>
<string name="callFailed_otasp_provisioning_in_process" msgid="3345666183602879326">"Cannot place a call as the device is currently being provisioned."</string>
- <string name="callFailed_already_dialing" msgid="7250591188960691086">"Cannot place a call as another outgoing call is already dialling."</string>
+ <string name="callFailed_already_dialing" msgid="7250591188960691086">"Cannot place a call as another outgoing call is already dialing."</string>
<string name="callFailed_already_ringing" msgid="2376603543544289303">"Cannot place a call as there is an unanswered incoming call. Answer or reject the incoming call prior to placing a new call."</string>
<string name="callFailed_calling_disabled" msgid="5010992739401206283">"Cannot place a call as calling has been disabled using the ro.telephony.disable-call system property."</string>
<string name="callFailed_too_many_calls" msgid="2761754044990799580">"Cannot place a call as there are already two calls in progress. Disconnect one of the calls or merge them into a conference prior to placing a new call."</string>
- <string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"To use <xliff:g id="SUPP_SERVICE">%s</xliff:g>, make sure that mobile data is turned on. You can change this in mobile network settings."</string>
- <string name="supp_service_over_ut_precautions_roaming" msgid="670342104569972327">"To use <xliff:g id="SUPP_SERVICE">%s</xliff:g>, make sure that mobile data and data roaming are turned on. You can change these in mobile network settings."</string>
- <string name="supp_service_over_ut_precautions_dual_sim" msgid="5166866975550910474">"To use <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, make sure that mobile data is turned on for SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g>. You can change this in mobile network settings."</string>
- <string name="supp_service_over_ut_precautions_roaming_dual_sim" msgid="6627654855191817965">"To use <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, make sure that mobile data and data roaming are turned on for SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g>. You can change these in mobile network settings."</string>
+ <string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"To use <xliff:g id="SUPP_SERVICE">%s</xliff:g>, make sure mobile data is turned on. You can change this in mobile network settings."</string>
+ <string name="supp_service_over_ut_precautions_roaming" msgid="670342104569972327">"To use <xliff:g id="SUPP_SERVICE">%s</xliff:g>, make sure mobile data and data roaming are turned on. You can change these in mobile network settings."</string>
+ <string name="supp_service_over_ut_precautions_dual_sim" msgid="5166866975550910474">"To use <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, make sure mobile data is turned on for SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g>. You can change this in mobile network settings."</string>
+ <string name="supp_service_over_ut_precautions_roaming_dual_sim" msgid="6627654855191817965">"To use <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, make sure mobile data and data roaming are turned on for SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g>. You can change these in mobile network settings."</string>
<string name="supp_service_over_ut_precautions_dialog_dismiss" msgid="5934541487903081652">"Dismiss"</string>
- <string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Enable data connection"</string>
- <string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Disable data connection"</string>
- <string name="volte_provisioned_switch_string" msgid="4812874990480336178">"VoLTE provisioned"</string>
- <string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Video calling provisioned"</string>
- <string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Wi-Fi calling provisioned"</string>
- <string name="eab_provisioned_switch_string" msgid="4449676720736033035">"EAB/Presence provisioned"</string>
- <string name="cbrs_data_switch_string" msgid="6060356430838077653">"CBRS data"</string>
+ <string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Enable Data Connection"</string>
+ <string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Disable Data Connection"</string>
+ <string name="volte_provisioned_switch_string" msgid="4812874990480336178">"VoLTE Provisioned"</string>
+ <string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Video Calling Provisioned"</string>
+ <string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Wifi Calling Provisioned"</string>
+ <string name="eab_provisioned_switch_string" msgid="4449676720736033035">"EAB/Presence Provisioned"</string>
+ <string name="cbrs_data_switch_string" msgid="6060356430838077653">"Cbrs Data"</string>
<string name="dsds_switch_string" msgid="7564769822086764796">"Enable DSDS"</string>
- <string name="dsds_dialog_title" msgid="8494569893941847575">"Restart device?"</string>
+ <string name="dsds_dialog_title" msgid="8494569893941847575">"Restart Device?"</string>
<string name="dsds_dialog_message" msgid="4047480385678538850">"You need to restart your device to change this setting."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Restart"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancel"</string>
- <string name="radio_info_radio_power" msgid="8805595022160471587">"Mobile radio power"</string>
- <string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"View SIM address book"</string>
- <string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"View fixed dialling numbers"</string>
- <string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"View service dialling numbers"</string>
- <string name="radioInfo_menu_getIMS" msgid="1950869267853198232">"IMS service status"</string>
- <string name="radio_info_ims_reg_status_title" msgid="6875885401313992007">"IMS status"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Set Removable eSIM as Default"</string>
+ <string name="radio_info_radio_power" msgid="8805595022160471587">"Mobile Radio Power"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulate Out of Service (Debug Build only)"</string>
+ <string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"View SIM Address Book"</string>
+ <string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"View Fixed Dialing Numbers"</string>
+ <string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"View Service Dialing Numbers"</string>
+ <string name="radioInfo_menu_getIMS" msgid="1950869267853198232">"IMS Service Status"</string>
+ <string name="radio_info_ims_reg_status_title" msgid="6875885401313992007">"IMS Status"</string>
<string name="radio_info_ims_reg_status_registered" msgid="7095182114078864326">"Registered"</string>
- <string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"Not registered"</string>
+ <string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"Not Registered"</string>
<string name="radio_info_ims_feature_status_available" msgid="6493200914756969292">"Available"</string>
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"Unavailable"</string>
- <string name="radio_info_ims_reg_status" msgid="25582845222446390">"IMS registration: <xliff:g id="STATUS">%1$s</xliff:g>\nVoice over LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nVoice over Wi-Fi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nVideo calling: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT interface: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
- <string name="radioInfo_service_in" msgid="45753418231446400">"In service"</string>
- <string name="radioInfo_service_out" msgid="287972405416142312">"Out of service"</string>
- <string name="radioInfo_service_emergency" msgid="4763879891415016848">"Emergency calls only"</string>
- <string name="radioInfo_service_off" msgid="3456583511226783064">"Radio off"</string>
+ <string name="radio_info_ims_reg_status" msgid="25582845222446390">"IMS Registration: <xliff:g id="STATUS">%1$s</xliff:g>\nVoice over LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nVoice over WiFi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nVideo Calling: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT Interface: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
+ <string name="radioInfo_service_in" msgid="45753418231446400">"In Service"</string>
+ <string name="radioInfo_service_out" msgid="287972405416142312">"Out of Service"</string>
+ <string name="radioInfo_service_emergency" msgid="4763879891415016848">"Emergency Calls Only"</string>
+ <string name="radioInfo_service_off" msgid="3456583511226783064">"Radio Off"</string>
<string name="radioInfo_roaming_in" msgid="3156335577793145965">"Roaming"</string>
- <string name="radioInfo_roaming_not" msgid="1904547918725478110">"Not roaming"</string>
+ <string name="radioInfo_roaming_not" msgid="1904547918725478110">"Not Roaming"</string>
<string name="radioInfo_phone_idle" msgid="2191653783170757819">"Idle"</string>
<string name="radioInfo_phone_ringing" msgid="8100354169567413370">"Ringing"</string>
- <string name="radioInfo_phone_offhook" msgid="7564601639749936170">"Call in progress"</string>
+ <string name="radioInfo_phone_offhook" msgid="7564601639749936170">"Call in Progress"</string>
<string name="radioInfo_data_disconnected" msgid="8085447971880814541">"Disconnected"</string>
<string name="radioInfo_data_connecting" msgid="925092271092152472">"Connecting"</string>
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Connected"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspended"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Unknown"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primary"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
<string name="radioInfo_display_asu" msgid="2247752203249646956">"asu"</string>
<string name="radioInfo_lac" msgid="3892986460272607013">"LAC"</string>
<string name="radioInfo_cid" msgid="1423185536264406705">"CID"</string>
- <string name="radio_info_subid" msgid="6839966868621703203">"Current subID:"</string>
+ <string name="radio_info_subid" msgid="6839966868621703203">"Current subId:"</string>
<string name="radio_info_dds" msgid="1122593144425697126">"SubId of default data SIM:"</string>
- <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL bandwidth (kbps):"</string>
- <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL bandwidth (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE physical channel configuration:"</string>
- <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Mobile info refresh rate:"</string>
- <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All mobile measurement info:"</string>
- <string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data service:"</string>
+ <string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL Bandwidth (kbps):"</string>
+ <string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL Bandwidth (kbps):"</string>
+ <string name="radio_info_phy_chan_config" msgid="1277949603275436081">"LTE Physical Channel Configuration:"</string>
+ <string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"Cell Info Refresh Rate:"</string>
+ <string name="radio_info_cellinfo_label" msgid="8199062974670377659">"All Cell Measurement Info:"</string>
+ <string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Data Service:"</string>
<string name="radio_info_roaming_label" msgid="6636932886446857120">"Roaming:"</string>
<string name="radio_info_imei_label" msgid="8947899706930120368">"IMEI:"</string>
- <string name="radio_info_call_redirect_label" msgid="4526480903023362276">"Call redirect:"</string>
- <string name="radio_info_ppp_resets_label" msgid="9131901102339077661">"Number of PPP reset since boot:"</string>
- <string name="radio_info_current_network_label" msgid="3052098695239642450">"Current network:"</string>
- <string name="radio_info_ppp_received_label" msgid="5753592451640644889">"Data received:"</string>
- <string name="radio_info_gsm_service_label" msgid="6443348321714241328">"Voice service:"</string>
- <string name="radio_info_signal_strength_label" msgid="5545444702102543260">"Signal strength"</string>
- <string name="radio_info_call_status_label" msgid="7693575431923095487">"Voice call status:"</string>
- <string name="radio_info_ppp_sent_label" msgid="6542208429356199695">"Data sent"</string>
- <string name="radio_info_message_waiting_label" msgid="1886549432566952078">"Message waiting:"</string>
- <string name="radio_info_phone_number_label" msgid="2533852539562512203">"Phone number:"</string>
- <string name="radio_info_band_mode_label" msgid="23480556225515290">"Select radio band"</string>
- <string name="radio_info_voice_network_type_label" msgid="2395347336419593265">"Voice network type:"</string>
- <string name="radio_info_data_network_type_label" msgid="8886597029237501929">"Data network type:"</string>
- <string name="radio_info_override_network_type_label" msgid="4176280017221092005">"Override network type:"</string>
+ <string name="radio_info_call_redirect_label" msgid="4526480903023362276">"Call Redirect:"</string>
+ <string name="radio_info_ppp_resets_label" msgid="9131901102339077661">"Number of PPP Reset Since Boot:"</string>
+ <string name="radio_info_current_network_label" msgid="3052098695239642450">"Current Network:"</string>
+ <string name="radio_info_ppp_received_label" msgid="5753592451640644889">"Data Received:"</string>
+ <string name="radio_info_gsm_service_label" msgid="6443348321714241328">"Voice Service:"</string>
+ <string name="radio_info_signal_strength_label" msgid="5545444702102543260">"Signal Strength:"</string>
+ <string name="radio_info_call_status_label" msgid="7693575431923095487">"Voice Call Status:"</string>
+ <string name="radio_info_ppp_sent_label" msgid="6542208429356199695">"Data Sent:"</string>
+ <string name="radio_info_message_waiting_label" msgid="1886549432566952078">"Message Waiting:"</string>
+ <string name="radio_info_phone_number_label" msgid="2533852539562512203">"Phone Number:"</string>
+ <string name="radio_info_band_mode_label" msgid="23480556225515290">"Select Radio Band"</string>
+ <string name="radio_info_voice_network_type_label" msgid="2395347336419593265">"Voice Network Type:"</string>
+ <string name="radio_info_data_network_type_label" msgid="8886597029237501929">"Data Network Type:"</string>
+ <string name="radio_info_override_network_type_label" msgid="4176280017221092005">"Override Network Type:"</string>
<string name="phone_index_label" msgid="6222406512768964268">"Select phone index"</string>
- <string name="radio_info_set_perferred_label" msgid="7408131389363136210">"Set preferred network type:"</string>
- <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Ping hostname(www.google.com) IPv4:"</string>
- <string name="radio_info_ping_hostname_v6" msgid="2748637889486554603">"Ping hostname(www.google.com) IPv6:"</string>
- <string name="radio_info_http_client_test" msgid="1329583721088428238">"HTTP client test:"</string>
- <string name="ping_test_label" msgid="448617502935719694">"Run ping test"</string>
+ <string name="radio_info_set_perferred_label" msgid="7408131389363136210">"Set Preferred Network Type:"</string>
+ <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Ping Hostname(www.google.com) IPv4:"</string>
+ <string name="radio_info_ping_hostname_v6" msgid="2748637889486554603">"Ping Hostname(www.google.com) IPv6:"</string>
+ <string name="radio_info_http_client_test" msgid="1329583721088428238">"HTTP Client Test:"</string>
+ <string name="ping_test_label" msgid="448617502935719694">"Run Ping Test"</string>
<string name="radio_info_smsc_label" msgid="3749927072726033763">"SMSC:"</string>
<string name="radio_info_smsc_update_label" msgid="5141996256097115753">"Update"</string>
<string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Refresh"</string>
- <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Toggle DNS check"</string>
- <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specific info/settings"</string>
- <string name="radio_info_endc_available" msgid="2983767110681230019">"EN-DC available (NSA):"</string>
- <string name="radio_info_dcnr_restricted" msgid="7147511536420148173">"DCNR restricted (NSA):"</string>
- <string name="radio_info_nr_available" msgid="3383388088451237182">"NR available (NSA):"</string>
- <string name="radio_info_nr_state" msgid="4158805093187555149">"NR state (NSA):"</string>
- <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR frequency:"</string>
- <string name="band_mode_title" msgid="7988822920724576842">"Set radio band mode"</string>
- <string name="band_mode_loading" msgid="795923726636735967">"Loading band list…"</string>
+ <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Toggle DNS Check"</string>
+ <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-specific Info/Settings"</string>
+ <string name="radio_info_endc_available" msgid="2983767110681230019">"EN-DC Available (NSA):"</string>
+ <string name="radio_info_dcnr_restricted" msgid="7147511536420148173">"DCNR Restricted (NSA):"</string>
+ <string name="radio_info_nr_available" msgid="3383388088451237182">"NR Available (NSA):"</string>
+ <string name="radio_info_nr_state" msgid="4158805093187555149">"NR State (NSA):"</string>
+ <string name="radio_info_nr_frequency" msgid="1201156032796584128">"NR Frequency:"</string>
+ <string name="band_mode_title" msgid="7988822920724576842">"Set Radio Band Mode"</string>
+ <string name="band_mode_loading" msgid="795923726636735967">"Loading Band List…"</string>
<string name="band_mode_set" msgid="6657819412803771421">"Set"</string>
<string name="band_mode_failed" msgid="1707488541847192924">"Unsuccessful"</string>
<string name="band_mode_succeeded" msgid="2230018000534761063">"Successful"</string>
<string name="phone_info_label" product="tablet" msgid="7477478709388477397">"Tablet info"</string>
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
- <string name="carrier_provisioning" msgid="2668065041869578376">"Operator provisioning info"</string>
- <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger operator provisioning"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Update"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Refresh"</string>
- <string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Your Bluetooth signal is weak. Try switching to speakerphone."</string>
- <string name="call_quality_notification_name" msgid="3476828289553948830">"Call quality notification"</string>
+ <string name="carrier_provisioning" msgid="2668065041869578376">"Carrier Provisioning Info"</string>
+ <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger Carrier Provisioning"</string>
+ <string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Your bluetooth signal is weak. Try switching to speakerphone."</string>
+ <string name="call_quality_notification_name" msgid="3476828289553948830">"Call Quality Notification"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Deprecated SIP accounts"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Can\'t send message from this profile"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Your work policy allows you to send message only from the work profile"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancel"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Switch to work profile"</string>
</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index cede509..dd8cb49 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"You need to restart your device to change this setting."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Restart"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancel"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Set removable eSIM as default"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobile radio power"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulate out of service (debug build only)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"View SIM address book"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"View fixed dialling numbers"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"View service dialling numbers"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Connected"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspended"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Unknown"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primary"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operator provisioning info"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger operator provisioning"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Update"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Refresh"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Your Bluetooth signal is weak. Try switching to speakerphone."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Call quality notification"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Deprecated SIP accounts"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Can\'t send message from this profile"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Your work policy allows you to send messages only from the work profile"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancel"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Switch to work profile"</string>
</resources>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index cede509..dd8cb49 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"You need to restart your device to change this setting."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Restart"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancel"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Set removable eSIM as default"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobile radio power"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulate out of service (debug build only)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"View SIM address book"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"View fixed dialling numbers"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"View service dialling numbers"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Connected"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspended"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Unknown"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primary"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operator provisioning info"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger operator provisioning"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Update"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Refresh"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Your Bluetooth signal is weak. Try switching to speakerphone."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Call quality notification"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Deprecated SIP accounts"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Can\'t send message from this profile"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Your work policy allows you to send messages only from the work profile"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancel"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Switch to work profile"</string>
</resources>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index 09d28cf..f8b0898 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"You need to restart your device to change this setting."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Restart"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancel"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Set Removable eSIM as Default"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobile Radio Power"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulate Out of Service (Debug Build only)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"View SIM Address Book"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"View Fixed Dialing Numbers"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"View Service Dialing Numbers"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Connected"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspended"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Unknown"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primary"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Phone info"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Carrier Provisioning Info"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger Carrier Provisioning"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Update"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Refresh"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Your bluetooth signal is weak. Try switching to speakerphone."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Call Quality Notification"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Deprecated SIP accounts"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Can\'t send message from this profile"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Your work policy allows you to send message only from the work profile"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancel"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Switch to work profile"</string>
</resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 882900c..82b4422 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -34,7 +34,7 @@
<string name="enter_input" msgid="6193628663039958990">"El mensaje USSD debe tener entre <xliff:g id="MIN_LEN">%1$d</xliff:g> y <xliff:g id="MAX_LEN">%2$d</xliff:g> caracteres. Vuelve a intentarlo."</string>
<string name="manageConferenceLabel" msgid="8415044818156353233">"Administrar conferencia telefónica"</string>
<string name="ok" msgid="7818974223666140165">"Aceptar"</string>
- <string name="audio_mode_speaker" msgid="243689733219312360">"Altavoz"</string>
+ <string name="audio_mode_speaker" msgid="243689733219312360">"Bocina"</string>
<string name="audio_mode_earpiece" msgid="2823700267171134282">"Auricular"</string>
<string name="audio_mode_wired_headset" msgid="5028010823105817443">"Auriculares con cable"</string>
<string name="audio_mode_bluetooth" msgid="25732183428018809">"Bluetooth"</string>
@@ -115,7 +115,7 @@
<string name="sum_cfb_disabled" msgid="3589913334164866035">"Desactivado"</string>
<string name="disable_cfb_forbidden" msgid="4831494744351633961">"Tu proveedor no admite la inhabilitación del desvío de llamadas cuando tu teléfono está ocupado."</string>
<string name="labelCFNRy" msgid="3403533792248457946">"Cuando no haya respuesta"</string>
- <string name="messageCFNRy" msgid="7644434155765359009">"Número cuando no contesta"</string>
+ <string name="messageCFNRy" msgid="7644434155765359009">"Número cuando no hay respuesta"</string>
<string name="sum_cfnry_enabled" msgid="3000500837493854799">"Reenviar a <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnry_disabled" msgid="1990563512406017880">"Desactivado"</string>
<string name="disable_cfnry_forbidden" msgid="3174731413216550689">"Tu proveedor no admite la inhabilitación del desvío de llamadas cuando tu teléfono no responde."</string>
@@ -575,7 +575,7 @@
<string name="fire_type_description" msgid="6565200468934914930">"Bomberos"</string>
<string name="description_concat_format" msgid="2014471565101724088">"%1$s, %2$s"</string>
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Utilizar teclado para marcar"</string>
- <string name="onscreenHoldText" msgid="4025348842151665191">"Retener"</string>
+ <string name="onscreenHoldText" msgid="4025348842151665191">"Pausar"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"Finalizar"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"Teclado telefónico"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Silenciar"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Debes reiniciar el dispositivo para cambiar este parámetro de configuración."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Reiniciar"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancelar"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Establecer eSIM extraíble como predeterminada"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Potencia de la señal móvil"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simular fuera de servicio (solo para la compilación de depuración)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Ver libreta de direcciones de SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Ver números de marcación fija"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Ver números de marcación de servicio"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Conectado"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspendido"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Desconocido"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"paquetes"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Información del teléfono"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Información del aprovisionamiento del proveedor"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Activar aprovisionamiento del proveedor"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID de derecho de WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Actualizar"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Actualizar"</string>
- <string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Tu señal de Bluetooth es débil. Intenta cambiar al altavoz."</string>
+ <string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Tu señal de Bluetooth es débil. Intenta cambiar a la bocina."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notificación de calidad de llamada"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Cuentas SIP obsoletas"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"No se puede enviar un mensaje desde este perfil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Tu política de trabajo te permite enviar mensajes solo desde el perfil de trabajo."</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancelar"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Cambiar al perfil de trabajo"</string>
</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 2759dbb..d87b856 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -575,7 +575,7 @@
<string name="fire_type_description" msgid="6565200468934914930">"Bomberos"</string>
<string name="description_concat_format" msgid="2014471565101724088">"%1$s, %2$s"</string>
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Utilizar teclado para marcar"</string>
- <string name="onscreenHoldText" msgid="4025348842151665191">"Retener"</string>
+ <string name="onscreenHoldText" msgid="4025348842151665191">"Pausar"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"Finalizar"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"Teclado"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Silenciar"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Debes reiniciar el dispositivo para cambiar este ajuste."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Reiniciar"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancelar"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Establecer eSIM extraíble como predeterminada"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Potencia de la señal móvil"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simular fuera del servicio (solo versión de depuración)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Ver libreta de direcciones de tarjeta SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Ver números de marcación fija"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Ver números de marcación de servicio"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Conectado"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspendido"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Desconocido"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pqts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Información sobre el teléfono"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Información de servicios del operador"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Activar servicios del operador"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID de derecho a WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Actualizar"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Actualizar"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Tu señal de Bluetooth es débil. Prueba a cambiar al altavoz."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notificación de calidad de la llamada"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Cuentas SIP obsoletas"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"No se puede enviar el mensaje desde este perfil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Tu política de trabajo te permite enviar mensajes solo desde el perfil de trabajo"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancelar"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Cambiar al perfil de trabajo"</string>
</resources>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index b1ca47c..e19f66a 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Selle seade muutmiseks peate seadme taaskäivitama."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Taaskäivita"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Tühista"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Eemaldatava eSIM-i määramine vaikevalikuks"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobiiliraadio toide"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simuleerimine ei tööta (ainult silumisjärgus)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Kuva SIM-i aadressiraamat"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Kuva fikseeritud valimisnumbrid"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Kuva teenuse valimise numbrid"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Ühendatud"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Peatatud"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Teadmata"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Peamine"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"baiti"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefoniteave"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operaatori ettevalmistamise teave"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Operaatori ettevalmistamise päästik"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC õiguse ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Uuenda"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Värskenda"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Teie Bluetoothi signaal on nõrk. Lülitage valjuhääldile."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Kõnekvaliteedi märguanne"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Katkestatud toega SIP-kontod"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Te ei saa sellelt profiililt sõnumeid saata"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Teie töökoja eeskirjad lubavad teil ainult tööprofiililt sõnumeid saata"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Tühista"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Lülitu tööprofiilile"</string>
</resources>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 58ba2f9..f912f4e 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -92,7 +92,7 @@
<string name="additional_cdma_call_settings" msgid="2178016561980611304">"CDMA deien ezarpen gehigarriak"</string>
<string name="sum_cdma_call_settings" msgid="3185825305136993636">"CDMA soilik motako deietarako ezarpen gehigarriak"</string>
<string name="labelNwService" msgid="6015891883487125120">"Sareko zerbitzuen ezarpenak"</string>
- <string name="labelCallerId" msgid="2090540744550903172">"Deitzailearen IDa"</string>
+ <string name="labelCallerId" msgid="2090540744550903172">"Deitzailearen identitatea"</string>
<string name="sum_loading_settings" msgid="434063780286688775">"Ezarpenak kargatzen…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Ezkutatu zenbakia irteerako deietan"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Erakutsi zenbakia irteerako deietan"</string>
@@ -143,7 +143,7 @@
<string name="stk_cc_ss_to_dial_error" msgid="5147693491690618704">"SS eskaera ohiko deira aldatu da"</string>
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"SS eskaera USSD eskaerara aldatu da"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"SS eskaera berrira aldatu da"</string>
- <string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"SS eskaera bideo-deira aldatu da"</string>
+ <string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"SS eskaera bideodeira aldatu da"</string>
<string name="fdn_check_failure" msgid="1833769746374185247">"Telefonoa aplikazioaren Markatze finkoko zenbakiak ezarpena aktibatuta daukazu. Ondorioz, deiekin lotutako eginbide batzuk ez dira funtzionatzen ari."</string>
<string name="radio_off_error" msgid="8321564164914232181">"Ezarpenak ikusi aurretik, piztu irratia."</string>
<string name="close_dialog" msgid="1074977476136119408">"Ados"</string>
@@ -167,7 +167,7 @@
<string name="vm_change_pin_progress_message" msgid="626015184502739044">"Itxaron, mesedez."</string>
<string name="vm_change_pin_error_too_short" msgid="1789139338449945483">"Laburregia da PIN berria."</string>
<string name="vm_change_pin_error_too_long" msgid="3634907034310018954">"Luzeegia da PIN berria."</string>
- <string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"Ez da batere segurua PIN berria. Pasahitza segurua izan dadin, ez du izan behar zenbaki-segidarik edo errepikatutako zenbakirik."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"Ez da batere segurua PIN berria. Pasahitz konplexuek ez dute izan behar zenbaki-segidarik edo errepikatutako zenbakirik."</string>
<string name="vm_change_pin_error_mismatch" msgid="5364847280026257331">"PIN zaharra ez dator bat."</string>
<string name="vm_change_pin_error_invalid" msgid="5230002671175580674">"Balio ez duten karaktereak ditu PIN berriak."</string>
<string name="vm_change_pin_error_system_error" msgid="9116483527909681791">"Ezin da aldatu PINa"</string>
@@ -310,7 +310,7 @@
<string name="sim_change_data_title" msgid="9142726786345906606">"Datuetarako SIMa aldatu nahi duzu?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Datu-konexiorako, <xliff:g id="NEW_SIM">%1$s</xliff:g> txartela erabili nahi duzu <xliff:g id="OLD_SIM">%2$s</xliff:g> txartelaren ordez?"</string>
<string name="wifi_calling_settings_title" msgid="5800018845662016507">"Wifi bidezko deiak"</string>
- <string name="video_calling_settings_title" msgid="342829454913266078">"Operadorearen bideo-deiak"</string>
+ <string name="video_calling_settings_title" msgid="342829454913266078">"Operadorearen bideodeiak"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"GSM/UMTS aukerak"</string>
<string name="cdma_options" msgid="3669592472226145665">"CDMA aukerak"</string>
<string name="throttle_data_usage" msgid="1944145350660420711">"Datu-erabilera"</string>
@@ -457,7 +457,7 @@
<string name="tty_mode_option_summary" msgid="4770510287236494371">"Ezarri TTY modua"</string>
<string name="auto_retry_mode_title" msgid="2985801935424422340">"Saiatu berriro automatikoki"</string>
<string name="auto_retry_mode_summary" msgid="2863919925349511402">"Gaitu automatikoki berriro saiatzeko modua"</string>
- <string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"Ezin da aldatu TTY modua bideo-deiak abian direnean"</string>
+ <string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"Ezin da aldatu TTY modua bideodeiak abian direnean"</string>
<string name="menu_add" msgid="5616487894975773141">"Gehitu kontaktua"</string>
<string name="menu_edit" msgid="3593856941552460706">"Editatu kontaktua"</string>
<string name="menu_delete" msgid="6326861853830546488">"Ezabatu kontaktua"</string>
@@ -534,7 +534,7 @@
<string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"Erantzungailuaren zenbakia ezezaguna da"</string>
<string name="notification_network_selection_title" msgid="255595526707809121">"Ez dago zerbitzurik"</string>
<string name="notification_network_selection_text" msgid="553288408722427659">"Hautatutako sarea (<xliff:g id="OPERATOR_NAME">%s</xliff:g>) ez dago erabilgarri"</string>
- <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Deitzeko, aktibatu sare mugikorra, desaktibatu hegaldi modua edo desaktibatu bateria-aurrezlea."</string>
+ <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Deitzeko, aktibatu sare mugikorra, desaktibatu hegaldi modua edo desaktibatu bateria-aurreztailea."</string>
<string name="incall_error_power_off" product="default" msgid="8131672264311208673">"Deia egiteko, desaktibatu hegaldi modua."</string>
<string name="incall_error_power_off_wfc" msgid="9125661184694727052">"Deia egiteko, desaktibatu hegaldi modua edo konektatu haririk gabeko sare batera."</string>
<string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"Telefonoa beroegi dago"</b>\n\n"Ezin da egin deia. Saiatu berriro telefonoa hozten denean.\n\nHala ere, larrialdi-deiak egin ditzakezu."</string>
@@ -585,7 +585,7 @@
<string name="onscreenManageCallsText" msgid="1162047856081836469">"Kudeatu deiak"</string>
<string name="onscreenManageConferenceText" msgid="4700574060601755137">"Kudeatu konferentzia"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"Audioa"</string>
- <string name="onscreenVideoCallText" msgid="1743992456126258698">"Bideo-deia"</string>
+ <string name="onscreenVideoCallText" msgid="1743992456126258698">"Bideodeia"</string>
<string name="importSimEntry" msgid="3892354284082689894">"Inportatu"</string>
<string name="importAllSimEntries" msgid="2628391505643564007">"Inportatu guztiak"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"SIM txarteleko kontaktuak inportatzen"</string>
@@ -596,7 +596,7 @@
<string name="hac_mode_summary" msgid="7774989500136009881">"Aktibatu audifonoen bateragarritasuna"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Deietan testua bidaltzeko eginbidea"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"Baimendu mezuak bidali eta jasotzea ahots-deien barruan"</string>
- <string name="rtt_mode_more_information" msgid="587500128658756318">"Deietan testua bidaltzeko eginbideak deitzaile gorrei, entzumen-arazoak dituztenei, hitz egiteko ezintasunen bat dutenei edota ahotsaz gain beste makuluren bat behar dutenei laguntzen die.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Lortu informazio gehiago</a>\n <br><br> - Deietan testua bidaltzeko eginbidearekin egindako deiak mezu-transkripzio gisa gordetzen dira.\n <br> - Deietan testua bidaltzeko eginbidea ez da bateragarria bideo-deiekin."</string>
+ <string name="rtt_mode_more_information" msgid="587500128658756318">"Deietan testua bidaltzeko eginbideak deitzaile gorrei, entzumen-arazoak dituztenei, hitz egiteko ezintasunen bat dutenei edota ahotsaz gain beste makuluren bat behar dutenei laguntzen die.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Lortu informazio gehiago</a>\n <br><br> - Deietan testua bidaltzeko eginbidearekin egindako deiak mezu-transkripzio gisa gordetzen dira.\n <br> - Deietan testua bidaltzeko eginbidea ez da bateragarria bideodeiekin."</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"Oharra: Deietan testua bidaltzeko eginbidea ez dago erabilgarri ibiltaritzan"</string>
<string-array name="tty_mode_entries">
<item msgid="3238070884803849303">"TTY desaktibatuta"</item>
@@ -615,7 +615,7 @@
<string name="ota_title_activate" msgid="4049645324841263423">"Aktibatu telefonoa"</string>
<string name="ota_touch_activate" msgid="838764494319694754">"Telefono-zerbitzua aktibatzeko, dei berezi bat egin behar da.\n\n\"Aktibatu\" sakatu ondoren, telefonoa aktibatzeko, entzun ematen zaizkizun argibideak."</string>
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Aktibatzen…"</string>
- <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Telefonoa datu-konexioaren zerbitzua aktibatzen ari da.\n\nEragiketa 5 minutura arte luza daiteke."</string>
+ <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Telefonoa mugikorretarako datu-zerbitzua aktibatzen ari da.\n\nEragiketa gehienez 5 minutu luza daiteke."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Aktibazioa saltatu nahi duzu?"</string>
<string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Aktibazioa saltatzen baduzu, ezingo duzu deirik egin, ez eta datu-konexioaren sareetara konektatu ere, baina Wi-Fi sareetara konektatu ahal izango duzu. Telefonoa aktibatzen duzun arte, pizten duzun bakoitzean eskatuko zaizu aktibatzeko."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Saltatu"</string>
@@ -664,8 +664,8 @@
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Aldatu PINa"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"Tonua eta dardara"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"SIM txartel integratuak"</string>
- <string name="enable_video_calling_title" msgid="7246600931634161830">"Aktibatu bideo-deiak"</string>
- <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Bideo-deiak aktibatzeko, 4G LTE modu hobetua aktibatu behar duzu \"Sarearen ezarpenak\" atalean."</string>
+ <string name="enable_video_calling_title" msgid="7246600931634161830">"Aktibatu bideodeiak"</string>
+ <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Bideodeiak aktibatzeko, 4G LTE modu hobetua aktibatu behar duzu \"Sarearen ezarpenak\" atalean."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"Sareko ezarpenak"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Itxi"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"Larrialdi-deiak"</string>
@@ -680,7 +680,7 @@
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Ezin da konektatu. Erabili balio duen SIM txartel bat."</string>
<string name="callFailed_wifi_lost" msgid="1788036730589163141">"Galdu egin da wifi-konexioa. Amaitu da deia."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"Ezin da egin deia, bateria gutxi gelditzen delako."</string>
- <string name="callFailed_low_battery" msgid="4056828320214416182">"Bideo-deia amaitu egin da bateria gutxi gelditzen delako."</string>
+ <string name="callFailed_low_battery" msgid="4056828320214416182">"Bideodeia amaitu egin da bateria gutxi gelditzen delako."</string>
<string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Ez daude erabilgarri wifi bidezko larrialdi-deiak kokapen honetan."</string>
<string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Ez daude erabilgarri wifi bidezko deiak kokapen honetan."</string>
<string name="change_pin_title" msgid="3564254326626797321">"Aldatu erantzungailuaren PINa"</string>
@@ -826,7 +826,7 @@
<string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Gaitu datu-konexioa"</string>
<string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Desgaitu datu-konexioa"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"VoLTE hornituta"</string>
- <string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Bideo-deiak aktibatuta"</string>
+ <string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Bideodeiak aktibatuta"</string>
<string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Wifi bidezko deiak aktibatuta"</string>
<string name="eab_provisioned_switch_string" msgid="4449676720736033035">"EAB/Presence hornitu da"</string>
<string name="cbrs_data_switch_string" msgid="6060356430838077653">"CBRS datuak"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Ezarpen hau aldatzeko, gailua berrabiarazi egin behar duzu."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Berrabiarazi"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Utzi"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Ezarri eSIM aldagarria lehenetsi gisa"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Sare mugikor bidezko irratiaren indarra"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulatu gailua ez dabilela (arazketa-konpilazioa soilik)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Ikusi SIMeko kontaktuak"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Ikusi markatze finkoko zenbakiak"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Ikusi zerbitzuaren markatze-zenbakiak"</string>
@@ -845,7 +847,7 @@
<string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"Erregistratu gabe"</string>
<string name="radio_info_ims_feature_status_available" msgid="6493200914756969292">"Libre"</string>
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"Ez dago erabilgarri"</string>
- <string name="radio_info_ims_reg_status" msgid="25582845222446390">"IMS erregistroa: <xliff:g id="STATUS">%1$s</xliff:g>\nLTE bidezko ahots-deiak: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nWifi bidezko ahots-deiak: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nBideo-deiak: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT interfazea: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
+ <string name="radio_info_ims_reg_status" msgid="25582845222446390">"IMS erregistroa: <xliff:g id="STATUS">%1$s</xliff:g>\nLTE bidezko ahots-deiak: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nWifi bidezko ahots-deiak: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nBideodeiak: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT interfazea: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"Erabilgarri"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"Ez erabilgarri"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"Larrialdi-deiak soilik"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Konektatuta"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Behin-behinean itxitakoak"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Ezezaguna"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Nagusia"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"byte"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefonoaren informazioa"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operadorearen hornikuntza-informazioa"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Abiarazi operadorearen hornikuntza"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Entitlement-eko IDa:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Eguneratu"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Freskatu"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth seinalea ahula da. Erabili telefonoko bozgorailua."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Deien kalitateari buruzko jakinarazpena"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"SIP-eko kontu zaharkituak"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Ezin duzu bidali mezurik profil honetatik"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Mezuak laneko profiletik soilik bidaltzeko baimena ematen dizute laneko gidalerroek"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Utzi"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Aldatu laneko profilera"</string>
</resources>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index f5e9968..707a214 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -191,7 +191,7 @@
<string name="preferred_network_mode_dialogtitle" msgid="2781447433514459696">"نوع شبکه ترجیحی"</string>
<string name="forbidden_network" msgid="5081729819561333023">"(ممنوع است)"</string>
<string name="choose_network_title" msgid="5335832663422653082">"انتخاب شبکه"</string>
- <string name="network_disconnected" msgid="8844141106841160825">"قطع اتصال"</string>
+ <string name="network_disconnected" msgid="8844141106841160825">"متصل نیست"</string>
<string name="network_connected" msgid="2760235679963580224">"متصل"</string>
<string name="network_connecting" msgid="160901383582774987">"درحال اتصال…"</string>
<string name="network_could_not_connect" msgid="6547460848093727998">"متصل نشد"</string>
@@ -451,7 +451,7 @@
<string name="sum_fdn" msgid="6152246141642323582">"مدیریت شمارههای شمارهگیری ثابت"</string>
<string name="sum_fdn_change_pin" msgid="3510994280557335727">"تغییر پین برای دسترسی FDN"</string>
<string name="sum_fdn_manage_list" msgid="3311397063233992907">"مدیریت فهرست شماره تلفن"</string>
- <string name="voice_privacy" msgid="7346935172372181951">"حریمخصوصی صوتی"</string>
+ <string name="voice_privacy" msgid="7346935172372181951">"حریم خصوصی صوتی"</string>
<string name="voice_privacy_summary" msgid="3556460926168473346">"فعال کردن حالت رازداری پیشرفته"</string>
<string name="tty_mode_option_title" msgid="3843817710032641703">"حالت TTY"</string>
<string name="tty_mode_option_summary" msgid="4770510287236494371">"تنظیم حالت TTY"</string>
@@ -592,9 +592,9 @@
<string name="importToFDNfromContacts" msgid="5068664870738407341">"وارد کردن از مخاطبین"</string>
<string name="singleContactImportedMsg" msgid="3619804066300998934">"مخاطب واردشده"</string>
<string name="failedToImportSingleContactMsg" msgid="228095510489830266">"مخاطب وارد نشد"</string>
- <string name="hac_mode_title" msgid="4127986689621125468">"دستگاههای کمکشنوایی"</string>
+ <string name="hac_mode_title" msgid="4127986689621125468">"سمعک"</string>
<string name="hac_mode_summary" msgid="7774989500136009881">"روشن کردن سازگاری دستگاه کمکشنوایی"</string>
- <string name="rtt_mode_title" msgid="3075948111362818043">"تماس نوشتار همزمان (RTT)"</string>
+ <string name="rtt_mode_title" msgid="3075948111362818043">"تماس با نوشتار همزمان (RTT)"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"پیامرسانی در تماس صوتی مجاز است"</string>
<string name="rtt_mode_more_information" msgid="587500128658756318">"«نوشتار همزمان» به تماس گیرندگان ناشنوا، دارای مشکل شنوایی، دارای ناتوانی گفتاری یا افرادی که به چیزی بیش از صدا نیاز دارند کمک میکند.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>بیشتر بدانید</a>\n <br><br> تماسهای «نوشتار همزمان» بهصورت ترانویسی پیام ذخیره میشود\n <br> «نوشتار همزمان» برای تماسهای ویدیویی دردسترس نیست"</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"نکته: «نوشتار همزمان» در هنگام فراگردی دردسترس نیست"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"برای تغییر این تنظیم، باید دستگاه را بازراهاندازی کنید."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"بازراهاندازی"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"لغو"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"تنظیم سیمکارت داخلی جداشدنی بهعنوان پیشفرض"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"توان رادیوی تلفن همراه"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"شبیهسازی از کار افتادن (فقط ساخت اشکالزدایی)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"مشاهده دفترچه نشانی سیمکارت"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"مشاهده شمارههای شمارهگیری ثابت"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"مشاهده شمارههای شمارهگیری سرویس"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"متصل"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"تعلیقشده"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"نامشخص"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"اصلی"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"بایت"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -898,7 +901,7 @@
<string name="ping_test_label" msgid="448617502935719694">"اجرای آزمایش پینگ"</string>
<string name="radio_info_smsc_label" msgid="3749927072726033763">"SMSC:"</string>
<string name="radio_info_smsc_update_label" msgid="5141996256097115753">"بهروزرسانی"</string>
- <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"بازخوانی"</string>
+ <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"بازآوری"</string>
<string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"تغییر وضعیت علامت DNS"</string>
<string name="oem_radio_info_label" msgid="2914167475119997456">"تنظیمات/اطلاعات خاص OEM"</string>
<string name="radio_info_endc_available" msgid="2983767110681230019">"EN-DC دردسترس است (NSA):"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"اطلاعات تلفن"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"اطلاعات ارائه شرکت مخابراتی"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"شروع ارائه شرکت مخابراتی"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"شناسه برخورداری از WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"بهروزرسانی"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"بازآوری"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"سیگنال بلوتوث شما ضعیف است. از بلندگوی تلفن استفاده کنید."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"اعلان کیفیت تماس"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"حسابهای SIP منسوخشده"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"نمیتوانید ازطریق این نمایه پیام ارسال کنید"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"طبق خطمشی کاریتان فقط میتوانید ازطریق نمایه کاری پیام ارسال کنید"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"لغو کردن"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"رفتن به نمایه کاری"</string>
</resources>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index d548e60..d20b004 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Laite on käynnistettävä uudelleen asetuksen muuttamiseksi."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Käynnistä uudelleen"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Peru"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Aseta poistettava eSIM oletukseksi"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobiiliradion voimakkuus"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Epäkunnossa-simulaatio (vain virheenkorjauksen koontiversio)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Näytä SIM-kortin osoitekirja"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Näytä sallitut numerot"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Näytä sallitut palvelunumerot"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Yhdistetty"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Jäädytetty"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Tuntematon"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Ensisijainen"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pakettia"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"tavua"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -892,8 +895,8 @@
<string name="radio_info_override_network_type_label" msgid="4176280017221092005">"Ohita verkon tyyppi:"</string>
<string name="phone_index_label" msgid="6222406512768964268">"Valitse puhelimen hakemisto"</string>
<string name="radio_info_set_perferred_label" msgid="7408131389363136210">"Aseta ensisijainen verkon tyyppi:"</string>
- <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Ping-kutsu isäntänimelle (www.google.com), IPv4:"</string>
- <string name="radio_info_ping_hostname_v6" msgid="2748637889486554603">"Ping-kutsu isäntänimelle (www.google.com), IPv6:"</string>
+ <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Ping isäntänimelle (www.google.com), IPv4:"</string>
+ <string name="radio_info_ping_hostname_v6" msgid="2748637889486554603">"Ping isäntänimelle (www.google.com), IPv6:"</string>
<string name="radio_info_http_client_test" msgid="1329583721088428238">"HTTP-asiakastesti:"</string>
<string name="ping_test_label" msgid="448617502935719694">"Suorita ping-testi"</string>
<string name="radio_info_smsc_label" msgid="3749927072726033763">"SMSC:"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Puhelimen tiedot"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operaattorin hallintatiedot"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Ota operaattorin hallinta käyttöön"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC-oikeuden tunnus:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Päivitä"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Päivitä"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth-signaali on heikko. Kokeile vaihtaa kaiutinpuhelimeen."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Puhelun laatua koskeva ilmoitus"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Käytöstä poistetut SIP-tilit"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Viestiä ei voi lähettää tästä profiilista"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Työkäytäntö sallii sinun lähettää viestejä vain työprofiilista"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Peru"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Vaihda työprofiiliin"</string>
</resources>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index fa3e257..21eab1f 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Vous devez redémarrer votre appareil pour modifier ce paramètre."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Redémarrer"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Annuler"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Définir la carte eSIM amovible comme carte SIM par défaut"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Alimentation de radio cellulaire"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulation de l\'appareil hors service (version de débogage uniquement)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Afficher le carnet d\'adresses de la carte SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Afficher les numéros d\'appel fixes"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Afficher les numéros de service"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Connecté"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspendu"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Inconnu"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"paquets"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"octets"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informations sur le téléphone"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Données d\'approvisionnement du fournisseur de services"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Déclencher l\'approvisionnement du fournisseur de services"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Identifiant de droit WFC :"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Mettre à jour"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Actualiser"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Votre signal Bluetooth est faible. Essayez de passer au haut-parleur mains libres."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notification de qualité d\'appel"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Comptes SIP obsolètes"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Impossible d\'envoyer un message à partir de ce profil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Votre politique de l\'entreprise vous autorise à envoyer des messages uniquement à partir de votre profil professionnel"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Annuler"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Passer au profil professionnel"</string>
</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 084f5ad..57f85ca 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Vous devez redémarrer l\'appareil pour modifier ce paramètre."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Redémarrer"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Annuler"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Définir l\'eSIM amovible comme SIM par défaut"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Alimentation radio mobile"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simuler une panne (version de débogage uniquement)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Afficher le carnet d\'adresses de la carte SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Afficher les numéros autorisés"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Afficher les numéros de service"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Connecté"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspendu"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Inconnu"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"paquets"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"octets"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -867,7 +870,7 @@
<string name="radioInfo_lac" msgid="3892986460272607013">"LAC"</string>
<string name="radioInfo_cid" msgid="1423185536264406705">"CID"</string>
<string name="radio_info_subid" msgid="6839966868621703203">"Sous-identifiant actuel :"</string>
- <string name="radio_info_dds" msgid="1122593144425697126">"Sous-identifiant de la carte SIM par défaut pour les données :"</string>
+ <string name="radio_info_dds" msgid="1122593144425697126">"Sous-identifiant SIM par défaut pour les données :"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"Bande passante de téléchargement (kbit/s) :"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"Bande passante d\'importation (kbit/s) :"</string>
<string name="radio_info_phy_chan_config" msgid="1277949603275436081">"Configuration de la chaîne physique LTE :"</string>
@@ -915,13 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informations sur le téléphone"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informations de gestion des comptes opérateur"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Déclencher la gestion des comptes opérateur"</string>
- <!-- no translation found for provisioning_info_wfc_entitlement_id (8845188780811890910) -->
- <skip />
- <!-- no translation found for update_provisioning_info_wfc_entitlement_id (7044171908781134221) -->
- <skip />
- <!-- no translation found for refresh_provisioning_info_wfc_entitlement_id (738894335351353407) -->
- <skip />
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Votre signal Bluetooth est faible. Essayez d\'utiliser le haut-parleur."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notification concernant la qualité de l\'appel"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Comptes SIP obsolètes"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Impossible d\'envoyer un message depuis ce profil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Votre règle professionnelle ne vous permet d\'envoyer des messages que depuis le profil professionnel"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Annuler"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Passer au profil professionnel"</string>
</resources>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 4981ebc..5d98c38 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -665,7 +665,7 @@
<string name="preference_category_ringtone" msgid="8787281191375434976">"Ton de chamada e vibración"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"Tarxetas SIM integradas"</string>
<string name="enable_video_calling_title" msgid="7246600931634161830">"Activar videochamadas"</string>
- <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Para activar as videochamadas, necesitas activar o Modo LTE 4G mellorado na configuración do sistema."</string>
+ <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Para activar as videochamadas, necesitas activar o modo LTE 4G mellorado na configuración do sistema."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"Configuración de rede"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Pechar"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"Chamadas de emerxencia"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Debes reiniciar o dispositivo para cambiar esta opción"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Reiniciar"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancelar"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Establecer eSIM extraíble como predeterminada"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Alimentación da radio móbil"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simular Fóra de servizo (só compilación de depuración)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Ver axenda de enderezos da SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Ver números de marcación fixa"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Ver números de marcación de servizo"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Conectada"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspendido"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Descoñecido"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Información do teléfono"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Información de aprovisionamento do operador"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aprovisionamento do operador do activador"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Identificador do dereito a usar chamadas por wifi:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Actualizar"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Actualizar"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"O teu sinal de Bluetooth é feble. Proba a cambiar ao altofalante."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notificación sobre a calidade da chamada"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Contas SIP obsoletas"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Non se poden enviar mensaxes desde este perfil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"A política do teu traballo só che permite enviar mensaxes desde o perfil de traballo"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancelar"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Cambiar ao perfil de traballo"</string>
</resources>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 1ad1a28..f5e57bb 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"આ સેટિંગમાં ફેરફાર કરવા માટે તમારા ડિવાઇસને ફરી શરૂ કરો."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ફરી શરૂ કરો"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"રદ કરો"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"કાઢી નાખી શકાય એવા ઇ-સિમ કાર્ડને ડિફૉલ્ટ તરીકે સેટ કરો"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"મોબાઇલ રેડિયો પાવર"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\'સેવા ઉપલબ્ધ નથી\' મોડ સિમ્યુલેટ કરો (માત્ર ડિબગ બિલ્ડ માટે)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"સિમમાં સરનામા પુસ્તિકા જુઓ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ફિક્સ્ડ ડાયલિંગ નંબર જુઓ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"સર્વિસ ડાયલિંગ નંબર જુઓ"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"કનેક્ટેડ"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"સસ્પેન્ડ કરી"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"અજાણ"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"પ્રાથમિક"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"બાઇટ"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ફોનની માહિતી"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"કૅરિઅરની જોગવાઈ વિશે માહિતી"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"કૅરિઅરની જોગવાઈ ટ્રિગર કરો"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC અધિકાર ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"અપડેટ કરો"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"રિફ્રેશ કરો"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"તમારા બ્લૂટૂથનું સિગ્નલ નબળું છે. સ્પીકરફોન પર સ્વિચ કરવાનો પ્રયાસ કરો."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"કૉલની ક્વૉલિટી માટે નોટિફિકેશન"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"ટાળવામાં આવેલા SIP એકાઉન્ટ"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"આ પ્રોફાઇલ પરથી મેસેજ મોકલી શકતા નથી"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"તમારી ઑફિસની પૉલિસી તમને માત્ર ઑફિસની પ્રોફાઇલ પરથી જ મેસેજ મોકલવાની મંજૂરી આપે છે"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"રદ કરો"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"ઑફિસની પ્રોફાઇલ પર સ્વિચ કરો"</string>
</resources>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 723d94d..c48332a 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"इस सेटिंग को बदलने के लिए आपको अपना डिवाइस रीस्टार्ट करना होगा."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"रीस्टार्ट करें"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"रद्द करें"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"हटाए जा सकने वाले ई-सिम को डिफ़ॉल्ट के तौर पर सेट करें"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"मोबाइल रेडियो पावर"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"सिम्युलेट किया गया डिवाइस काम नहीं कर रहा है (सिर्फ़ डीबग के लिए बिल्ड)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"सिम में संपर्कों के पते की सूची देखें"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"फ़िक्स्ड डायलिंग नंबर देखें"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"सेवा के डायलिंग नंबर देखें"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"कनेक्ट किया गया"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"थोड़ी देर के लिए रोक लगी है"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"अज्ञात"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"प्राइमरी"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"बाइट"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"फ़ोन की जानकारी"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी के प्रावधान की जानकारी"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"मोबाइल और इंटरनेट सेवा देने वाली कंपनी के प्रावधान चालू करें"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC सदस्यता आईडी:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"अपडेट करें"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"रीफ़्रेश करें"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"आपका ब्लूटूथ सिग्नल कमज़ोर है. स्पीकरफ़ोन की सुविधा का इस्तेमाल करें."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"कॉल की क्वालिटी की सूचना"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"ऐसे SIP खाते जिनका समर्थन रोक दिया गया है"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"इस प्रोफ़ाइल से मैसेज नहीं भेजा जा सकता"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"ऑफ़िस की नीति के तहत, वर्क प्रोफ़ाइल से ही मैसेज भेजा जा सकता है"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"रद्द करें"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"वर्क प्रोफ़ाइल पर स्विच करें"</string>
</resources>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 909957d..3055b25 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Ponovo pokrenite uređaj da biste promijenili tu postavku."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Ponovno pokretanje"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Odustani"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Postavljanje uklonjivog eSIM-a kao zadanog"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Snaga mobilnog radija"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulacija stanja \"izvan upotrebe\" (samo međuverzija programa za otklanjanje pogrešaka)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Prikaži imenik SIM-a"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Prikaži brojeve za fiksno biranje"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Prikaži brojeve za servisno biranje"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Povezano"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Obustavljeno"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Nepoznato"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primarno"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bajtovi"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacije o telefonu"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informacije o uslugama mobilnog operatera"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Pokretanje usluga mobilnog operatera"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID prava na WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Ažuriranje"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Osvježavanje"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Signal Bluetootha je slab. Pokušajte se prebaciti na zvučnik."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Obavijest o kvaliteti poziva"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Obustavljeni SIP računi"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Slanje poruke s ovog profila nije moguće"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Vaša poslovna pravila dopuštaju vam da šaljete poruke samo s poslovnog profila"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Odustani"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Prelazak na poslovni profil"</string>
</resources>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 47091eb..5d6d22d 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"A beállítás módosításához újra kell indítania az eszközt."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Újraindítás"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Mégse"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Cserélhető eSIM beállítása alapértelmezettként"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobil rádióadó teljesítménye"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Szolgáltatáskiesés szimulációja (csak hibaelhárító build)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM-kártya telefonkönyvének megtekintése"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Fix hívószámok megtekintése"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Szolgáltatásszámok megtekintése"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Csatlakoztatva"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Felfüggesztve"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Ismeretlen"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Elsődleges"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"csomag"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bájt"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefon adatai"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Információ a szolgáltatói ellátásról"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Szolgáltatói ellátás aktiválása"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC-jogosultság azonosítója:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Módosítás"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Frissítés"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Gyenge a Bluetooth-jel. Próbáljon kihangosítóra váltani."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Értesítés a hívás minőségéről"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Elavult SIP-fiókok"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Nem lehet üzenetet küldeni ebből a profilból"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"A munkahelyi házirend csak az üzenetek munkaprofilból való küldését engedélyezi"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Mégse"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Váltás munkaprofilra"</string>
</resources>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 0318c9d..1038d8d 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="phoneAppLabel" product="tablet" msgid="1916019789885839910">"Բջջային տվյալներ"</string>
<string name="phoneAppLabel" product="default" msgid="130465039375347763">"Հեռախոսի ծառայություններ"</string>
- <string name="emergencyDialerIconLabel" msgid="8668005772339436680">"Արտակարգ իրավիճակների համարհավաքիչ"</string>
+ <string name="emergencyDialerIconLabel" msgid="8668005772339436680">"Արտակարգ իրավիճակների համարահավաքիչ"</string>
<string name="phoneIconLabel" msgid="3015941229249651419">"Հեռախոս"</string>
<string name="fdnListLabel" msgid="4119121875004244097">"FDN ցուցակ"</string>
<string name="unknown" msgid="8279698889921830815">"Անհայտ"</string>
@@ -284,7 +284,7 @@
<string name="roaming" msgid="1576180772877858949">"Ռոումինգ"</string>
<string name="roaming_enable" msgid="6853685214521494819">"Միանալ տվյալների փոխանցման ծառայություններին ռոումինգում"</string>
<string name="roaming_disable" msgid="8856224638624592681">"Միանալ տվյալների փոխանցման ծառայություններին ռոումինգում"</string>
- <string name="roaming_reenable_message" msgid="1951802463885727915">"Ռոումինգում բջջային ինտերնետն անջատված է: Հպեք՝ միացնելու համար:"</string>
+ <string name="roaming_reenable_message" msgid="1951802463885727915">"Ռոումինգում բջջային ինտերնետն անջատված է: Հպեք միացնելու համար:"</string>
<string name="roaming_enabled_message" msgid="9022249120750897">"Ռոումինգի համար կարող է գումար գանձվել: Հպեք՝ փոփոխելու համար:"</string>
<string name="roaming_notification_title" msgid="3590348480688047320">"Բջջային ինտերնետը կորավ"</string>
<string name="roaming_on_notification_title" msgid="7451473196411559173">"Ինտերնետ ռոումինգը միացված է"</string>
@@ -575,7 +575,7 @@
<string name="fire_type_description" msgid="6565200468934914930">"Հրշեջ ծառայություն"</string>
<string name="description_concat_format" msgid="2014471565101724088">"%1$s, %2$s"</string>
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Օգտագործեք ստեղնաշարը՝ համարհավաքման համար"</string>
- <string name="onscreenHoldText" msgid="4025348842151665191">"Պահել"</string>
+ <string name="onscreenHoldText" msgid="4025348842151665191">"Սպասման մեջ դնել"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"Ավարտել"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"Թվաշար"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Խլացնել"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Վերագործարկեք սարքը՝ այս կարգավորումը փոխելու համար:"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Վերագործարկել"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Չեղարկել"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Սահմանել հեռացվելի eSIM քարտը որպես կանխադրված"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Բջջային ռադիոազդանշանի հզորությունը"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Սպասարկման գոտուց դուրս գտնվելու սիմուլյացիա (միայն վրիպազերծման կառուցում)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Դիտել SIM քարտի հասցեագիրքը"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Տեսնել ամրակցված հեռախոսահամարները"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Տեսնել ծառայությունների հեռախոսահամարները"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Միացված է"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Անջատված է"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Անհայտ"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Հիմնական"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"բայթ"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Հեռախոսի տեղեկություններ"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Օպերատորի նախապատրաստման տվյալներ"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Գործարկել օպերատորի նախապատրաստումը"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC թույլտվության ID՝"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Թարմացնել"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Թարմացնել"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Ձեր Bluetooth-ի ազդանշանը թույլ է։ Փորձեք միացնել բարձրախոսը։"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Զանգի որակի մասին ծանուցում"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Հնացած SIP հաշիվներ"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Հնարավոր չէ հաղորդագրություն ուղարկել այս պրոֆիլից"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Ձեր աշխատանքային կանոնների համաձայն՝ դուք կարող եք հաղորդագրություն ուղարկել միայն աշխատանքային պրոֆիլից"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Չեղարկել"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Անցնել աշխատանքային պրոֆիլ"</string>
</resources>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index a5da578..8e9653f 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -48,7 +48,7 @@
<string name="no_vm_number_msg" msgid="5165161462411372504">"Tidak ada nomor kotak pesan tersimpan pada kartu SIM."</string>
<string name="add_vm_number_str" msgid="7368168964435881637">"Tambahkan nomor"</string>
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Setelan Pesan Suara hanya dapat diubah oleh Pengguna Utama."</string>
- <string name="puk_unlocked" msgid="4627340655215746511">"Kartu SIM Anda tidak lagi dicekal. Ponsel Anda sedang dibuka kuncinya..."</string>
+ <string name="puk_unlocked" msgid="4627340655215746511">"Kartu SIM Anda tidak lagi diblokir. Ponsel Anda sedang dibuka kuncinya..."</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN pembuka kunci jaringan SIM"</string>
<string name="label_phoneid" msgid="8775611434123577808">"SIM dikunci untuk operator"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Buka kunci"</string>
@@ -674,7 +674,7 @@
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"Aksesibilitas"</string>
<string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Panggilan Wi-Fi dari"</string>
<string name="status_hint_label_wifi_call" msgid="942993035689809853">"Panggilan Wi-Fi"</string>
- <string name="message_decode_error" msgid="1061856591500290887">"Terjadi kesalahan saat mendekode pesan."</string>
+ <string name="message_decode_error" msgid="1061856591500290887">"Terjadi error saat mendekode pesan."</string>
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"Kartu SIM telah mengaktifkan layanan dan memperbarui kemampuan roaming ponsel."</string>
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Ada terlalu banyak panggilan aktif. Akhiri atau gabungkan panggilan yang ada sebelum melakukan panggilan baru."</string>
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Tidak dapat terhubung, masukkan kartu SIM yang valid."</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Anda perlu memulai ulang perangkat untuk mengubah setelan."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Mulai ulang"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Batal"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Tetapkan eSIM yang Dapat Dilepas sebagai Default"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Daya Radio Seluler"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulasi Tidak dapat Digunakan (Khusus Build Debug)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Lihat Buku Alamat SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Lihat Panggilan Terbatas"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Lihat Nomor Panggilan Layanan"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Terhubung"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Ditangguhkan"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Tidak diketahui"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primer"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"byte"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Info telepon"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Info Provisioning Operator"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Memicu Provisioning Operator"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID Hak WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Perbarui"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Muat ulang"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Sinyal bluetooth Anda lemah. Coba beralih ke speaker ponsel."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notifikasi Kualitas Panggilan"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Akun SIP yang tidak digunakan lagi"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Tidak dapat mengirim pesan dari profil ini"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Kebijakan kantor mengizinkan Anda mengirim pesan hanya dari profil kerja"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Batal"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Beralih ke profil kerja"</string>
</resources>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 45726af..437585a 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Endurræsa þarf tækið til að breyta þessari stillingu."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Endurræsa"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Hætta við"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Stilla laust eSIM sem sjálfgefið"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Loftnetsstyrkur farsíma"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Líkja eftir „Utan þjónustusvæðis“ (aðeins villuleitarsmíði)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Skoða símaskrá SIM-korts"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Skoða læst númeraval"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Skoða þjónustunúmer"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Tengt"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Lokað tímabundið"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Óþekkt"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Aðal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pk."</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bæti"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Upplýsingar um síma"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Úthlutunarupplýsingar símafyrirtækis"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Kveikja á úthlutun símafyrirtækis"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Auðkenni WFC-réttinda:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Uppfæra"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Endurnýja"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth-tengingin er léleg. Prófaðu að nota hátalara í staðinn."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Tilkynning um símtalsgæði"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Úreldir SIP-reikningar"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Ekki er hægt að senda skilaboð úr þessu sniði"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Vinnureglur gera þér aðeins kleift að senda skilaboð úr vinnusniði"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Hætta við"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Skipta yfir í vinnusnið"</string>
</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 6a79566..8189edf 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="phoneAppLabel" product="tablet" msgid="1916019789885839910">"Dati cellulare"</string>
- <string name="phoneAppLabel" product="default" msgid="130465039375347763">"Phone Services"</string>
+ <string name="phoneAppLabel" product="default" msgid="130465039375347763">"Servizi telefonici"</string>
<string name="emergencyDialerIconLabel" msgid="8668005772339436680">"Chiamata di emergenza"</string>
<string name="phoneIconLabel" msgid="3015941229249651419">"Telefono"</string>
<string name="fdnListLabel" msgid="4119121875004244097">"Elenco numeri consentiti"</string>
@@ -572,7 +572,7 @@
<string name="pin_puk_system_user_only" msgid="1045147220686867922">"Solo il proprietario del dispositivo può inserire i codici PIN/PUK."</string>
<string name="police_type_description" msgid="2819533883972081757">"Polizia"</string>
<string name="ambulance_type_description" msgid="6798237503553180461">"Ambulanza"</string>
- <string name="fire_type_description" msgid="6565200468934914930">"Vigili del fuoco"</string>
+ <string name="fire_type_description" msgid="6565200468934914930">"Pompieri"</string>
<string name="description_concat_format" msgid="2014471565101724088">"%1$s, %2$s"</string>
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"Usa tastiera"</string>
<string name="onscreenHoldText" msgid="4025348842151665191">"In attesa"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Riavvia il dispositivo per modificare questa impostazione."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Riavvia"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Annulla"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Imposta la eSIM rimovibile come predefinita"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Potenza del segnale radio mobile"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulazione non disponibile (solo build di debug)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Visualizza rubrica SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Visualizza numeri consentiti"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Visualizza numeri dell\'elenco dei numeri di servizio"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Connesso"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Sospeso"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Sconosciuto"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principale"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkt"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"byte"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Info telefono"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informazioni sul provisioning operatore"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Attiva provisioning operatore"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID diritto per le chiamate Wi-Fi:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Aggiorna"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Aggiorna"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Il segnale del Bluetooth è debole. Prova a passare al vivavoce."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notifica sulla qualità della chiamata"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Account SIP deprecati"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Impossibile inviare messaggi da questo profilo"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Le norme di lavoro ti consentono di inviare messaggi solo dal profilo di lavoro"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Annulla"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Passa a profilo di lavoro"</string>
</resources>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index 3626c66..d70bf85 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"עליך להפעיל מחדש את המכשיר כדי לשנות הגדרה זו."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"הפעלה מחדש"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"ביטול"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"הגדרת eSIM נשלף כברירת המחדל"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"הפעלה של רדיו סלולרי"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"סימולציה של המצב \'לא בשירות\' (גרסת build לניפוי באגים בלבד)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"הצגת פנקס כתובות של SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"הצגת מספרי חיוג קבועים"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"מספרי חיוג לשירות"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"מקושר"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"בהשעיה"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"לא ידוע"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ראשי"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"בייטים"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"פרטי טלפון"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"פרטי ניהול תצורה של ספק סלולרי"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"הפעלת ניהול תצורה של ספק סלולרי"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"מזהה הרשאת WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"עדכון"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"רענון"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"הקליטה של ה-Bluetooth חלשה. כדאי לעבור לדיבורית."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"התראה על איכות השיחה"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"חשבונות SIP שהוצאו משימוש"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"אי אפשר לשלוח הודעות מהפרופיל הזה"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"המדיניות של מקום העבודה מאפשרת לך לשלוח הודעות רק מפרופיל העבודה"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"ביטול"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"החלפה לפרופיל עבודה"</string>
</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index b55c175..96d564a 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -662,7 +662,7 @@
<string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"ビジュアル留守番電話"</string>
<string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"PIN の設定"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"PIN の変更"</string>
- <string name="preference_category_ringtone" msgid="8787281191375434976">"着信音とバイブレーション"</string>
+ <string name="preference_category_ringtone" msgid="8787281191375434976">"音とバイブレーション"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"内蔵のSIMカード"</string>
<string name="enable_video_calling_title" msgid="7246600931634161830">"ビデオハングアウトを有効にする"</string>
<string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"ビデオハングアウトをONにするには、ネットワーク設定で4G LTE拡張モードを有効にする必要があります。"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"この設定を変更するには、デバイスの再起動が必要です。"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"再起動"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"キャンセル"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"リムーバブル eSIM をデフォルトに設定"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"モバイル無線電力"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"圏外状態のシミュレート(デバッグビルドのみ)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM のアドレス帳を表示"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"発信番号制限を表示"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"サービス電話番号を表示"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"接続済み"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"停止中"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"不明"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"メイン"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"バイト"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"スマートフォン情報"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"携帯通信会社のプロビジョニング情報"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"携帯通信会社のプロビジョニングをトリガー"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC 利用資格 ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"アップデート"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"更新"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth の信号強度が十分ではありません。スピーカーフォンに切り替えてみてください。"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"通話品質に関するお知らせ"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"サポートが終了した SIP アカウント"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"このプロファイルからはメッセージを送信できません"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"仕事用ポリシーでは、メッセージの送信を仕事用プロファイルからのみに制限できます"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"キャンセル"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"仕事用プロファイルに切り替える"</string>
</resources>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index 94302f9..c6bcd58 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"ამ პარამეტრის შესაცვლელად საჭიროა მოწყობილობის გადატვირთვა."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"გადატვირთვა"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"გაუქმება"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"მოსახსნელი eSIM-ის ნაგულისხმევად დაყენება"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"მობილური რადიოკავშირის ელკვება"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"სიმულაცია სერვისის გარეშე (მხოლოდ გამართვის აგება)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM-ის მისამართების წიგნის ნახვა"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"დაშვებული ნომრების ნახვა"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"სერვისის დარეკილი ნომრების ნახვა"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"დაკავშირებულია"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"შეჩერებულია"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"უცნობი"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ძირითადი"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"პკტ."</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ბაიტი"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ტელეფონის ინფორმაცია"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"ოპერატორის უზრუნველყოფის ინფორმაცია"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ოპერატორის უზრუნველყოფის გააქტიურება"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"განახლება"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"განახლება"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"თქვენი Bluetooth სიგნალი სუსტია. სცადეთ სპიკერფონზე გადართვა."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"შეტყობინება ზარის ხარისხის შესახებ"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"მოძველებული SIP ანგარიშები"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ამ პროფილიდან შეტყობინებების გაგზავნა შეუძლებელია"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"თქვენი სამსახურის წესები საშუალებას გაძლევთ, შეტყობინებები გაგზავნოთ მხოლოდ სამუშაო პროფილიდან"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"გაუქმება"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"სამსახურის პროფილზე გადართვა"</string>
</resources>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index eecbd52..878f59d 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -303,7 +303,7 @@
<string name="carrier_settings_euicc" msgid="1190237227261337749">"Оператор"</string>
<string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"оператор, esim, sim, euicc, операторларды ауыстыру, оператор қосу"</string>
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> — <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
- <string name="mobile_data_settings_title" msgid="7228249980933944101">"Мобильдік деректер"</string>
+ <string name="mobile_data_settings_title" msgid="7228249980933944101">"Мобильдік интернет"</string>
<string name="mobile_data_settings_summary" msgid="5012570152029118471">"Деректерге мобильдік желі арқылы кіру"</string>
<string name="data_usage_disable_mobile" msgid="5669109209055988308">"Мобильдік байланысты өшіру қажет пе?"</string>
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Таңдау қажет"</string>
@@ -452,7 +452,7 @@
<string name="sum_fdn_change_pin" msgid="3510994280557335727">"ТТН қол жетімділігі үшін PIN кодты өзгерту"</string>
<string name="sum_fdn_manage_list" msgid="3311397063233992907">"Телефон нөмірлері тізімін басқару"</string>
<string name="voice_privacy" msgid="7346935172372181951">"Дауыс құпиялығы"</string>
- <string name="voice_privacy_summary" msgid="3556460926168473346">"Жетілдірілген құпиялылық режимін қосу"</string>
+ <string name="voice_privacy_summary" msgid="3556460926168473346">"Жетілдірілген құпиялық режимін қосу"</string>
<string name="tty_mode_option_title" msgid="3843817710032641703">"Tелетайп режимі"</string>
<string name="tty_mode_option_summary" msgid="4770510287236494371">"Телетайп режиміне реттеу"</string>
<string name="auto_retry_mode_title" msgid="2985801935424422340">"Әрекетті автоматты қайталау"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Бұл параметрді өзгерту үшін құрылғыны қайта қосу қажет."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Қайта қосу"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Өшіру"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Алынбалы eSIM әдепкі етіп орнату"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Радиосигнал күші"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\"Істен шыққан\" қызметін симуляциялау (түзету құрамасы ғана)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM мекенжай кітапшасын көру"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Рұқсат нөмірлерді көру"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Қызметтік теру нөмірлерін көру"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Жалғанған"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Уақытша тоқтатылған"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Белгісіз"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Негізгі"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"байт"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Телефон ақпараты"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Операторды инициализациялау туралы ақпарат"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Операторды инциализациялауды іске қосу"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC негіздеме идентификаторы:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Жаңарту"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Жаңарту"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth сигналы нашар. Спикерфонға ауысып көріңіз."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Қоңырау сапасы туралы хабарландыру"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Қолданыстан шыққан SIP аккаунттары"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Бұл профильден хабар жіберу мүмкін емес"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Жұмыс саясатыңызға сәйкес тек жұмыс профилінен хабар жіберуге болады."</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Бас тарту"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Жұмыс профиліне ауысу"</string>
</resources>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index 3f20814..9fc200d 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"អ្នកត្រូវចាប់ផ្ដើមឧបករណ៍របស់អ្នកឡើងវិញ ដើម្បីផ្លាស់ប្ដូរការកំណត់នេះ។"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ចាប់ផ្ដើមឡើងវិញ"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"បោះបង់"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"កំណត់ eSIM ដែលអាចដកបានជាលំនាំដើម"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"ថាមពលវិទ្យុទូរសព្ទចល័ត"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"ត្រាប់តាមពេលគ្មានសេវា (កំណែបង្កើតសម្រាប់ជួសជុលតែប៉ុណ្ណោះ)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"មើលសៀវភៅអាសយដ្ឋានក្នុងស៊ីមកាត"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"មើលលេខហៅថេរ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"មើលលេខហៅសេវាកម្ម"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"បានភ្ជាប់"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"បានផ្អាក"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"មិនស្គាល់"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ចម្បង"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"បៃ"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ព័ត៌មានទូរសព្ទ"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"ព័ត៌មានអំពីការផ្តល់ទិន្នន័យរបស់ក្រុមហ៊ុនសេវាទូរសព្ទ"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"នាំឱ្យមានការផ្តល់ទិន្នន័យពីក្រុមហ៊ុនសេវាទូរសព្ទ"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"លេខសម្គាល់ការផ្ដល់សិទ្ធិ WFC៖"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"ដំឡើងកំណែ"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ផ្ទុកឡើងវិញ"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"រលកសញ្ញាប៊្លូធូសរបស់អ្នកមានកម្រិតខ្សោយ។ សូមសាកល្បងប្ដូរទៅឧបករណ៍បំពងសំឡេងទូរសព្ទ។"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"ការជូនដំណឹងអំពីគុណភាពហៅទូរសព្ទ"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"គណនី SIP ដែលបានបញ្ឈប់"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"មិនអាចផ្ញើសារពីកម្រងព័ត៌មាននេះបានទេ"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"គោលការណ៍ការងាររបស់អ្នកអនុញ្ញាតឱ្យអ្នកផ្ញើសារបានតែពីកម្រងព័ត៌មានការងារប៉ុណ្ណោះ"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"បោះបង់"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"ប្ដូរទៅកម្រងព័ត៌មានការងារ"</string>
</resources>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index 166d1da..c0117f5 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -584,7 +584,7 @@
<string name="onscreenSwapCallsText" msgid="2682542150803377991">"ಸ್ವ್ಯಾಪ್ ಮಾಡು"</string>
<string name="onscreenManageCallsText" msgid="1162047856081836469">"ಕರೆಗಳನ್ನು ನಿರ್ವಹಿಸಿ"</string>
<string name="onscreenManageConferenceText" msgid="4700574060601755137">"ಕಾನ್ಫರೆನ್ಸ್ ನಿರ್ವಹಿಸಿ"</string>
- <string name="onscreenAudioText" msgid="7224226735052019986">"ಆಡಿಯೊ"</string>
+ <string name="onscreenAudioText" msgid="7224226735052019986">"ಆಡಿಯೋ"</string>
<string name="onscreenVideoCallText" msgid="1743992456126258698">"ವೀಡಿಯೊ ಕರೆ"</string>
<string name="importSimEntry" msgid="3892354284082689894">"ಆಮದು"</string>
<string name="importAllSimEntries" msgid="2628391505643564007">"ಎಲ್ಲವನ್ನೂ ಆಮದು ಮಾಡು"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"ಈ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಬದಲಾಯಿಸಲು ನೀವು ಸಾಧನವನ್ನು ಮರುಪ್ರಾರಂಭಿಸುವ ಅಗತ್ಯವಿದೆ."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ಮರುಪ್ರಾರಂಭಿಸಿ"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"ರದ್ದುಮಾಡಿ"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"ತೆಗೆದುಹಾಕಬಹುದಾದ eSIM ಅನ್ನು ಡೀಫಾಲ್ಟ್ ಆಗಿ ಸೆಟ್ ಮಾಡಿ"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"ಮೊಬೈಲ್ ರೇಡಿಯೋ ಪವರ್"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"ಸೇವೆಯಲ್ಲಿಲ್ಲದಿರುವುದನ್ನು ಸಿಮ್ಯುಲೇಟ್ ಮಾಡುವುದು (ಡೀಬಗ್ ಬಿಲ್ಡ್ ಮಾತ್ರ)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ಸಿಮ್ ವಿಳಾಸ ಪುಸ್ತಕವನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ಸೇವಾ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"ಅಮಾನತುಗೊಳಿಸಲಾಗಿದೆ"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"ಅಪರಿಚಿತ"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ಪ್ರಾಥಮಿಕ"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ಬೈಟ್ಗಳು"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ಫೋನ್ ಮಾಹಿತಿ"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"ವಾಹಕ ಪೂರೈಕೆಯ ಮಾಹಿತಿ"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ಟ್ರಿಗರ್ ವಾಹಕ ಪೂರೈಕೆ"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC ಅರ್ಹತೆ ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"ಅಪ್ಡೇಟ್ ಮಾಡಿ"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ರಿಫ್ರೆಶ್"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"ನಿಮ್ಮ ಬ್ಲೂಟೂತ್ ಸಿಗ್ನಲ್ ದುರ್ಬಲವಾಗಿದೆ. ಸ್ಪೀಕರ್ಫೋನ್ಗೆ ಬದಲಾಯಿಸಲು ಪ್ರಯತ್ನಿಸಿ."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"ಕರೆ ಗುಣಮಟ್ಟದ ಅಧಿಸೂಚನೆ"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"ತಡೆಹಿಡಿಯಲಾಗಿರುವ SIP ಖಾತೆಗಳು"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ಈ ಪ್ರೊಫೈಲ್ನಿಂದ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"ನಿಮ್ಮ ಉದ್ಯೋಗದ ನೀತಿಯು ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ನಿಂದ ಮಾತ್ರ ಸಂದೇಶವನ್ನು ಕಳುಹಿಸಲು ನಿಮಗೆ ಅನುಮತಿಸುತ್ತದೆ"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"ರದ್ದುಮಾಡಿ"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ಗೆ ಬದಲಿಸಿ"</string>
</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index ed07f60..c80c6c3 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"설정을 변경하려면 기기를 다시 시작해야 합니다."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"다시 시작"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"취소"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"삭제 가능한 eSIM을 기본으로 설정"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"모바일 무선 전력"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\'서비스 지역 벗어남\' 시뮬레이션(디버그 빌드만 해당)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM 주소록 보기"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"발신 허용 번호 보기"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"SDN(Service Dialing Numbers) 보기"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"연결됨"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"정지됨"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"알 수 없음"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"기본"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"패킷"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"바이트"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"휴대전화 정보"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"이동통신사 프로비저닝 정보"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"이동통신사 프로비저닝 실행"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC 사용 권한 ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"업데이트"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"새로고침"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"블루투스 신호 강도가 약합니다. 스피커폰으로 전환해 보세요."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"통화 품질 알림"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"지원 중단된 SIP 계정"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"이 프로필에서 메시지를 보낼 수 없음"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"직장 정책을 사용하면 직장 프로필에서만 메시지를 보낼 수 있습니다."</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"취소"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"직장 프로필로 전환"</string>
</resources>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index d864bf9..0e9f986 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -47,7 +47,7 @@
<string name="no_vm_number" msgid="6623853880546176930">"Үн почтасынын номери жок болуп жатат"</string>
<string name="no_vm_number_msg" msgid="5165161462411372504">"SIM-картада сакталган үн почтасынын номери жок."</string>
<string name="add_vm_number_str" msgid="7368168964435881637">"Номер кошуу"</string>
- <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Үн почта жөндөөлөрүн алгачкы колдонуучу гана өзгөртө алат."</string>
+ <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Үн почта параметрлерин алгачкы колдонуучу гана өзгөртө алат."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"SIM картаңыз бөгөттөн чыгарылган. Телефонуңуздун кулпусу ачылууда…"</string>
<string name="label_ndp" msgid="7617392683877410341">"SIM-карта тармагынын кулпусун ачуучу PIN код"</string>
<string name="label_phoneid" msgid="8775611434123577808">"SIM-карта оператор үчүн кулпуланган"</string>
@@ -56,23 +56,23 @@
<string name="requesting_unlock" msgid="930512210309437741">"Тармак кулпусун ачуу суралууда…"</string>
<string name="unlock_failed" msgid="7103543844840661366">"Тармактын кулпусун ачуу өтүнүчү ишке ашкан жок."</string>
<string name="unlock_success" msgid="32681089371067565">"Тармактын кулпусу ийгиликтүү ачылды."</string>
- <string name="mobile_network_settings_not_available" msgid="8678168497517090039">"Бул колдонуучу мобилдик тармак жөндөөлөрүн колдоно албайт"</string>
- <string name="labelGSMMore" msgid="7354182269461281543">"GSM чалуунун жөндөөлөрү"</string>
- <string name="labelGsmMore_with_label" msgid="3206015314393246224">"GSM чалуунун жөндөөлөрү (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
- <string name="labelCDMAMore" msgid="7937441382611224632">"CDMA чалуунун жөндөөлөрү"</string>
- <string name="labelCdmaMore_with_label" msgid="7759692829160238152">"CDMA чалуунун жөндөөлөрү (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="mobile_network_settings_not_available" msgid="8678168497517090039">"Бул колдонуучу мобилдик тармак параметрлерин колдоно албайт"</string>
+ <string name="labelGSMMore" msgid="7354182269461281543">"GSM чалуунун параметрлери"</string>
+ <string name="labelGsmMore_with_label" msgid="3206015314393246224">"GSM чалуунун параметрлери (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="labelCDMAMore" msgid="7937441382611224632">"CDMA чалуунун параметрлери"</string>
+ <string name="labelCdmaMore_with_label" msgid="7759692829160238152">"CDMA чалуунун параметрлери (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="apn_settings" msgid="1978652203074756623">"Туташуу түйүндөрү (APN)"</string>
- <string name="settings_label" msgid="9101778088412567956">"Тармак жөндөөлөрү"</string>
+ <string name="settings_label" msgid="9101778088412567956">"Тармак параметрлери"</string>
<string name="phone_accounts" msgid="1216879437523774604">"Чалуу аккаунттары"</string>
<string name="phone_accounts_make_calls_with" msgid="16747814788918145">"Чалууларды төмөнкү менен жасоо"</string>
<string name="phone_accounts_make_sip_calls_with" msgid="4691221006731847255">"SIP чалууларын төмөнкү менен жасоо"</string>
<string name="phone_accounts_ask_every_time" msgid="6192347582666047168">"Биринчи сурасын"</string>
<string name="phone_accounts_default_account_label" msgid="5107598881335931101">"Тармак жок"</string>
- <string name="phone_accounts_settings_header" msgid="6296501692964706536">"Жөндөөлөр"</string>
+ <string name="phone_accounts_settings_header" msgid="6296501692964706536">"Параметрлер"</string>
<string name="phone_accounts_choose_accounts" msgid="4748805293314824974">"Аккаунттарды тандоо"</string>
<string name="phone_accounts_selection_header" msgid="2945830843104108440">"Телефон каттоо эсептери"</string>
<string name="phone_accounts_add_sip_account" msgid="1437634802033309305">"SIP аккаунтун кошуу"</string>
- <string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Каттоо эсеп жөндөөлөрүн конфигурациялоо"</string>
+ <string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Каттоо эсеп параметрлерин конфигурациялоо"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"Бардык чалуу каттоо эсептери"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Чалуулар жасала турган каттоо эсептерин тандаңыз"</string>
<string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi чалуу"</string>
@@ -85,18 +85,18 @@
<string name="smart_forwarding_settings_menu_summary" msgid="5096947726032885325">"Бир номер жеткиликсиз болсо, чалууларды ар дайым башка номериңизге багыттоо"</string>
<string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"Билдирмелер"</string>
<string name="cell_broadcast_settings" msgid="8135324242541809924">"Өзгөчө кырдаал тууралуу кулактандыруу"</string>
- <string name="call_settings" msgid="3677282690157603818">"Чалуу жөндөөлөрү"</string>
+ <string name="call_settings" msgid="3677282690157603818">"Чалуу параметрлери"</string>
<string name="additional_gsm_call_settings" msgid="1561980168685658846">"Кошумча жөндөөлөр"</string>
<string name="additional_gsm_call_settings_with_label" msgid="7973920539979524908">"Кошумча жөндөөлөр (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
- <string name="sum_gsm_call_settings" msgid="7964692601608878138">"GSM менен гана чалуунун кошумча жөндөөлөрү"</string>
- <string name="additional_cdma_call_settings" msgid="2178016561980611304">"Кошумча CDMA чалуунун жөндөөлөрү"</string>
- <string name="sum_cdma_call_settings" msgid="3185825305136993636">"CDMA менен гана чалуунун кошумча жөндөөлөрү"</string>
- <string name="labelNwService" msgid="6015891883487125120">"Тармак кызматынын жөндөөлөрү"</string>
+ <string name="sum_gsm_call_settings" msgid="7964692601608878138">"GSM менен гана чалуунун кошумча параметрлери"</string>
+ <string name="additional_cdma_call_settings" msgid="2178016561980611304">"Кошумча CDMA чалуунун параметрлери"</string>
+ <string name="sum_cdma_call_settings" msgid="3185825305136993636">"CDMA менен гана чалуунун кошумча параметрлери"</string>
+ <string name="labelNwService" msgid="6015891883487125120">"Тармак кызматынын параметрлери"</string>
<string name="labelCallerId" msgid="2090540744550903172">"Чалуучуну аныктоо"</string>
- <string name="sum_loading_settings" msgid="434063780286688775">"Жөндөөлөр жүктөлүүдө…"</string>
+ <string name="sum_loading_settings" msgid="434063780286688775">"Параметрлер жүктөлүүдө…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Чыгуучу чалууларда номер жашырылган"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Чыгуучу чалууларда көрсөтүлчү номер"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Кимдир-бирөөгө чалып жатканда ага номерим көрүнүшү үчүн байланыш операторунун стандарттуу жөндөөлөрү колдонулат."</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Кимдир-бирөөгө чалып жатканда ага номерим көрүнүшү үчүн байланыш операторунун стандарттуу параметрлери колдонулат."</string>
<string name="labelCW" msgid="8449327023861428622">"Чалууну кармап туруу"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Бирөө менен сүйлөшүп жатканда сизге келген чалуулар жөнүндө эскертилет"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Бирөө менен сүйлөшүп жатканда сизге келген чалуулар жөнүндө эскертилет"</string>
@@ -131,13 +131,13 @@
<string name="disable_cdma_cw" msgid="7119290446496301734">"Баш тартуу"</string>
<string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMS платформасында CDMA чалуу күтүүcү күйгүзүлгөн"</string>
<string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMS платформасында CDMA чалуу күтүүcү өчүрүлгөн"</string>
- <string name="updating_title" msgid="6130548922615719689">"Чалуу жөндөөлөрү"</string>
- <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Чалуу жөндөөлөрүн администратор гана өзгөртө алат."</string>
- <string name="call_settings_with_label" msgid="8460230435361579511">"Жөндөөлөр (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
+ <string name="updating_title" msgid="6130548922615719689">"Чалуу параметрлери"</string>
+ <string name="call_settings_admin_user_only" msgid="7238947387649986286">"Чалуу параметрлерин администратор гана өзгөртө алат."</string>
+ <string name="call_settings_with_label" msgid="8460230435361579511">"Параметрлер (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"Чалуу жөндөөлөрүндө ката кетти"</string>
- <string name="reading_settings" msgid="1605904432450871183">"Жөндөөлөр окулууда…"</string>
- <string name="updating_settings" msgid="3650396734816028808">"Жөндөөлөр жаңыртылууда…"</string>
- <string name="reverting_settings" msgid="7378668837291012205">"Жөндөөлөр артка кайтарылууда…"</string>
+ <string name="reading_settings" msgid="1605904432450871183">"Параметрлер окулууда…"</string>
+ <string name="updating_settings" msgid="3650396734816028808">"Параметрлер жаңыртылууда…"</string>
+ <string name="reverting_settings" msgid="7378668837291012205">"Параметрлер артка кайтарылууда…"</string>
<string name="response_error" msgid="3904481964024543330">"Тармактан күтүлбөгөн жооп алынды."</string>
<string name="exception_error" msgid="330994460090467">"Тармак же SIM карта катасы."</string>
<string name="stk_cc_ss_to_dial_error" msgid="5147693491690618704">"SS сурамы демейки чалууга өзгөртүлдү"</string>
@@ -328,7 +328,7 @@
<string name="enable_disable_cell_bc_sms" msgid="4759958924031721350">"Уюлдук жөнөтүү SMS\'и"</string>
<string name="cell_bc_sms_enable" msgid="2019708772024632073">"Уюлдук жөнөтүү SMS\'и иштетилген"</string>
<string name="cell_bc_sms_disable" msgid="1214238639910875347">"Уюлдук жөнөтүү SMS\'и өчүрүлгөн"</string>
- <string name="cb_sms_settings" msgid="6858093721831312036">"Уюлдук жөнөтүүлөрдүн SMS жөндөөлөрү"</string>
+ <string name="cb_sms_settings" msgid="6858093721831312036">"Уюлдук жөнөтүүлөрдүн SMS параметрлери"</string>
<string name="enable_disable_emergency_broadcast" msgid="6325655044472196496">"Өзгөчө кырдаалдагы жөнөтүүлөр"</string>
<string name="emergency_broadcast_enable" msgid="5759610647771102442">"Өзгөчө кырдаалдагы жөнөтүүлөр иштетилген"</string>
<string name="emergency_broadcast_disable" msgid="2844904734469323266">"Өзгөчө кырдаалдагы жөнөтүүлөр өчүрүлгөн"</string>
@@ -650,7 +650,7 @@
<string name="voicemail_provider" msgid="4158806657253745294">"Кызмат"</string>
<string name="voicemail_settings" msgid="4451045613238972776">"Жөндөө"</string>
<string name="voicemail_number_not_set" msgid="8831561283386938155">"<Коюлган эмес>"</string>
- <string name="other_settings" msgid="8895088007393598447">"Башка чалуу жөндөөлөрү"</string>
+ <string name="other_settings" msgid="8895088007393598447">"Башка чалуу параметрлери"</string>
<string name="calling_via_template" msgid="1791323450703751750">"<xliff:g id="PROVIDER_NAME">%s</xliff:g> аркылуу чалуу"</string>
<string name="contactPhoto" msgid="7885089213135154834">"байланыштын сүрөтү"</string>
<string name="goPrivate" msgid="4645108311382209551">"купуя режимине өтүү"</string>
@@ -665,8 +665,8 @@
<string name="preference_category_ringtone" msgid="8787281191375434976">"Рингтон жана Титирөө"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"Кыналган SIM карталар"</string>
<string name="enable_video_calling_title" msgid="7246600931634161830">"Видео чалууну күйгүзүү"</string>
- <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Видео чалууну күйгүзүү үчүн тармак жөндөөлөрүнөн Жакшыртылган 4G LTE режимин иштетишиңиз керек."</string>
- <string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"Тармак жөндөөлөрү"</string>
+ <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Видео чалууну күйгүзүү үчүн тармак параметрлеринен Жакшыртылган 4G LTE режимин иштетишиңиз керек."</string>
+ <string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"Тармак параметрлери"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Жабуу"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"Шашылыш чалуулар"</string>
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"Шашылыш чалуу гана"</string>
@@ -781,7 +781,7 @@
<string name="call_barring_baicr_enabled" msgid="64774270234828175">"Роумингдеги эл аралык кирүүчү чалууларды бөгөттөө функциясы өчүрүлсүнбү?"</string>
<string name="call_barring_baicr_disabled" msgid="3488129262744027262">"Роумингдеги эл аралык кирүүчү чалуу бөгөттөлсүнбү?"</string>
<string name="call_barring_deactivate_all" msgid="7837931580047157328">"Баары өчүрүлсүн"</string>
- <string name="call_barring_deactivate_all_description" msgid="4474119585042121604">"Чалууларга тыюу салуу функциясынын жөндөөлөрүн өчүрүү"</string>
+ <string name="call_barring_deactivate_all_description" msgid="4474119585042121604">"Чалууларга тыюу салуу функциясынын параметрлерин өчүрүү"</string>
<string name="call_barring_deactivate_success" msgid="3545644320298275337">"Чалууларга тыюу салуу функциясы өчүрүлдү"</string>
<string name="call_barring_change_pwd" msgid="1730691950940338387">"Сызсөздү өзгөртүү"</string>
<string name="call_barring_change_pwd_description" msgid="1274245130382054227">"Чалууларга тыюу салуу функциясынын сырсөзүн өзгөртүү"</string>
@@ -793,7 +793,7 @@
<string name="call_barring_new_pwd" msgid="2515524903813227732">"Жаңы сырсөз"</string>
<string name="call_barring_confirm_pwd" msgid="7552526161616461858">"Сырсөздү ырастоо"</string>
<string name="messageCallBarring" msgid="5537730400652466912">"Сырсөздү киргизиңиз"</string>
- <string name="call_barring_settings" msgid="4616607285790258919">"Чалууларга тыюу салуу функциясынын жөндөөлөрү"</string>
+ <string name="call_barring_settings" msgid="4616607285790258919">"Чалууларга тыюу салуу функциясынын параметрлери"</string>
<string name="callFailed_NetworkBusy" msgid="5437103975842913681">"Тармак бош эмес. Кийинчерээк кайра чалыңыз."</string>
<string name="callFailed_NetworkCongested" msgid="6801283142342775380">"Тармак ашыкча жүктөлгөн. Жардам алуу үчүн мобилдик операторуңуз менен байланышыңыз."</string>
<string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"Чалуу кабыл алынган жок."</string>
@@ -818,10 +818,10 @@
<string name="callFailed_already_ringing" msgid="2376603543544289303">"Чалуу аткарылбайт, анткени кирүүчү чалууга жооп берилген жок. Жаңы чалуу аткаруудан мурун кирүүчү чалууга жооп берип же четке кагыңыз."</string>
<string name="callFailed_calling_disabled" msgid="5010992739401206283">"Чалуу аткарылбайт, анткени чалуу ro.telephony.disable-call тутуму аркылуу өчүрүлгөн."</string>
<string name="callFailed_too_many_calls" msgid="2761754044990799580">"Чалуу аткарылбайт, анткени эки чалуу аткарылууда. Бир чалууну өчүрүңүз же аларды конференцияга бириктириңиз."</string>
- <string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"<xliff:g id="SUPP_SERVICE">%s</xliff:g> колдонуу үчүн мобилдик Интернет күйгүзүлгөнүн текшериңиз. Муну мобилдик тармак жөндөөлөрүнөн өзгөртсөңүз болот."</string>
- <string name="supp_service_over_ut_precautions_roaming" msgid="670342104569972327">"<xliff:g id="SUPP_SERVICE">%s</xliff:g> колдонуу үчүн мобилдик Интернет жана Интернет-роуминг күйгүзүлгөнүн текшериңиз. Муну мобилдик тармак жөндөөлөрүнөн өзгөртсөңүз болот."</string>
- <string name="supp_service_over_ut_precautions_dual_sim" msgid="5166866975550910474">"<xliff:g id="SUPP_SERVICE">%1$s</xliff:g> колдонуу үчүн <xliff:g id="SIM_NUMBER">%2$d</xliff:g> SIM-картасында мобилдик Интернет күйгүзүлгөнүн текшериңиз. Муну мобилдик тармак жөндөөлөрүнөн өзгөртсөңүз болот."</string>
- <string name="supp_service_over_ut_precautions_roaming_dual_sim" msgid="6627654855191817965">"<xliff:g id="SUPP_SERVICE">%1$s</xliff:g> колдонуу үчүн <xliff:g id="SIM_NUMBER">%2$d</xliff:g> SIM-картасында мобилдик Интернет жана Интернет-роуминг күйгүзүлгөнүн текшериңиз. Муну мобилдик тармак жөндөөлөрүнөн өзгөртсөңүз болот."</string>
+ <string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"<xliff:g id="SUPP_SERVICE">%s</xliff:g> колдонуу үчүн мобилдик Интернет күйгүзүлгөнүн текшериңиз. Муну мобилдик тармак параметрлеринен өзгөртсөңүз болот."</string>
+ <string name="supp_service_over_ut_precautions_roaming" msgid="670342104569972327">"<xliff:g id="SUPP_SERVICE">%s</xliff:g> колдонуу үчүн мобилдик Интернет жана Интернет-роуминг күйгүзүлгөнүн текшериңиз. Муну мобилдик тармак параметрлеринен өзгөртсөңүз болот."</string>
+ <string name="supp_service_over_ut_precautions_dual_sim" msgid="5166866975550910474">"<xliff:g id="SUPP_SERVICE">%1$s</xliff:g> колдонуу үчүн <xliff:g id="SIM_NUMBER">%2$d</xliff:g> SIM-картасында мобилдик Интернет күйгүзүлгөнүн текшериңиз. Муну мобилдик тармак параметрлеринен өзгөртсөңүз болот."</string>
+ <string name="supp_service_over_ut_precautions_roaming_dual_sim" msgid="6627654855191817965">"<xliff:g id="SUPP_SERVICE">%1$s</xliff:g> колдонуу үчүн <xliff:g id="SIM_NUMBER">%2$d</xliff:g> SIM-картасында мобилдик Интернет жана Интернет-роуминг күйгүзүлгөнүн текшериңиз. Муну мобилдик тармак параметрлеринен өзгөртсөңүз болот."</string>
<string name="supp_service_over_ut_precautions_dialog_dismiss" msgid="5934541487903081652">"Жабуу"</string>
<string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Мобилдик туташууну иштетүү"</string>
<string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Мобилдик туташууну өчүрүү"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Бул жөндөөнү өзгөртүү үчүн түзмөгүңүздү өчүрүп күйгүзүңүз."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Өчүрүп-күйгүзүү"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Жокко чыгаруу"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Чыгарылуучу eSIM-картаны демейки катары коюу"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Мобилдик радионун кубаты"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Тейлөө аймагынын сыртында режимин иштетүү (Мүчүлүштүктөрдү оңдоо үчүн гана)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM картадагы дарек китепчесин көрүү"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Туруктуу терүү номерлерин көрүү"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Кызматтык терүү номерлерин көрүү"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Туташты"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Убактылуу токтотулду"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Белгисиз"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Башкы"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"байттар"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -900,7 +903,7 @@
<string name="radio_info_smsc_update_label" msgid="5141996256097115753">"Жаңыртуу"</string>
<string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Жаңылоо"</string>
<string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS текшерүүнү которуштуруу"</string>
- <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM\'ге тиешелүү Маалымат/Жөндөөлөр"</string>
+ <string name="oem_radio_info_label" msgid="2914167475119997456">"OEM\'ге тиешелүү Маалымат/Параметрлер"</string>
<string name="radio_info_endc_available" msgid="2983767110681230019">"EN-DC жеткиликтүү (NSA):"</string>
<string name="radio_info_dcnr_restricted" msgid="7147511536420148173">"DCNR чектелген (NSA):"</string>
<string name="radio_info_nr_available" msgid="3383388088451237182">"NR жеткиликтүү (NSA):"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Телефондун маалыматы"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Байланыш оператору жөнүндө маалымат"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Байланыш операторун өзгөртүү"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Entitlement идентификатору:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Жаңыртуу"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Жаңыртуу"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth сигналыңыз начар. Спикерфонго которулуп көрүңүз."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Чалуунун сапаты тууралуу билдирме"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Колдонуудан чыккан SIP аккаунттары"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Билдирүүлөрдү бул профилден жөнөтүүгө болбойт"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Жумуш саясатыңызга ылайык, билдирүүлөрдү жумуш профилинен гана жөнөтө аласыз"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Жокко чыгаруу"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Жумуш профилине которулуу"</string>
</resources>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 79d8899..4bbe66e 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"ທ່ານຕ້ອງຣີສະຕາດອຸປະກອນຂອງທ່ານເພື່ອປ່ຽນການຕັ້ງຄ່ານີ້."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ປິດເປີດຄືນໃໝ່"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"ຍົກເລີກ"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"ຕັ້ງຄ່າ eSIM ແບບຖອດໄດ້ໃຫ້ເປັນຄ່າເລີ່ມຕົ້ນ"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"ພະລັງງານວິທະຍຸມືຖື"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"ຈໍາລອງເຫດການບໍ່ພ້ອມໃຫ້ບໍລິການ (ສໍາລັບ Build ດີບັກເທົ່ານັ້ນ)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ເບິ່ງສະໝຸດທີ່ຢູ່ໃນຊິມ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ເບິ່ງໝາຍເລກໂທອອກທີ່ກຳນົດ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ເບິ່ງໝາຍເລກບໍລິການໂທອອກ"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"ລະງັບໄວ້ແລ້ວ"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"ບໍ່ຮູ້ຈັກ"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ຫຼັກ"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ໄບຕ໌"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ຂໍ້ມູນໂທລະສັບ"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"ຂໍ້ມູນການເປີດນຳໃຊ້ເຄືອຂ່າຍ"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ກະຕຸ້ນການຈັດຫາຜູ້ໃຫ້ບໍລິການ"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ລະຫັດ ID ສິດ ຂອງ WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"ອັບເດດ"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ໂຫຼດຂໍ້ມູນຄືນໃໝ່"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"ສັນຍານ Bluetooth ຂອງທ່ານອ່ອນ. ລອງສະຫຼັບລຳໂພງໂທລະສັບ."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"ການແຈ້ງເຕືອນຄຸນນະພາບການໂທ"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"ບັນຊີ SIP ທີ່ເຊົາສະໜັບສະໜູນ"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ບໍ່ສາມາດສົ່ງຂໍ້ຄວາມຈາກໂປຣໄຟລ໌ນີ້ໄດ້"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"ນະໂຍບາຍບ່ອນເຮັດວຽກຂອງທ່ານອະນຸຍາດໃຫ້ທ່ານສົ່ງຂໍ້ຄວາມໄດ້ຈາກໂປຣໄຟລ໌ບ່ອນເຮັດວຽກເທົ່ານັ້ນ"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"ຍົກເລີກ"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"ສະຫຼັບໄປໃຊ້ໂປຣໄຟລ໌ບ່ອນເຮັດວຽກ"</string>
</resources>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index cd529a5..9c2d2ea 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Turite paleisti įrenginį iš naujo, kad galėtumėte pakeisti šį nustatymą."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Paleisti iš naujo"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Atšaukti"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Nustatyti pašalinimą „eSIM“ kaip numatytąją"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobiliojo ryšio radijo signalas"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Modeliavimas neteikiamas (tik derinimo versija)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Žiūrėti SIM kortelės adresų knygą"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Žiūrėti fiksuotojo rinkimo numerius"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Žiūrėti paslaugos renkamus numerius"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Prisijungta"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Laikinai sustabdyta"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Nežinoma"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Pagrindinis"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pakuot."</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"B"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefono informacija"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operatoriaus aprūpinimo informacija"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktyviklio operatoriaus aprūpinimas"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"„Wi-Fi“ skambinimo teisės suteikimo ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Atnaujinti"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Atnaujinti"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Silpnas „Bluetooth“ signalas. Pabandykite perjungti garsiakalbį."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Pranešimas apie skambučio kokybę"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Nebenaudojamos SIP paskyros"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Nepavyko išsiųsti pranešimo iš šio profilio"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Pagal jūsų darbo politiką galite siųsti pranešimus tik iš darbo profilio"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Atšaukti"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Perjungti į darbo profilį"</string>
</resources>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index cd59d1a..a60d560 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Lai mainītu šo iestatījumu, jums jārestartē ierīce."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Restartēt"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Atcelt"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Iestatīt noņemamu eSIM kā noklusējumu"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobilā tālruņa radio signāla stiprums"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulācijas ierīce nedarbojas (tikai būvējuma atkļūdošana)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Skatīt SIM adrešu grāmatu"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Skatīt ierobežotā zvanu saraksta numurus"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Pakalpojuma iezvanes numuru skatīšana"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Savienojums izveidots"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Darbība apturēta"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Nezināms"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primārais"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"baiti"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Tālruņa informācija"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informācija par mobilo sakaru operatora nodrošināšanu"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktivizēt operatora nodrošināšanu"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Wi-Fi zvanu pilnvaras ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Atjaunināt"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Atsvaidzināt"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth signāls ir vājš. Mēģiniet pārslēgties uz skaļruni."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Paziņojums par zvana kvalitāti"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"SIP konti, kuru darbība ir pārtraukta"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Nevar nosūtīt ziņojumu no šī profila"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Saskaņā ar darbavietas politiku drīkstat sūtīt ziņojumus tikai no darba profila."</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Atcelt"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Pārslēgties uz darba profilu"</string>
</resources>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 7cfea83..487d996 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Треба да го рестартирате уредот за да ја промените поставкава."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Рестартирај"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Откажи"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Поставување eSIM што може да се отстрани како стандардна"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Радио-напојување на мобилен"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Симулирање „Надвор од употреба“ (само за верзиите за отстранување грешки)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Прикажи именик на SIM-картичката"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Прикажи броеви со ограничено бирање"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Прикажи броеви за бирање служби"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Поврзан"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Суспендиран"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Непознат"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Примарен"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"бајти"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Информации за телефонот"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Информации за обезбедување оператор"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Активирајте обезбедување оператор"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID на дозвола за WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Ажурирај"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Освежи"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Вашиот сигнал на Bluetooth е слаб. Обидете се со префрлање на интерфон."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Известување за квалитет на повик"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Неподдржани сметки на SIP"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Не може да се испрати порака од профилов"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Вашето работно правило ви дозволува да испраќате пораки само од работниот профил"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Откажи"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Префрли на работен профил"</string>
</resources>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index 4533385..2de21b3 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"ഈ ക്രമീകരണം മാറ്റാൻ നിങ്ങളുടെ ഉപകരണം റീസ്റ്റാർട്ട് ചെയ്യേണ്ടതുണ്ട്."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"റീസ്റ്റാർട്ട് ചെയ്യുക"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"റദ്ദാക്കുക"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"നീക്കം ചെയ്യാവുന്ന ഇ-സിം ഡിഫോൾട്ടായി സജ്ജീകരിക്കുക"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"മൊബൈൽ റേഡിയോ പവർ"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"സേവനം ലഭ്യമല്ലെന്ന് അനുകരിക്കുക (ഡീബഗ് ബിൽഡ് മാത്രം)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"സിം വിലാസ പുസ്തകം കാണുക"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"സ്ഥിര ഡയലിംഗ് നമ്പറുകൾ കാണുക"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"സർവീസ് ഡയലിംഗ് നമ്പറുകൾ കാണുക"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"കണക്റ്റ് ചെയ്തു"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"താൽക്കാലികമായി റദ്ദാക്കി"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"അജ്ഞാതം"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"പ്രാഥമികം"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ബൈറ്റുകൾ"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ഫോൺ വിവരം"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"കാരിയർ പ്രൊവിഷനിംഗ് വിവരം"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"കാരിയർ പ്രൊവിഷനിംഗ് തുടങ്ങുക"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC എൻടെെറ്റിൽമെന്റ് ഐഡി:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"അപ്ഡേറ്റ് ചെയ്യുക"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"റീഫ്രഷ് ചെയ്യുക"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"നിങ്ങളുടെ Bluetooth സിഗ്നൽ ദുർബലമാണ്. സ്പീക്കർഫോണിലേക്ക് മാറ്റി നോക്കൂ."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"കോൾ നിലവാര അറിയിപ്പ്"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"അവസാനിപ്പിച്ച SIP അക്കൗണ്ടുകൾ"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ഈ പ്രൊഫൈലിൽ നിന്ന് സന്ദേശം അയയ്ക്കാനാകില്ല"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"ഔദ്യോഗിക പ്രൊഫൈലിൽ നിന്ന് മാത്രം സന്ദേശം അയയ്ക്കാനാണ് നിങ്ങളുടെ ഔദ്യോഗിക നയം അനുവദിക്കുന്നത്"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"റദ്ദാക്കുക"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"ഔദ്യോഗിക പ്രൊഫൈലിലേക്ക് മാറുക"</string>
</resources>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index b8dc6df..81d5a12 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -534,7 +534,7 @@
<string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"Дуут шуудангийн дугаар тодорхойгүй"</string>
<string name="notification_network_selection_title" msgid="255595526707809121">"Үйлчилгээ байхгүй"</string>
<string name="notification_network_selection_text" msgid="553288408722427659">"Сонгосон <xliff:g id="OPERATOR_NAME">%s</xliff:g> сүлжээг ашиглах боломжгүй"</string>
- <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Дуудлага хийхийн тулд мобайл сүлжээг асаах, нислэгийн горим буюу батерей хэмнэх горимыг идэвхгүй болгоно уу."</string>
+ <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Дуудлага хийхийн тулд мобайл сүлжээг асаах, нислэгийн горим буюу батарей хэмнэх горимыг идэвхгүй болгоно уу."</string>
<string name="incall_error_power_off" product="default" msgid="8131672264311208673">"Дуудлага хийхийн тулд онгоцны горимыг унтраа."</string>
<string name="incall_error_power_off_wfc" msgid="9125661184694727052">"Дуудлага хийхийн тулд онгоцны горимыг унтраа эсвэл утасгүй интернетэд холбогдоно уу."</string>
<string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"Утас хэт халуун байна"</b>\n\n"Энэ дуудлагыг гүйцээх боломжгүй. Та утсаа хөрсөн үед дахин оролдоно уу.\n\nТа яаралтай дуудлага хийх боломжтой хэвээр байна."</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Та энэ тохиргоог өөрчлөхийн тулд төхөөрөмжөө дахин эхлүүлэх шаардлагатай."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Дахин эхлүүлэх"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Цуцлах"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Салгах боломжтой eSIM-г өгөгдмөлөөр тохируулах"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Мобайл радио цахилгаан"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Үйлчилгээний хүрээнээс гарсан нөхцөл байдлыг загварчлах (зөвхөн дебагийн хийц)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM хаягийн лавлахыг харах"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Залгахаар тохируулсан дугаарыг харах"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Үйлчилгээний залгах дугаарыг харах"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Холбогдсон"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Түр хаасан"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Тодорхойгүй"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Үндсэн"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"байт"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Утасны мэдээлэл"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Оператор компанийн хангалтын мэдээлэл"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Оператор компанийн хангалтыг эхлүүлэх"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Шинэчлэх"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Сэргээх"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Таны Bluetooth-н дохио сул байна. Чанга яригчтай утас руу сэлгэж үзнэ үү."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Дуудлагын чанарын мэдэгдэл"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"SIP-н зогсоосон бүртгэлүүд"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Энэ профайлаас мессеж илгээх боломжгүй"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Таны ажлын бодлого танд зөвхөн ажлын профайлаас мессеж илгээхийг зөвшөөрдөг"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Цуцлах"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Ажлын профайл руу сэлгэх"</string>
</resources>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 793bd06..800020e 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -48,7 +48,7 @@
<string name="no_vm_number_msg" msgid="5165161462411372504">"सिम कार्डवर कोणताही व्हॉइसमेल नंबर स्टोअर केला नाही."</string>
<string name="add_vm_number_str" msgid="7368168964435881637">"नंबर जोडा"</string>
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"केवळ प्राथमिक वापरकर्ता व्हॉइसमेल सेटिंग्ज बदलू शकतो."</string>
- <string name="puk_unlocked" msgid="4627340655215746511">"तुमचे सिम कार्ड अवरोधित करणे रद्द केले गेले आहे. तुमचा फोन अनलॉक होत आहे…"</string>
+ <string name="puk_unlocked" msgid="4627340655215746511">"तुमचे सिम कार्ड ब्लॉक करणे रद्द केले गेले आहे. तुमचा फोन अनलॉक होत आहे…"</string>
<string name="label_ndp" msgid="7617392683877410341">"सिम नेटवर्क अनलॉक पिन"</string>
<string name="label_phoneid" msgid="8775611434123577808">"ऑपरेटरसाठी सिम लॉक केले आहे"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"अनलॉक करा"</string>
@@ -424,7 +424,7 @@
</string-array>
<string name="cdma_subscription_title" msgid="3449527179325589434">"CDMA सदस्यता"</string>
<string name="cdma_subscription_summary" msgid="5681152534466169001">"RUIM/सिम आणि NV मध्ये बदला"</string>
- <string name="cdma_subscription_dialogtitle" msgid="8872086335839723980">"सदस्यता"</string>
+ <string name="cdma_subscription_dialogtitle" msgid="8872086335839723980">"सदस्यत्व"</string>
<string-array name="cdma_subscription_choices">
<item msgid="7989486897370727698">"RUIM/सिम"</item>
<item msgid="5445342771222849381">"NV"</item>
@@ -499,7 +499,7 @@
<string name="disable_pin_ok" msgid="888505244389647754">"पिन साफ केला"</string>
<string name="pin_failed" msgid="4527347792881939652">"पिन चुकीचा आहे"</string>
<string name="pin_changed" msgid="7291153750090452808">"पिन अपडेट केला"</string>
- <string name="puk_requested" msgid="2061337960609806851">"पासवर्ड चुकीचा आहे. पिन आता अवरोधित केला. PUK ची विनंती केली."</string>
+ <string name="puk_requested" msgid="2061337960609806851">"पासवर्ड चुकीचा आहे. पिन आता ब्लॉक केला. PUK ची विनंती केली."</string>
<string name="enter_pin2_text" msgid="7266379426804295979">"PIN2"</string>
<string name="oldPin2Label" msgid="4648543187859997203">"जुना PIN2"</string>
<string name="newPin2Label" msgid="1840905981784453939">"नवीन PIN2"</string>
@@ -511,12 +511,12 @@
<string name="invalidPuk2" msgid="713729511903849544">"8 अंक असलेला एक PUK2 प्रविष्ट करा."</string>
<string name="pin2_changed" msgid="5710551850481287821">"पिन2 अपडेट केला"</string>
<string name="label_puk2_code" msgid="2852217004288085562">"PUK2 कोड प्रविष्ट करा"</string>
- <string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"पासवर्ड चुकीचा आहे. पिन2 आता अवरोधित केला. पुन्हा प्रयत्न करण्यासाठी, पिन 2 बदला."</string>
+ <string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"पासवर्ड चुकीचा आहे. पिन2 आता ब्लॉक केला. पुन्हा प्रयत्न करण्यासाठी, पिन 2 बदला."</string>
<string name="puk2_requested" msgid="6992374450720307514">"पासवर्ड चुकीचा आहे. सिम आता लॉक केले आहे. PUK2 प्रविष्ट करा."</string>
- <string name="puk2_blocked" msgid="3131139031779319911">"PUK2 कायमचे अवरोधित केले आहे."</string>
+ <string name="puk2_blocked" msgid="3131139031779319911">"PUK2 कायमचे ब्लॉक केले आहे."</string>
<string name="pin2_attempts" msgid="5625178102026453023">\n"आपल्याकडे <xliff:g id="NUMBER">%d</xliff:g> शिल्लक प्रयत्न आहेत."</string>
<string name="puk2_locked" msgid="6497760825455461057">"PUK2 द्वारे लॉक केले आहे. ते अनलॉक करण्यासाठी सेवा पुरवठादाराशी संपर्क साधा."</string>
- <string name="pin2_unblocked" msgid="4481107908727789303">"पिन2 अवरोधित केला नाही"</string>
+ <string name="pin2_unblocked" msgid="4481107908727789303">"पिन2 ब्लॉक केला नाही"</string>
<string name="pin2_error_exception" msgid="8116103864600823641">"नेटवर्क किंवा सिम कार्ड एरर"</string>
<string name="doneButton" msgid="7371209609238460207">"पूर्ण झाले"</string>
<string name="voicemail_settings_number_label" msgid="1265118640154688162">"व्हॉइसमेल नंबर"</string>
@@ -545,7 +545,7 @@
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"कॉल करण्यासाठी, एक वैध नंबर एंटर करा."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"कॉल अयशस्वी झाला."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"या वेळी कॉल जोडू शकत नाही. तुम्ही मेसेज पाठवून संपर्क करण्याचा प्रयत्न करू शकता."</string>
- <string name="incall_error_supp_service_unknown" msgid="8751177117194592623">"सेवा समर्थित नाही"</string>
+ <string name="incall_error_supp_service_unknown" msgid="8751177117194592623">"सेवेला सपोर्ट नाही"</string>
<string name="incall_error_supp_service_switch" msgid="5272822448189448479">"कॉल स्विच करू शकत नाही."</string>
<string name="incall_error_supp_service_resume" msgid="1276861499306817035">"कॉल पुन्हा सुरू करू शकत नाही."</string>
<string name="incall_error_supp_service_separate" msgid="8932660028965274353">"कॉल विभक्त करू शकत नाही."</string>
@@ -655,7 +655,7 @@
<string name="contactPhoto" msgid="7885089213135154834">"संपर्क फोटो"</string>
<string name="goPrivate" msgid="4645108311382209551">"खाजगी जा"</string>
<string name="selectContact" msgid="1527612842599767382">"संपर्क निवडा"</string>
- <string name="not_voice_capable" msgid="2819996734252084253">"व्हॉइस कॉलिंंग समर्थित नाही"</string>
+ <string name="not_voice_capable" msgid="2819996734252084253">"व्हॉइस कॉलिंंग याला सपोर्ट नाही"</string>
<string name="description_dial_button" msgid="8614631902795087259">"डायल करा"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"डायलपॅड दाखवा"</string>
<string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"आणीबाणी डायलपॅड"</string>
@@ -801,8 +801,8 @@
<string name="supp_service_notification_call_waiting" msgid="4577403881609445324">"कॉल प्रतीक्षेत आहे."</string>
<string name="supp_service_clir_suppression_rejected" msgid="6105737020194776121">"क्रमांक ब्लॉक करणे रद्द केले."</string>
<string name="supp_service_closed_user_group_call" msgid="2811636666505250689">"बंद वापरकर्ता गट कॉल."</string>
- <string name="supp_service_incoming_calls_barred" msgid="2034627421274447674">"इनकमिंग कॉल अवरोधित केले."</string>
- <string name="supp_service_outgoing_calls_barred" msgid="5205725332394087112">"जाणारे कॉल अवरोधित केले."</string>
+ <string name="supp_service_incoming_calls_barred" msgid="2034627421274447674">"इनकमिंग कॉल ब्लॉक केले."</string>
+ <string name="supp_service_outgoing_calls_barred" msgid="5205725332394087112">"आउटगोइंग कॉल ब्लॉक केले."</string>
<string name="supp_service_call_forwarding_active" msgid="7910162960395132464">"कॉल फॉरवर्ड होत आहे."</string>
<string name="supp_service_additional_call_forwarded" msgid="8772753260008398632">"अतिरिक्त कॉल फॉरवर्ड केला."</string>
<string name="supp_service_additional_ect_connected" msgid="8525934162945220237">"भडक कॉल ट्रान्सफर करणे पूर्ण झाले."</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"ही सेटिंग बदलण्यासाठी तुम्ही तुमचे डिव्हाइस रीस्टार्ट करणे आवश्यक आहे."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"रीस्टार्ट करा"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"रद्द करा"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"काढून टाकण्यायोग्य eSIM डीफॉल्ट म्हणून सेट करा"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"मोबाइल रेडिओ पॉवर"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"सेवा बंद आहे सिम्युलेट करा (फक्त डीबगचा बिल्ड)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"सिम ॲड्रेस बुक पहा"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"निश्चित डायलिंग नंबर पहा"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"सर्व्हिस डायलिंग नंबर पहा"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"कनेक्ट केले"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"निलंबित केले"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"अज्ञात"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"प्राथमिक"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"बाइट"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"फोनची माहिती"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"वाहक सुविधा माहिती"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"वाहक सुविधा ट्रिगर करा"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC अधिकार आयडी:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"अपडेट करा"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"रिफ्रेश करा"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"तुमचा ब्लूटूथ सिग्नल कमकुवत आहे. स्पीकरफोनवर स्विच करून पहा."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"कॉल गुणवत्ता सूचना"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"कालबाह्य झालेली SIP खाती"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"या प्रोफाइलवरून मेसेज पाठवू शकत नाही"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"तुमचे कामाशी संबंधित धोरण हे तुम्हाला फक्त तुमच्या कार्य प्रोफाइलवरून मेसेज पाठवण्याची अनुमती देते"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"रद्द करा"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"कार्य प्रोफाइलवर स्विच करा"</string>
</resources>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 8dda074..75e93a6 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Anda perlu memulakan semula peranti untuk menukar tetapan ini."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Mulakan semula"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Batal"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Tetapkan eSIM Boleh Tanggal sebagai Lalai"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Kuasa Radio Mudah Alih"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulasi Rosak (Binaan Penyahpepijatan sahaja)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Lihat Buku Alamat SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Lihat Nombor Dailan Tetap"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Lihat Nombor Dailan Perkhidmatan"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Disambungkan"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Digantung"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Tidak diketahui"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Utama"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"bgksn"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bait"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Maklumat telefon"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Maklumat Peruntukan Pembawa"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Cetus Peruntukan Pembawa"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID Kelayakan WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Kemas kini"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Muat semula"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Isyarat bluetooth anda lemah. Cuba beralih kepada fon pembesar suara."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Pemberitahuan Kualiti Panggilan"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Akaun SIP ditamatkan"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Tidak dapat menghantar mesej daripada profil ini"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Dasar kerja anda membenarkan anda menghantar mesej hanya daripada profil kerja"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Batal"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Beralih kepada profil kerja"</string>
</resources>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index d910d15..7f45ddc 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -631,7 +631,7 @@
<string name="ota_spc_failure" msgid="904092035241370080">"အလွန်အကျွံ SPC မအောင်မြင်မှုများ"</string>
<string name="ota_call_end" msgid="8657746378290737034">"နောက်သို့"</string>
<string name="ota_try_again" msgid="6914781945599998550">"ပြန်ကြိုးစားပါ"</string>
- <string name="ota_next" msgid="2041016619313475914">"ရှေ့ဆက်သွားရန်"</string>
+ <string name="ota_next" msgid="2041016619313475914">"ရှေ့သို့"</string>
<string name="ecm_exit_dialog" msgid="4200691880721429078">"EcmExitDialog"</string>
<string name="phone_entered_ecm_text" msgid="8431238297843035842">"အရေးပေါ်ပြန်လည်ခေါ်ဆိုမှုအား ရိုက်သွင်းပြီး"</string>
<string name="phone_in_ecm_notification_title" msgid="6825016389926367946">"အရေးပေါ်ပြန်လည်ခေါ်ဆိုမှု"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"ဤဆက်တင်ကိုပြောင်းရန် သင့်စက်ကို ပြန်စတင်ရပါမည်။"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ပြန်စရန်"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"မလုပ်တော့ပါ"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"ဖယ်ရှားနိုင်သော eSIM ကို မူရင်းအဖြစ် သတ်မှတ်ရန်"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"မိုဘိုင်း ရေဒီယိုစွမ်းအား"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"အသွင်တူပြုလုပ်သောစက် အလုပ်မလုပ်ပါ (အမှားရှာပြင်ခြင်းသာလျှင်)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM ထဲရှိ လိပ်စာ စာအုပ်ကိုကြည့်ပါ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ခေါ်ဆိုရန် ကန့်သတ် နံပါတ်ကို ကြည့်မည်"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ခေါ်ဆိုသည့်ဝန်ဆောင်မှုနံပါတ်အားကြည့်မည်"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"ချိတ်ဆက်ထားသည်"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"ဆိုင်းငံ့ထားသည်"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"မသိရသေးပါ"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"အဓိက"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ဘိုက်"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ဖုန်းအချက်အလက်"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"ဝန်ဆောင်မှုပေးသူက ပေးထားသည့် အချက်အလက်များ"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"အစပျိုးပေးသော ဖုန်းကုမ္ပဏီ ပံ့ပိုးမှု"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC ခံစားခွင့် ID-"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"အပ်ဒိတ်လုပ်ရန်"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ပြန်လည်စတင်ရန်"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"သင်၏ ဘလူးတုသ်လိုင်းဆွဲအား မကောင်းပါ။ စပီကာဖုန်းသို့ ပြောင်းကြည့်ပါ။"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"ခေါ်ဆိုမှုအရည်အသွေး အကြောင်းကြားချက်"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"ရပ်ဆိုင်းထားသော SIP အကောင့်များ"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ဤပရိုဖိုင်မှ မက်ဆေ့ဂျ်ပို့၍ မရပါ"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"သင့်အလုပ်ခွင်မူဝါဒသည် အလုပ်ပရိုဖိုင်မှသာ မက်ဆေ့ဂျ်ပို့ခွင့်ပြုသည်"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"မလုပ်တော့"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"အလုပ်ပရိုဖိုင်သို့ ပြောင်းရန်"</string>
</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index 256ce0e..d60ed3b 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -75,7 +75,7 @@
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Konfigurer kontoinnstillingene"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"Alle ringekontoer"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Velg hvilke kontoer som kan ringe"</string>
- <string name="wifi_calling" msgid="3650509202851355742">"Wi-Fi-anrop"</string>
+ <string name="wifi_calling" msgid="3650509202851355742">"Wifi-anrop"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Innebygd tilkoblingstjeneste"</string>
<string name="voicemail" msgid="7697769412804195032">"Talepostkasse"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Talepostkasse (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
@@ -309,7 +309,7 @@
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Du må velge en SIM-innstilling"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"Endre SIM-kort for databruk?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Vil du bruke <xliff:g id="NEW_SIM">%1$s</xliff:g> i stedet for <xliff:g id="OLD_SIM">%2$s</xliff:g> for mobildata?"</string>
- <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Wi-Fi-anrop"</string>
+ <string name="wifi_calling_settings_title" msgid="5800018845662016507">"Wifi-anrop"</string>
<string name="video_calling_settings_title" msgid="342829454913266078">"Videoanrop via mobiloperatør"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"GSM/UMTS-innstillinger"</string>
<string name="cdma_options" msgid="3669592472226145665">"CDMA-innstillinger"</string>
@@ -537,7 +537,7 @@
<string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Slå på mobilnettverket, slå av flymodus eller slå av batterisparingsmodus for å ringe ut."</string>
<string name="incall_error_power_off" product="default" msgid="8131672264311208673">"Slå av flymodus for å ringe."</string>
<string name="incall_error_power_off_wfc" msgid="9125661184694727052">"Slå av flymodus eller koble til et trådløst nettverk for å ringe."</string>
- <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"Telefonen er for varm"</b>\n\n"Kan ikke fullføre dette anropet. Prøv igjen når telefonen har kjølt seg ned.\n\nDu kan fortsatt foreta nødanrop."</string>
+ <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"Telefonen er for varm"</b>\n\n"Kan ikke fullføre dette anropet. Prøv på nytt når telefonen har kjølt seg ned.\n\nDu kan fortsatt foreta nødanrop."</string>
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Avslutt modusen for nødanrop for å gjøre et vanlig anrop."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ikke registrert på nettverket."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilnettverket er ikke tilgjengelig."</string>
@@ -555,7 +555,7 @@
<string name="incall_error_supp_service_hangup" msgid="836524952243836735">"Kan ikke frigjøre samtale(r)."</string>
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Kan ikke sette samtaler på vent."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Koble til et trådløst nettverk for å ringe."</string>
- <string name="incall_error_promote_wfc" msgid="9164896813931363415">"Slå på telefonanrop via Wi-Fi for å ringe."</string>
+ <string name="incall_error_promote_wfc" msgid="9164896813931363415">"Slå på telefonanrop via Wifi for å ringe."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Nødinformasjon"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Eier"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Trykk på nytt for å se informasjon"</string>
@@ -630,7 +630,7 @@
<string name="ota_unsuccessful" msgid="8531037653803955754">"Telefonen ble ikke aktivert.\nPrøv å finne et område med bedre dekning (ved et vindu eller utendørs).\n\nPrøv på nytt, eller ring kundetjenesten for å få flere alternativer."</string>
<string name="ota_spc_failure" msgid="904092035241370080">"Omfattende SPC-feil"</string>
<string name="ota_call_end" msgid="8657746378290737034">"Tilbake"</string>
- <string name="ota_try_again" msgid="6914781945599998550">"Prøv igjen"</string>
+ <string name="ota_try_again" msgid="6914781945599998550">"Prøv på nytt"</string>
<string name="ota_next" msgid="2041016619313475914">"Neste"</string>
<string name="ecm_exit_dialog" msgid="4200691880721429078">"EcmExitDialog"</string>
<string name="phone_entered_ecm_text" msgid="8431238297843035842">"Startet modusen nødsamtale-tilbakeringing"</string>
@@ -672,17 +672,17 @@
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"Kun nødanrop"</string>
<string name="sim_description_default" msgid="7474671114363724971">"SIM-kort, spor: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"Tilgjengelighet"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Wi-Fi-anrop fra"</string>
- <string name="status_hint_label_wifi_call" msgid="942993035689809853">"Oppringing via Wi-Fi"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Wifi-anrop fra"</string>
+ <string name="status_hint_label_wifi_call" msgid="942993035689809853">"Oppringing via Wifi"</string>
<string name="message_decode_error" msgid="1061856591500290887">"Det oppsto en feil under dekoding av meldingen."</string>
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"Et SIM-kort har aktivert tjenesten din og oppdatert roamingfunksjonene for telefonen din."</string>
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Du har for mange aktive samtaler. Avslutt eller slå sammen eksisterende samtaler før du starter en ny samtale."</string>
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Kunne ikke koble til. Sett inn et gyldig SIM-kort."</string>
- <string name="callFailed_wifi_lost" msgid="1788036730589163141">"Samtalen ble avsluttet fordi Wi-Fi-forbindelsen ble brutt."</string>
+ <string name="callFailed_wifi_lost" msgid="1788036730589163141">"Samtalen ble avsluttet fordi Wifi-forbindelsen ble brutt."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"Kan ikke utføre videoanropet på grunn av lite batteristrøm."</string>
<string name="callFailed_low_battery" msgid="4056828320214416182">"Videosamtalen ble avsluttet på grunn av lite batteristrøm."</string>
- <string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Nødanrop via Wi-Fi-anrop er ikke tilgjengelig på dette stedet."</string>
- <string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Wi-Fi-anrop er ikke tilgjengelige på dette stedet."</string>
+ <string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Nødanrop via wifi-anrop er ikke tilgjengelig på dette stedet."</string>
+ <string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Wifi-anrop er ikke tilgjengelige på dette stedet."</string>
<string name="change_pin_title" msgid="3564254326626797321">"Endre PIN-kode for talemeldinger"</string>
<string name="change_pin_continue_label" msgid="5177011752453506371">"Fortsett"</string>
<string name="change_pin_cancel_label" msgid="2301711566758827936">"Avbryt"</string>
@@ -827,7 +827,7 @@
<string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Slå av datatilkobling"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"VoLTE-tildelt"</string>
<string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Identitetshåndtering aktiv for videoanrop"</string>
- <string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Identitetshåndtering aktiv for Wi-Fi-anrop"</string>
+ <string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Identitetshåndtering aktiv for wifi-anrop"</string>
<string name="eab_provisioned_switch_string" msgid="4449676720736033035">"EAB/Presence er klargjort"</string>
<string name="cbrs_data_switch_string" msgid="6060356430838077653">"CBRS-data"</string>
<string name="dsds_switch_string" msgid="7564769822086764796">"Slå på DSDS"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Du må starte enheten din på nytt for å endre innstillingen."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Start på nytt"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Avbryt"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Angi flyttbart e-SIM-kort som standard"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Strømforsyning for mobilradio"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Ute av drift-simulering (bare for feilsøkingsversjoner)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Se adressebok for SIM-kort"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Vis forhåndsbestemte numre"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Vis tjenestenumre"</string>
@@ -845,7 +847,7 @@
<string name="radio_info_ims_reg_status_not_registered" msgid="8045821447288876085">"Ikke registrert"</string>
<string name="radio_info_ims_feature_status_available" msgid="6493200914756969292">"Tilgjengelig"</string>
<string name="radio_info_ims_feature_status_unavailable" msgid="8930391136839759778">"Utilgjengelig"</string>
- <string name="radio_info_ims_reg_status" msgid="25582845222446390">"IMS-registrering: <xliff:g id="STATUS">%1$s</xliff:g>\nTale over LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nTale over Wi-Fi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nVideoanrop: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT-grensesnitt: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
+ <string name="radio_info_ims_reg_status" msgid="25582845222446390">"IMS-registrering: <xliff:g id="STATUS">%1$s</xliff:g>\nTale over LTE: <xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nTale over Wifi: <xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\nVideoanrop: <xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT-grensesnitt: <xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"Fungerer som normalt"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"Ute av drift"</string>
<string name="radioInfo_service_emergency" msgid="4763879891415016848">"Bare nødanrop"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Tilkoblet"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Sperret midlertidig"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Ukjent"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primær"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pakker"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"byte"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefoninformasjon"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informasjon om operatørhåndtering"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Utløs operatørhåndtering"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC-rettighets-ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Oppdater"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Last inn på nytt"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth-signalet er svakt. Prøv å bytte til høyttaleren."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Varsel om anropskvalitet"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Avviklede SIP-kontoer"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Kan ikke sende meldingen fra denne profilen"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"I henhold til jobbreglene dine kan du bare sende meldinger fra jobbprofilen"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Avbryt"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Bytt til jobbprofilen"</string>
</resources>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index e08713b..0e3e439 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"यो सेटिङ परिवर्तन गर्न तपाईंले आफ्नो यन्त्र पुनः सुरु गर्नु पर्छ।"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"पुनः सुरु गर्नुहोस्"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"रद्द गर्नुहोस्"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"हटाउन मिल्ने eSIM डिफल्ट रूपमा सेट गर्नुहोस्"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"मोबाइल रेडियोको पावर"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\"सेवा उपलब्ध छैन\" सिमुलेट गर्नुहोस् (डिबग बिल्डमा मात्र सिमुलेट गर्न मिल्छ)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM को ठेगाना पुस्तिका हेर्नुहोस्"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"स्थिर डायल गर्ने नम्बरहरू हेर्नुहोस्"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"सेवामा डायल गर्ने नम्बरहरू हेर्नुहोस्"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"जडान गरियो"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"निलम्बित"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"अज्ञात"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"प्राथमिक"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"बाइटहरू"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"फोनसम्बन्धी जानकारी"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"सेवा प्रदायकको प्रावधानसम्बन्धी जानकारी"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"सेवा प्रदायकको प्रावधानलाई ट्रिगर गर्नुहोस्"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"अपडेट गर्नुहोस्"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"रिफ्रेस गर्नुहोस्"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"ब्लुटुथको सिग्नल कमजोर छ। स्पिकरफोन प्रयोग गरी हेर्नुहोस्।"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"कलको गुणस्तरसम्बन्धी सूचना"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"चल्तीबाट हटाइएका SIP खाताहरू"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"यो प्रोफाइलबाट म्यासेज पठाउन सकिँदैन"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"तपाईंको कामसम्बन्धी नीतिअनुसार कार्य प्रोफाइलबाट मात्र म्यासेज पठाउन सकिन्छ"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"रद्द गर्नुहोस्"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"कार्य प्रोफाइल प्रयोग गर्नुहोस्"</string>
</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index 459ecc4..bece75e 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Start het apparaat opnieuw op om de instelling te wijzigen."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Opnieuw opstarten"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Annuleren"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Verwisselbare e-simkaart instellen als standaard"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobiel radiovermogen"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\'Niet in gebruik\' simuleren (alleen in foutopsporingsbuild)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Adresboek op simkaart bekijken"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Vaste nummers bekijken"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Servicenummers bekijken"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Verbonden"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Opgeschort"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Onbekend"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primair"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pakketten"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,15 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefooninformatie"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Gegevens voor providerregistratie"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Providerregistratie activeren"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC-toegangsrecht-ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Updaten"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Vernieuwen"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Het bluetooth-signaal is zwak. Schakel over naar bellen op luidspreker."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Melding over gesprekskwaliteit"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Beëindigde SIP-accounts"</string>
+ <!-- no translation found for send_from_work_profile_title (9201528838448432473) -->
+ <skip />
+ <!-- no translation found for send_from_work_profile_description (5002701841936861636) -->
+ <skip />
+ <!-- no translation found for send_from_work_profile_cancel (177746511030381711) -->
+ <skip />
+ <!-- no translation found for send_from_work_profile_action_str (6892775562934243337) -->
+ <skip />
</resources>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 57790ab..4dfd1b0 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -30,7 +30,7 @@
<string name="mmiStarted" msgid="9212975136944568623">"MMI କୋଡ୍କୁ ଆରମ୍ଭ କରାଯାଇଛି"</string>
<string name="ussdRunning" msgid="1163586813106772717">"USSD କୋଡ୍ ରନ୍ କରୁଛି…"</string>
<string name="mmiCancelled" msgid="5339191899200678272">"MMI କୋଡ୍କୁ ବାତିଲ୍ କରାଯାଇଛି"</string>
- <string name="cancel" msgid="8984206397635155197">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="cancel" msgid="8984206397635155197">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="enter_input" msgid="6193628663039958990">"USSD ମେସେଜ୍ ନିଶ୍ଚିତରୂପେ <xliff:g id="MIN_LEN">%1$d</xliff:g> ଓ <xliff:g id="MAX_LEN">%2$d</xliff:g>ଟି ଅକ୍ଷର ମଧ୍ୟରେ ରହିବ। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="manageConferenceLabel" msgid="8415044818156353233">"କନଫରେନ୍ସ କଲ୍କୁ ପରିଚାଳନା କରନ୍ତୁ"</string>
<string name="ok" msgid="7818974223666140165">"ଠିକ୍ ଅଛି"</string>
@@ -47,7 +47,7 @@
<string name="no_vm_number" msgid="6623853880546176930">"ହଜିଯାଇଥିବା ଭଏସମେଲ୍ ନମ୍ବର୍"</string>
<string name="no_vm_number_msg" msgid="5165161462411372504">"SIM କାର୍ଡରେ କୌଣସି ଭଏସମେଲ୍ ନମ୍ବର୍ ଷ୍ଟୋର୍ କରାଯାଇନାହିଁ।"</string>
<string name="add_vm_number_str" msgid="7368168964435881637">"ନମ୍ବର୍ ଯୋଡ଼ନ୍ତୁ"</string>
- <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"ଭଏସମେଲ ସେଟିଂସକୁ ପ୍ରାଥମିକ ଉପଯୋଗକର୍ତ୍ତା କେବଳ ପରିବର୍ତ୍ତିତ କରିପାରିବେ।"</string>
+ <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"ଭଏସମେଲ ସେଟିଂସକୁ କେବଳ ପ୍ରାଥମିକ ୟୁଜର ପରିବର୍ତ୍ତନ କରିପାରିବେ।"</string>
<string name="puk_unlocked" msgid="4627340655215746511">"ଆପଣଙ୍କର SIM କାର୍ଡକୁ ଅବରୋଧ କରିଦିଆଯାଇଛି। ଆପଣଙ୍କର ଫୋନ୍ ଅନଲକ୍ ହେଉଛି…"</string>
<string name="label_ndp" msgid="7617392683877410341">"SIM ନେଟ୍ୱର୍କକୁ ଅନଲକ୍ କରିବା ପାଇଁ PIN"</string>
<string name="label_phoneid" msgid="8775611434123577808">"ଅପରେଟର୍ ପାଇଁ SIM ଲକ୍ କରାଯାଇଛି"</string>
@@ -56,7 +56,7 @@
<string name="requesting_unlock" msgid="930512210309437741">"ନେଟ୍ୱର୍କକୁ ଅନଲକ୍ କରିବା ପାଇଁ ଅନୁରୋଧ କରାଯାଉଛି…"</string>
<string name="unlock_failed" msgid="7103543844840661366">"ନେଟ୍ୱର୍କ ଅନଲକ୍ କରିବା ପାଇଁ ଅନୁରୋଧ ବିଫଳ ହୋଇଛି।"</string>
<string name="unlock_success" msgid="32681089371067565">"ନେଟ୍ୱର୍କ ଅନଲକ୍ କରିବା ସଫଳ ହେଲା।"</string>
- <string name="mobile_network_settings_not_available" msgid="8678168497517090039">"ଏହି ୟୁଜରଙ୍କ ପାଇଁ ମୋବାଇଲ୍ ନେଟ୍ୱର୍କ ସେଟିଙ୍ଗ ଉପଲବ୍ଧ ନାହିଁ"</string>
+ <string name="mobile_network_settings_not_available" msgid="8678168497517090039">"ଏହି ୟୁଜରଙ୍କ ପାଇଁ ମୋବାଇଲ ନେଟୱାର୍କ ସେଟିଂସ ଉପଲବ୍ଧ ନାହିଁ"</string>
<string name="labelGSMMore" msgid="7354182269461281543">"GSM କଲ ସେଟିଂସ"</string>
<string name="labelGsmMore_with_label" msgid="3206015314393246224">"GSM କଲ ସେଟିଂସ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCDMAMore" msgid="7937441382611224632">"CDMA କଲ୍ ସେଟିଙ୍ଗ"</string>
@@ -128,11 +128,11 @@
<string name="cdma_call_waiting" msgid="4565070960879673216">"\'କଲ୍ ୱେଟିଂ\' ସୁବିଧା ଚାଲୁ କରିବେ?"</string>
<string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"କଲ୍ ସମୟରେ, ଇନକମିଂ କଲଗୁଡ଼ିକ ବିଷୟରେ ଆପଣଙ୍କୁ ସୂଚିତ କରାଯିବ"</string>
<string name="enable_cdma_cw" msgid="811047045863422232">"ଚାଲୁ କରନ୍ତୁ"</string>
- <string name="disable_cdma_cw" msgid="7119290446496301734">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="disable_cdma_cw" msgid="7119290446496301734">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMSରେ CDMA \'କଲ୍ ୱେଟିଂ\' ସୁବିଧା ଚାଲୁ ଅଛି"</string>
<string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMSରେ CDMA \'କଲ୍ ୱେଟିଂ\' ସୁବିଧା ବନ୍ଦ ଅଛି"</string>
<string name="updating_title" msgid="6130548922615719689">"କଲ ସେଟିଂସ"</string>
- <string name="call_settings_admin_user_only" msgid="7238947387649986286">"କଲ୍ ସେଟିଙ୍ଗକୁ କେବଳ ଆଡମିନ୍ ୟୁଜର୍ ବଦଳାଇପାରିବେ।"</string>
+ <string name="call_settings_admin_user_only" msgid="7238947387649986286">"କଲ ସେଟିଂସକୁ କେବଳ ଆଡମିନ ୟୁଜର ବଦଳାଇପାରିବେ।"</string>
<string name="call_settings_with_label" msgid="8460230435361579511">"ସେଟିଙ୍ଗ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="error_updating_title" msgid="2024290892676808965">"କଲ୍ ସେଟିଙ୍ଗରେ ତ୍ରୁଟି"</string>
<string name="reading_settings" msgid="1605904432450871183">"ସେଟିଂସକୁ ପଢ଼ାଯାଉଛି…"</string>
@@ -156,8 +156,8 @@
<item msgid="9150034130629852635">"ସଂଖ୍ୟାକୁ ଦେଖାନ୍ତୁ"</item>
</string-array>
<string name="vm_changed" msgid="4739599044379692505">"ଭଏସମେଲ୍ ନମ୍ବର୍ ବଦଳିଗଲା।"</string>
- <string name="vm_change_failed" msgid="7877733929455763566">"ଭଏସମେଲ୍ ନମ୍ବର୍ ବଦଳାଯାଇପାରିଲା ନାହିଁ। \nଯଦି ଏହି ସମସ୍ୟା ଜାରିରୁହେ ତେବେ ନିଜର କେରିଅର୍ଙ୍କ ସହ ସମ୍ପର୍କ କରନ୍ତୁ।"</string>
- <string name="fw_change_failed" msgid="9179241823460192148">"ଫଏୱାର୍ଡିଙ୍ଗ ନମ୍ବର୍କୁ ବଦଳାଇହେଲା ନାହିଁ। \n ଯଦି ଏହି ସମସ୍ୟା ଜାରିରୁହେ ତେବେ ନିଜର କେରିଅର୍ଙ୍କ ସହ ସମ୍ପର୍କ କରନ୍ତୁ।"</string>
+ <string name="vm_change_failed" msgid="7877733929455763566">"ଭଏସମେଲ ନମ୍ବର ବଦଳାଯାଇପାରିଲା ନାହିଁ। \nଯଦି ଏହି ସମସ୍ୟା ଜାରି ରୁହେ ତେବେ ନିଜର କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
+ <string name="fw_change_failed" msgid="9179241823460192148">"ଫରୱାର୍ଡିଙ୍ଗ ନମ୍ବରକୁ ବଦଳାଯାଇପାରିଲା ନାହିଁ। \n ଯଦି ଏହି ସମସ୍ୟା ଜାରି ରୁହେ ତେବେ ନିଜର କ୍ଯାରିଅରଙ୍କ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="fw_get_in_vm_failed" msgid="2432678237218183844">"ବର୍ତ୍ତମାନର ଫରୱାର୍ଡିଂ ନମ୍ବର ସେଟିଂସକୁ ପୁନରୁଦ୍ଧାର ଓ ସେଭ କରାଯାଇପାରିଲା ନାହିଁ। \nନୂଆ ପ୍ରଦାନକାରୀକୁ ଯେ କୌଣସି ମତେ ସ୍ଵିଚ କରିବେ?"</string>
<string name="no_change" msgid="3737264882821031892">"କୌଣସି ପରିବର୍ତ୍ତନ କରାଯାଇନାହିଁ|"</string>
<string name="sum_voicemail_choose_provider" msgid="6750824719081403773">"ଭଏସ୍ମେଲ୍ ସେବାକୁ ଚୟନ କରନ୍ତୁ"</string>
@@ -419,7 +419,7 @@
<string name="cdma_system_select_summary" msgid="3840420390242060407">"CDMAର ରୋମିଙ୍ଗ ମୋଡ୍କୁ ବଦଳାନ୍ତୁ"</string>
<string name="cdma_system_select_dialogtitle" msgid="5524639510676501802">"ସିଷ୍ଟମ୍ ଚୟନ କରନ୍ତୁ"</string>
<string-array name="cdma_system_select_choices">
- <item msgid="462340042928284921">"କେବଳ ହୋମ୍"</item>
+ <item msgid="462340042928284921">"କେବଳ ହୋମ"</item>
<item msgid="6058010046783562674">"ସ୍ଵଚାଳିତ"</item>
</string-array>
<string name="cdma_subscription_title" msgid="3449527179325589434">"CDMA ସବସ୍କ୍ରିପଶନ୍"</string>
@@ -458,10 +458,10 @@
<string name="auto_retry_mode_title" msgid="2985801935424422340">"ଅଟୋ-ରିଟ୍ରାଏ କରନ୍ତୁ"</string>
<string name="auto_retry_mode_summary" msgid="2863919925349511402">"ଅଟୋ-ରିଟ୍ରାଏ ମୋଡ୍କୁ ସକ୍ଷମ କରନ୍ତୁ"</string>
<string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"ଭିଡିଓ କଲ୍ କରିବା ସମୟରେ TTY ମୋଡ୍କୁ ପରିବର୍ତ୍ତନ କରିବା ପାଇଁ ଅନୁମତି ନାହିଁ"</string>
- <string name="menu_add" msgid="5616487894975773141">"ଯୋଗାଯୋଗକୁ ଯୋଡ଼ନ୍ତୁ"</string>
- <string name="menu_edit" msgid="3593856941552460706">"ଯୋଗାଯୋଗକୁ ଏଡିଟ୍ କରନ୍ତୁ"</string>
- <string name="menu_delete" msgid="6326861853830546488">"ଯୋଗାଯୋଗକୁ ଡିଲିଟ୍ କରନ୍ତୁ"</string>
- <string name="menu_dial" msgid="4178537318419450012">"ଯୋଗାଯୋଗକୁ ଡାଏଲ୍ କରନ୍ତୁ"</string>
+ <string name="menu_add" msgid="5616487894975773141">"କଣ୍ଟାକ୍ଟ ଯୋଗ କରନ୍ତୁ"</string>
+ <string name="menu_edit" msgid="3593856941552460706">"କଣ୍ଟାକ୍ଟ ଏଡିଟ କରନ୍ତୁ"</string>
+ <string name="menu_delete" msgid="6326861853830546488">"କଣ୍ଟାକ୍ଟ ଡିଲିଟ କରନ୍ତୁ"</string>
+ <string name="menu_dial" msgid="4178537318419450012">"କଣ୍ଟାକ୍ଟ ଡାଏଲ କରନ୍ତୁ"</string>
<string name="get_pin2" msgid="4221654606863196332">"PIN2 ଟାଇପ୍ କରନ୍ତୁ"</string>
<string name="name" msgid="1347432469852527784">"ନାମ"</string>
<string name="number" msgid="1564053487748491000">"ନମ୍ବର୍"</string>
@@ -469,7 +469,7 @@
<string name="add_fdn_contact" msgid="1169713422306640887">"ଫିକ୍ସଡ୍ ଡାଏଲିଙ୍ଗ ନମ୍ବର୍ ଯୋଡ଼ନ୍ତୁ"</string>
<string name="adding_fdn_contact" msgid="3112531600824361259">"ଫିକ୍ସଡ୍ ଡାଏଲିଙ୍ଗ ନମ୍ବର୍କୁ ଯୋଡ଼ାଯାଉଛି…"</string>
<string name="fdn_contact_added" msgid="2840016151693394596">"ଫିକ୍ସଡ୍ ଡାଏଲିଙ୍ଗ ନମ୍ବର୍ ଯୋଡ଼ାଗଲା।"</string>
- <string name="edit_fdn_contact" msgid="6030829994819587408">"ଫିକ୍ସଡ୍ ଡାଏଲିଙ୍ଗ ନମ୍ବର୍କୁ ଏଡିଟ୍ କରନ୍ତୁ"</string>
+ <string name="edit_fdn_contact" msgid="6030829994819587408">"ଫିକ୍ସଡ ଡାଏଲିଙ୍ଗ ନମ୍ବରକୁ ଏଡିଟ କରନ୍ତୁ"</string>
<string name="updating_fdn_contact" msgid="6989341376868227150">"ଫିକ୍ସଡ୍ ଡାଏଲିଙ୍ଗ ନମ୍ବର୍ ଅପଡେଟ୍ ହେଉଛି…"</string>
<string name="fdn_contact_updated" msgid="6876330243323118937">"ଫିକ୍ସଡ୍ ଡାଏଲିଙ୍ଗ ନମ୍ବର୍ ଅପଡେଟ୍ କରାଗଲା।"</string>
<string name="delete_fdn_contact" msgid="7027405651994507077">"ଫିକ୍ସଡ୍ ଡାଏଲିଙ୍ଗ ନମ୍ବର୍କୁ ଡିଲିଟ୍ କରନ୍ତୁ"</string>
@@ -515,7 +515,7 @@
<string name="puk2_requested" msgid="6992374450720307514">"ଭୁଲ୍ ପାସ୍ୱର୍ଡ। ବର୍ତ୍ତମାନ SIM ଲକ୍ ହୋଇଗଲା। PUK2କୁ ପ୍ରବେଶ କରନ୍ତୁ।"</string>
<string name="puk2_blocked" msgid="3131139031779319911">"PUK2କୁ ସ୍ଥାୟୀରୂପେ ଅବରୋଧ କରାଯାଇଛି।"</string>
<string name="pin2_attempts" msgid="5625178102026453023">\n"ଆପଣଙ୍କର <xliff:g id="NUMBER">%d</xliff:g>ଟି ସୁଯୋଗ ବଳକା ଅଛି।"</string>
- <string name="puk2_locked" msgid="6497760825455461057">"PUK2 ଲକ୍ କରାଯାଇଛି। ଅନଲକ୍ କରିବାକୁ ସେବା ପ୍ରଦାନକାରୀ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="puk2_locked" msgid="6497760825455461057">"PUK2 ଲକ କରାଯାଇଛି। ଅନଲକ କରିବାକୁ ସେବା ପ୍ରଦାନକାରୀ ସହ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="pin2_unblocked" msgid="4481107908727789303">"PIN2କୁ ଆଉ ଅବରୋଧ କରାଯାଇନାହିଁ"</string>
<string name="pin2_error_exception" msgid="8116103864600823641">"ନେଟ୍ୱର୍କ କିମ୍ବା SIM କାର୍ଡ ତ୍ରୁଟି"</string>
<string name="doneButton" msgid="7371209609238460207">"ହୋଇଗଲା"</string>
@@ -590,8 +590,8 @@
<string name="importAllSimEntries" msgid="2628391505643564007">"ସମସ୍ତ ଇମ୍ପୋର୍ଟ କରନ୍ତୁ"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"SIMରେ ଥିବା ଯୋଗାଯୋଗକୁ ଇମ୍ପୋର୍ଟ କରାଯାଉଛି"</string>
<string name="importToFDNfromContacts" msgid="5068664870738407341">"ଯୋଗଯୋଗରୁ ଇମ୍ପୋର୍ଟ କରନ୍ତୁ"</string>
- <string name="singleContactImportedMsg" msgid="3619804066300998934">"ଇମ୍ପୋର୍ଟ କରାଯାଇଥିବା ଯୋଗାଯୋଗ"</string>
- <string name="failedToImportSingleContactMsg" msgid="228095510489830266">"ଯୋଗଯୋଗକୁ ଇମ୍ପୋର୍ଟ କରିବାରେ ବିଫଳ ହେଲା"</string>
+ <string name="singleContactImportedMsg" msgid="3619804066300998934">"ଇମ୍ପୋର୍ଟ କରାଯାଇଥିବା କଣ୍ଟାକ୍ଟ"</string>
+ <string name="failedToImportSingleContactMsg" msgid="228095510489830266">"କଣ୍ଟାକ୍ଟକୁ ଇମ୍ପୋର୍ଟ କରିବାରେ ବିଫଳ ହୋଇଛି"</string>
<string name="hac_mode_title" msgid="4127986689621125468">"ଶ୍ରବଣ ଯନ୍ତ୍ର"</string>
<string name="hac_mode_summary" msgid="7774989500136009881">"ଶ୍ରବଣ ଯନ୍ତ୍ର କମ୍ପ୍ୟାଟିବିଲିଟୀକୁ ଚାଲୁ କରନ୍ତୁ"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"ରିଅଲ୍-ଟାଇମ୍ ଟେକ୍ସଟ୍ (RTT) କଲ୍"</string>
@@ -652,9 +652,9 @@
<string name="voicemail_number_not_set" msgid="8831561283386938155">"<ସେଟ୍ ହୋଇନାହିଁ>"</string>
<string name="other_settings" msgid="8895088007393598447">"ଅନ୍ୟାନ୍ୟ କଲ୍ ସେଟିଙ୍ଗ"</string>
<string name="calling_via_template" msgid="1791323450703751750">"<xliff:g id="PROVIDER_NAME">%s</xliff:g> ମାଧ୍ୟମରେ କଲ୍ କରନ୍ତୁ"</string>
- <string name="contactPhoto" msgid="7885089213135154834">"ଯୋଗାଯୋଗ ଫଟୋ"</string>
+ <string name="contactPhoto" msgid="7885089213135154834">"କଣ୍ଟାକ୍ଟ ଫଟୋ"</string>
<string name="goPrivate" msgid="4645108311382209551">"ବ୍ୟକ୍ତିଗତ ହୁଅନ୍ତୁ"</string>
- <string name="selectContact" msgid="1527612842599767382">"ଯୋଗାଯୋଗକୁ ଚୟନ କରନ୍ତୁ"</string>
+ <string name="selectContact" msgid="1527612842599767382">"କଣ୍ଟାକ୍ଟ ଚୟନ କରନ୍ତୁ"</string>
<string name="not_voice_capable" msgid="2819996734252084253">"ଭଏସ୍ କଲ୍ ସପୋର୍ଟ କରୁନାହିଁ"</string>
<string name="description_dial_button" msgid="8614631902795087259">"ଡାଏଲ୍ କରନ୍ତୁ"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"ଡାୟଲ୍ପ୍ୟାଡ୍ ଦେଖାନ୍ତୁ"</string>
@@ -685,7 +685,7 @@
<string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"ଏହି ଲୋକେସନ୍ରେ ୱାଇ-ଫାଇ କଲିଂ ଉପଲବ୍ଧ ନାହିଁ।"</string>
<string name="change_pin_title" msgid="3564254326626797321">"ଭଏସମେଲ୍ PINକୁ ବଦଳାନ୍ତୁ"</string>
<string name="change_pin_continue_label" msgid="5177011752453506371">"ଜାରି ରଖନ୍ତୁ"</string>
- <string name="change_pin_cancel_label" msgid="2301711566758827936">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="change_pin_cancel_label" msgid="2301711566758827936">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="change_pin_ok_label" msgid="6861082678817785330">"ଠିକ୍ ଅଛି"</string>
<string name="change_pin_enter_old_pin_header" msgid="853151335217594829">"ଆପଣଙ୍କର ପୁରୁଣା PINକୁ ନିଶ୍ଚିତ କରନ୍ତୁ"</string>
<string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"ଜାରି ରଖିବା ପାଇଁ ଆପଣଙ୍କର ଭଏସମେଲ୍ PINକୁ ପ୍ରବେଶ କରନ୍ତୁ।"</string>
@@ -708,7 +708,7 @@
<string name="mobile_data_activate_diag_title" msgid="5401741936224757312">"ଡାଟାକୁ ଯୋଡ଼ିବେ?"</string>
<string name="mobile_data_activate_diag_message" msgid="3527260988020415441">"ଆପଣଙ୍କୁ <xliff:g id="PROVIDER_NAME">%s</xliff:g> ମାଧ୍ୟମରେ ଡାଟା ଯୋଡ଼ିବାକୁ ପଡ଼ିପାରେ"</string>
<string name="mobile_data_activate_button" msgid="1139792516354374612">"ଡାଟା ଯୋଡ଼ନ୍ତୁ"</string>
- <string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"ବାତିଲ କରନ୍ତୁ"</string>
<string name="clh_card_title_call_ended_txt" msgid="5977978317527299698">"କଲ୍ ସମାପ୍ତ ହୋଇଛି"</string>
<string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"ଏୟାରପ୍ଲେନ୍ ମୋଡ୍ ଚାଲୁ ଅଛି"</string>
<string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"SIM କାର୍ଡକୁ ଆକ୍ସେସ୍ କରିହେଉନାହିଁ"</string>
@@ -718,8 +718,8 @@
<string name="clh_callFailed_channel_unacceptable_txt" msgid="4062754579408613021">"କଲ୍ ସମ୍ପୂର୍ଣ୍ଣ କରିହେଲା ନାହିଁ। ତ୍ରୁଟି କୋଡ୍ 6।"</string>
<string name="clh_callFailed_operator_determined_barring_txt" msgid="4202077821465974286">"କଲ୍ ସମ୍ପୂର୍ଣ୍ଣ କରିହେଲା ନାହିଁ। ତ୍ରୁଟି କୋଡ୍ 8।"</string>
<string name="clh_callFailed_normal_call_clearing_txt" msgid="5677987959062976462">"କଲ୍ ସମ୍ପୂର୍ଣ୍ଣ କରିହେଲା ନାହିଁ। ତ୍ରୁଟି କୋଡ୍ 16।"</string>
- <string name="clh_callFailed_user_busy_txt" msgid="8886432858568086854">"ୟୁଜର୍ ବ୍ୟସ୍ତ ଅଛନ୍ତି"</string>
- <string name="clh_callFailed_no_user_responding_txt" msgid="341100226919865128">"ୟୁଜର୍ ଉତ୍ତର ଦେଉନାହାନ୍ତି"</string>
+ <string name="clh_callFailed_user_busy_txt" msgid="8886432858568086854">"ୟୁଜର ବ୍ୟସ୍ତ ଅଛନ୍ତି"</string>
+ <string name="clh_callFailed_no_user_responding_txt" msgid="341100226919865128">"ୟୁଜର ଉତ୍ତର ଦେଉନାହାଁନ୍ତି"</string>
<string name="clh_callFailed_user_alerting_txt" msgid="896082976264427969">"କଲ୍ ସମ୍ପୂର୍ଣ୍ଣ କରିହେଲା ନାହିଁ। ତ୍ରୁଟି କୋଡ୍ 19।"</string>
<string name="clh_callFailed_call_rejected_txt" msgid="3439435671153341709">"କଲ୍କୁ ପ୍ରତ୍ୟାଖ୍ୟାନ କରାଗଲା"</string>
<string name="clh_callFailed_number_changed_txt" msgid="2868476949771441667">"ନମ୍ବର୍ ବଦଳିଯାଇଛି"</string>
@@ -795,12 +795,12 @@
<string name="messageCallBarring" msgid="5537730400652466912">"ପାସ୍ୱର୍ଡ ପ୍ରବେଶ କରନ୍ତୁ"</string>
<string name="call_barring_settings" msgid="4616607285790258919">"କଲ୍ ରୋକିବା ସେଟିଙ୍ଗ"</string>
<string name="callFailed_NetworkBusy" msgid="5437103975842913681">"ନେଟ୍ୱର୍କ ବ୍ୟସ୍ତ ଅଛି। ଦୟାକରି ଆପଣ ପରେ ପୁଣି କଲ୍ ଚେଷ୍ଟା କରିବା ପାଇଁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
- <string name="callFailed_NetworkCongested" msgid="6801283142342775380">"ନେଟ୍ୱର୍କ ବ୍ୟସ୍ତ ଅଛି। ସହାୟତା ପାଇଁ ଆପଣଙ୍କର ମୋବାଇଲ୍ ଅପରେଟର୍ଙ୍କୁ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
+ <string name="callFailed_NetworkCongested" msgid="6801283142342775380">"ନେଟୱାର୍କ ବ୍ୟସ୍ତ ଅଛି। ସହାୟତା ପାଇଁ ଆପଣଙ୍କର ମୋବାଇଲ ଅପରେଟରଙ୍କୁ କଣ୍ଟାକ୍ଟ କରନ୍ତୁ।"</string>
<string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"କଲ୍ ଅନ୍ୟ ପାଖକୁ ଯିବା ବଦଳରେ ନିଜ ପାଖକୁ ଆସିଯାଇଛି।"</string>
<string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"କଲ୍କୁ ଫରୱାର୍ଡ କରାଯାଇଛି।"</string>
<string name="supp_service_notification_call_waiting" msgid="4577403881609445324">"କଲ୍ ଅପେକ୍ଷାରେ ଅଛି।"</string>
<string name="supp_service_clir_suppression_rejected" msgid="6105737020194776121">"ନମ୍ବର୍ ଅବରୋଧକୁ ପ୍ରତ୍ୟାଖ୍ୟାନ କରାଗଲା।"</string>
- <string name="supp_service_closed_user_group_call" msgid="2811636666505250689">"ନିକଟତମ ୟୁଜର୍ ଗ୍ରୁପ୍ ଦ୍ଵାରା କଲ୍ରେ ସୀମିତ।"</string>
+ <string name="supp_service_closed_user_group_call" msgid="2811636666505250689">"ନିକଟତମ ୟୁଜର ଗ୍ରୁପ କଲ।"</string>
<string name="supp_service_incoming_calls_barred" msgid="2034627421274447674">"ଇନକମିଙ୍ଗ କଲ୍କୁ ରୋକାଯାଇଛି।"</string>
<string name="supp_service_outgoing_calls_barred" msgid="5205725332394087112">"ଆଉଟ୍ଗୋଇଙ୍ଗ କଲ୍କୁ ରୋକାଯାଇଛି।"</string>
<string name="supp_service_call_forwarding_active" msgid="7910162960395132464">"କଲ୍ ଫରୱାର୍ଡିଙ୍ଗ ସକ୍ରିୟ ଅଛି।"</string>
@@ -834,8 +834,10 @@
<string name="dsds_dialog_title" msgid="8494569893941847575">"ଡିଭାଇସ୍ ରିଷ୍ଟାର୍ଟ କରିବେ?"</string>
<string name="dsds_dialog_message" msgid="4047480385678538850">"ଏହି ସେଟିଂ ବଦଳାଇବାକୁ ଆପଣଙ୍କୁ ଆପଣଙ୍କର ଡିଭାଇସ୍ ରିଷ୍ଟାର୍ଟ କରିବାକୁ ହେବ।"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ"</string>
- <string name="dsds_dialog_cancel" msgid="3245958947099586655">"ବାତିଲ୍ କରନ୍ତୁ"</string>
+ <string name="dsds_dialog_cancel" msgid="3245958947099586655">"ବାତିଲ କରନ୍ତୁ"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"କାଢ଼ି ହେଉଥିବା eSIMକୁ ଡିଫଲ୍ଟ ଭାବେ ସେଟ କରନ୍ତୁ"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"ମୋବାଇଲ୍ ରେଡିଓ ପାୱାର୍"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\"କାମ କରୁନାହିଁ\"ରେ ସିମୁଲେଟ କରନ୍ତୁ (କେବଳ ଡିବଗ ବିଲ୍ଡ)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ସିମ୍ରେ ଥିବା ଠିକଣା ପୁସ୍ତକ ଦେଖନ୍ତୁ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ସ୍ଥାୟୀ ଡାଏଲିଂ ନମ୍ୱରଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ସର୍ଭିସ୍ ଡାଏଲିଂ ନମ୍ୱରଗୁଡ଼ିକ ଦେଖନ୍ତୁ"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"ସଂଯୋଗ କରାଯାଇଛି"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"ନିଲମ୍ବନ କରାଯାଇଛି"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"ଅଜଣା"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ପ୍ରାଥମିକ"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"ପ୍ୟାକେଟ୍"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ବାଇଟ୍ସ"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ଫୋନ୍ ସୂଚନା"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"ମୋବାଇଲ୍ କମ୍ପାନୀ ପ୍ରାବଧାନ ସୂଚନା"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"କେରିଅର୍ ପ୍ରୋଭିଜନିଂ ଟ୍ରିଗର୍ କରନ୍ତୁ"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC ଏନଟାଇଟେଲମେଣ୍ଟ ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"ଅପଡେଟ କରନ୍ତୁ"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ରିଫ୍ରେସ କରନ୍ତୁ"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"ଆପଣଙ୍କ ବ୍ଲୁଟୁଥ୍ ସିଗନାଲ୍ ଦୁର୍ବଳ ଅଛି। ସ୍ପିକରଫୋନକୁ ସ୍ୱିଚ୍ କରିବା ପାଇଁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"କଲ୍ ଗୁଣବତ୍ତା ବିଜ୍ଞପ୍ତି"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"ଅସମର୍ଥିତ SIP ଆକାଉଣ୍ଟଗୁଡ଼ିକ"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ଏହି ପ୍ରୋଫାଇଲରୁ ମେସେଜ ପଠାଯାଇପାରିବ ନାହିଁ"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"ଆପଣଙ୍କ ୱାର୍କ ନୀତି ଆପଣଙ୍କୁ କେବଳ ୱାର୍କ ପ୍ରୋଫାଇଲରୁ ମେସେଜ ପଠାଇବାକୁ ଅନୁମତି ଦିଏ"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"ବାତିଲ କରନ୍ତୁ"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"ୱାର୍କ ପ୍ରୋଫାଇଲକୁ ସ୍ୱିଚ କରନ୍ତୁ"</string>
</resources>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index f19c231..1e35145 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -596,7 +596,7 @@
<string name="hac_mode_summary" msgid="7774989500136009881">"ਸੁਣਨ ਲਈ ਸਹਾਇਕ ਸਾਧਨ ਅਨੁਕੂਲਤਾ ਚਾਲੂ ਕਰੋ"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"ਨਾਲ-ਦੀ-ਨਾਲ ਦਿਸਦੀ ਲਿਖਤ (RTT) ਵਾਲੀ ਕਾਲ"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"ਕਿਸੇ ਅਵਾਜ਼ੀ ਕਾਲ ਦੌਰਾਨ ਸੁਨੇਹਾ ਭੇਜਣ ਦਿਓ"</string>
- <string name="rtt_mode_more_information" msgid="587500128658756318">"RTT ਅਜਿਹੇ ਕਾਲ ਕਰਨ ਵਾਲੇ ਲੋਕਾਂ ਦੀ ਸਹਾਇਤਾ ਕਰਦਾ ਹੈ ਜੋ ਬੋਲੇ, ਘੱਟ ਸੁਣਨ ਵਾਲੇ, ਬੋਲਣ ਵਿੱਚ ਅਸਮਰਥ ਜਾਂ ਜਿਨ੍ਹਾਂ ਲਈ ਸਿਰਫ਼ ਅਵਾਜ਼ ਕਾਫ਼ੀ ਨਹੀਂ ਹੁੰਦੀ।<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>ਹੋਰ ਜਾਣੋ</a>\n <br><br> - RTT ਕਾਲਾਂ ਨੂੰ ਇੱਕ ਪ੍ਰਤਿਲਿਪੀ ਸੁਨੇਹੇ ਵਜੋਂ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ\n <br> - RTT ਵੀਡੀਓ ਕਾਲਾਂ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
+ <string name="rtt_mode_more_information" msgid="587500128658756318">"RTT ਅਜਿਹੇ ਕਾਲ ਕਰਨ ਵਾਲੇ ਲੋਕਾਂ ਦੀ ਸਹਾਇਤਾ ਕਰਦਾ ਹੈ ਜੋ ਬੋਲੇ, ਘੱਟ ਸੁਣਨ ਵਾਲੇ, ਬੋਲਣ ਵਿੱਚ ਅਸਮਰੱਥ ਜਾਂ ਜਿਨ੍ਹਾਂ ਲਈ ਸਿਰਫ਼ ਅਵਾਜ਼ ਕਾਫ਼ੀ ਨਹੀਂ ਹੁੰਦੀ।<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>ਹੋਰ ਜਾਣੋ</a>\n <br><br> - RTT ਕਾਲਾਂ ਨੂੰ ਇੱਕ ਪ੍ਰਤੀਲਿਪੀਕਰਨ ਸੁਨੇਹੇ ਵਜੋਂ ਰੱਖਿਅਤ ਕੀਤਾ ਜਾਂਦਾ ਹੈ\n <br> - RTT ਵੀਡੀਓ ਕਾਲਾਂ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"ਨੋਟ ਕਥਨ:ਵੇਲੇ RTT ਉਪਲਬਧ ਨਹੀਂ ਹੈ"</string>
<string-array name="tty_mode_entries">
<item msgid="3238070884803849303">"TTY ਬੰਦ"</item>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"ਤੁਹਾਨੂੰ ਇਹ ਸੈਟਿੰਗ ਬਦਲਣ ਲਈ ਡੀਵਾਈਸ ਨੂੰ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਨ ਦੀ ਲੋੜ ਹੈ।"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"ਮੁੜ-ਸ਼ੁਰੂ ਕਰੋ"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"ਰੱਦ ਕਰੋ"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"ਹਟਾਉਣਯੋਗ ਈ-ਸਿਮ ਨੂੰ ਪੂਰਵ-ਨਿਰਧਾਰਿਤ ਵਜੋਂ ਸੈੱਟ ਕਰੋ"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"ਮੋਬਾਈਲ ਰੇਡੀਓ ਪਾਵਰ"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\'ਸੇਵਾ ਵਿੱਚ ਨਹੀਂ\' ਨੂੰ ਸਿਮੂਲੇਟ ਕਰੋ (ਸਿਰਫ਼ ਡੀਬੱਗ ਬਿਲਡ)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ਸਿਮ ਦੀ ਪਤਾ ਬੁੱਕ ਦੇਖੋ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ਫਿਕਸਡ ਡਾਇਲਿੰਗ ਨੰਬਰ ਦੇਖੋ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ਸੇਵਾ ਡਾਇਲਿੰਗ ਨੰਬਰ ਦੇਖੋ"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"ਕਨੈਕਟ ਹੈ"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"ਮੁਅੱਤਲ ਕੀਤਾ ਗਿਆ"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"ਅਗਿਆਤ"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ਪ੍ਰਾਇਮਰੀ"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ਬਾਈਟਾਂ"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ਫ਼ੋਨ ਜਾਣਕਾਰੀ"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"ਕੈਰੀਅਰ ਪ੍ਰੋਵਿਜ਼ਨਿੰਗ ਜਾਣਕਾਰੀ"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ਕੈਰੀਅਰ ਪ੍ਰਵਿਜ਼ਨਿੰਗ ਨੂੰ ਟ੍ਰਿਗਰ ਕਰੋ"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC ਹੱਕਦਾਰੀ ਆਈਡੀ:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"ਅੱਪਡੇਟ ਕਰੋ"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ਰਿਫ੍ਰੈਸ਼ ਕਰੋ"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"ਤੁਹਾਡਾ ਬਲੂਟੁੱਥ ਸਿਗਨਲ ਕਮਜ਼ੋਰ ਹੈ। ਸਪੀਕਰਫ਼ੋਨ \'ਤੇ ਲਿਜਾ ਕੇ ਦੇਖੋ।"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"ਕਾਲ ਦੀ ਕੁਆਲਿਟੀ ਸੰਬੰਧੀ ਸੂਚਨਾ"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"ਨਾਪਸੰਦ ਕੀਤੇ SIP ਖਾਤੇ"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ਇਸ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਸੁਨੇਹਾ ਨਹੀਂ ਭੇਜਿਆ ਜਾ ਸਕਦਾ"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"ਤੁਹਾਡੀ ਕਾਰਜ ਨੀਤੀ ਤੁਹਾਨੂੰ ਸਿਰਫ਼ ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਹੀ ਸੁਨੇਹਾ ਭੇਜਣ ਦੀ ਆਗਿਆ ਦਿੰਦੀ ਹੈ"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"ਰੱਦ ਕਰੋ"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ \'ਤੇ ਜਾਓ"</string>
</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index c6de1b1..9569634 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Musisz ponownie uruchomić urządzenie, by to zmienić."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Uruchom ponownie"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Anuluj"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Ustaw wymienną kartę eSIM jako domyślną"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Moc sygnału komórkowego"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Symulowana przerwa w działaniu usługi (tylko w kompilacji do debugowania)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Wyświetl książkę adresową z karty SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Wyświetl ustalone numery"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Wyświetl numery usług"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Połączono"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Zawieszone"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Brak informacji"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Główny"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"– pakiety"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"B"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacje o telefonie"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informacje o obsłudze administracyjnej operatora"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Uruchom obsługę administracyjną operatora"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Identyfikator uprawnienia dotyczącego połączeń przez Wi-Fi:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Aktualizuj"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Odśwież"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Twój sygnał Bluetooth jest słaby. Spróbuj przełączyć na głośnik."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Powiadomienie o jakości połączenia"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Wycofane konta SIP"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Nie możesz wysłać wiadomości z tego profilu"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Zasady obowiązujące w firmie zezwalają na wysyłanie wiadomości tylko z profilu służbowego"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Anuluj"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Przełącz na profil służbowy"</string>
</resources>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 586cb7f..f65c8b7 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -179,7 +179,7 @@
<string name="network_query_error" msgid="3862515805115145124">"Não foi possível localizar nenhuma rede. Tente novamente."</string>
<string name="register_on_network" msgid="4194770527833960423">"A registar em <xliff:g id="NETWORK">%s</xliff:g>..."</string>
<string name="not_allowed" msgid="8541221928746104798">"O cartão SIM não permite uma ligação a esta rede."</string>
- <string name="connect_later" msgid="1950138106010005425">"De momento, não é possível estabelecer ligação com esta rede. Tente novamente mais tarde."</string>
+ <string name="connect_later" msgid="1950138106010005425">"De momento, não é possível estabelecer ligação com esta rede. Tente mais tarde."</string>
<string name="registration_done" msgid="5337407023566953292">"Registado na rede."</string>
<string name="already_auto" msgid="8607068290733079336">"A seleção automática já está ativada."</string>
<string name="select_automatically" msgid="779750291257872651">"Selecionar automaticamente a rede"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Tem de reiniciar o dispositivo para alterar esta definição."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Reiniciar"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancelar"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Predefinir eSIM removível"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Potência do rádio móvel"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simule o modo fora de serviço (apenas na versão de depuração)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Ver livro de endereços do SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Ver números autorizados"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Ver números de marcação de serviços"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Ligado"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspenso"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Desconhecido"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informações do telefone"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informações de fornecimento do operador"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Acionar fornecimento do operador"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID de direito de utilização de WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Atualizar"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Atualizar"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"O seu sinal Bluetooth é fraco. Tente mudar para o altifalante."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notificação de qualidade da chamada"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Contas SIP descontinuadas"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Não é possível enviar mensagens a partir deste perfil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"A sua Política de Trabalho permite-lhe enviar mensagens apenas a partir do perfil de trabalho"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancelar"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Mudar para perfil de trabalho"</string>
</resources>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index ced0b61..a72babd 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -579,7 +579,7 @@
<string name="onscreenEndCallText" msgid="6138725377654842757">"Finalizar"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"Teclado"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"Desativar som"</string>
- <string name="onscreenAddCallText" msgid="9075675082903611677">"Adicionar chamada"</string>
+ <string name="onscreenAddCallText" msgid="9075675082903611677">"Adicionar ligação"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"Juntar chamadas"</string>
<string name="onscreenSwapCallsText" msgid="2682542150803377991">"Trocar"</string>
<string name="onscreenManageCallsText" msgid="1162047856081836469">"Gerenciar chamadas"</string>
@@ -595,7 +595,7 @@
<string name="hac_mode_title" msgid="4127986689621125468">"Aparelhos auditivos"</string>
<string name="hac_mode_summary" msgid="7774989500136009881">"Ativar compatibilidade com aparelhos auditivos"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Chamada com mensagem de texto em tempo real (RTT)"</string>
- <string name="rtt_mode_summary" msgid="8631541375609989562">"Permitir o envio de mensagens de texto em uma chamada de voz"</string>
+ <string name="rtt_mode_summary" msgid="8631541375609989562">"Permitir o envio de mensagens de texto em uma ligação"</string>
<string name="rtt_mode_more_information" msgid="587500128658756318">"A RTT ajuda os autores das chamadas com deficiências como surdez, dificuldade de audição ou fala ou que precisam de outros recursos além de voz.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Saiba mais</a>\n <br><br> — As chamadas RTT são salvas como transcrições de mensagem\n <br> — A RTT não está disponível para videochamadas"</string>
<string name="no_rtt_when_roaming" msgid="5268008247378355389">"Observação: a RTT não está disponível em roaming"</string>
<string-array name="tty_mode_entries">
@@ -655,7 +655,7 @@
<string name="contactPhoto" msgid="7885089213135154834">"foto do contato"</string>
<string name="goPrivate" msgid="4645108311382209551">"conversar em particular"</string>
<string name="selectContact" msgid="1527612842599767382">"selecionar contato"</string>
- <string name="not_voice_capable" msgid="2819996734252084253">"Chamada de voz não compatível"</string>
+ <string name="not_voice_capable" msgid="2819996734252084253">"Ligação não compatível"</string>
<string name="description_dial_button" msgid="8614631902795087259">"discar"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"Mostrar teclado"</string>
<string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Teclado de emergência"</string>
@@ -815,7 +815,7 @@
<string name="supp_service_held_call_released" msgid="2847835124639112410">"A chamada em espera foi desconectada."</string>
<string name="callFailed_otasp_provisioning_in_process" msgid="3345666183602879326">"Não é possível ligar porque o dispositivo está sendo provisionado no momento,"</string>
<string name="callFailed_already_dialing" msgid="7250591188960691086">"Não é possível ligar porque há outra chamada sendo realizada."</string>
- <string name="callFailed_already_ringing" msgid="2376603543544289303">"Não é possível ligar porque há uma chamada recebida que não foi atendida. Atenda ou rejeite essa chamada antes de fazer outra."</string>
+ <string name="callFailed_already_ringing" msgid="2376603543544289303">"Não é possível ligar porque há uma ligação recebida que não foi atendida. Atenda ou rejeite essa chamada antes de fazer outra."</string>
<string name="callFailed_calling_disabled" msgid="5010992739401206283">"Não é possível ligar porque as chamadas foram desativadas pela propriedade \"ro.telephony.disable-call system\"."</string>
<string name="callFailed_too_many_calls" msgid="2761754044990799580">"Não é possível ligar porque já há duas chamadas em andamento. Encerre uma das chamadas ou mescle-as em uma conferência antes de fazer outra."</string>
<string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"Verifique se os dados móveis estão ativados para usar este serviço: <xliff:g id="SUPP_SERVICE">%s</xliff:g>. Você pode alterar essa opção nas configurações da rede móvel."</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Reinicie o dispositivo para alterar essa configuração."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Reiniciar"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Cancelar"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Definir eSIM removível como padrão"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Potência do rádio celular"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simular o modo fora de serviço (somente build de depuração)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Ver o catálogo de endereços do chip"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Ver números de discagem fixa"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Ver números de discagem do serviço"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Conectado"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspenso"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Desconhecido"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -882,7 +885,7 @@
<string name="radio_info_ppp_received_label" msgid="5753592451640644889">"Dados recebidos:"</string>
<string name="radio_info_gsm_service_label" msgid="6443348321714241328">"Serviço de voz:"</string>
<string name="radio_info_signal_strength_label" msgid="5545444702102543260">"Potência do sinal:"</string>
- <string name="radio_info_call_status_label" msgid="7693575431923095487">"Status da chamada de voz:"</string>
+ <string name="radio_info_call_status_label" msgid="7693575431923095487">"Status da ligação:"</string>
<string name="radio_info_ppp_sent_label" msgid="6542208429356199695">"Dados enviados:"</string>
<string name="radio_info_message_waiting_label" msgid="1886549432566952078">"Mensagem em espera:"</string>
<string name="radio_info_phone_number_label" msgid="2533852539562512203">"Número de telefone:"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informações do telefone"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informações de provisionamento da operadora"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Acionar provisionamento da operadora"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID de direito WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Atualizar"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Atualizar"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"O sinal do Bluetooth está fraco. Mude para o viva-voz."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notificação sobre a qualidade da chamada"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Contas SIP suspensas"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Não é possível enviar mensagens deste perfil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Sua política de trabalho só permite o envio de mensagens pelo perfil de trabalho"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Cancelar"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Mudar para o perfil de trabalho"</string>
</resources>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 037efa8..2260b62 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -30,29 +30,29 @@
<string name="mmiStarted" msgid="9212975136944568623">"Cod MMI pornit"</string>
<string name="ussdRunning" msgid="1163586813106772717">"Se rulează codul USSD..."</string>
<string name="mmiCancelled" msgid="5339191899200678272">"Cod MMI anulat"</string>
- <string name="cancel" msgid="8984206397635155197">"Anulați"</string>
- <string name="enter_input" msgid="6193628663039958990">"Mesajul USSD trebuie să aibă între <xliff:g id="MIN_LEN">%1$d</xliff:g> și <xliff:g id="MAX_LEN">%2$d</xliff:g> caractere. Încercați din nou."</string>
- <string name="manageConferenceLabel" msgid="8415044818156353233">"Gestionați teleconferința"</string>
+ <string name="cancel" msgid="8984206397635155197">"Anulează"</string>
+ <string name="enter_input" msgid="6193628663039958990">"Mesajul USSD trebuie să aibă între <xliff:g id="MIN_LEN">%1$d</xliff:g> și <xliff:g id="MAX_LEN">%2$d</xliff:g> caractere. Încearcă din nou."</string>
+ <string name="manageConferenceLabel" msgid="8415044818156353233">"Gestionează teleconferința"</string>
<string name="ok" msgid="7818974223666140165">"OK"</string>
<string name="audio_mode_speaker" msgid="243689733219312360">"Difuzor"</string>
<string name="audio_mode_earpiece" msgid="2823700267171134282">"Casca dispozitivului"</string>
<string name="audio_mode_wired_headset" msgid="5028010823105817443">"Cască cu fir"</string>
<string name="audio_mode_bluetooth" msgid="25732183428018809">"Bluetooth"</string>
- <string name="wait_prompt_str" msgid="5136209532150094910">"Trimiteți următoarele tonuri?\n"</string>
+ <string name="wait_prompt_str" msgid="5136209532150094910">"Trimiți următoarele tonuri?\n"</string>
<string name="pause_prompt_str" msgid="2308897950360272213">"Se trimit tonuri\n"</string>
- <string name="send_button" msgid="5070379600779031932">"Trimiteți"</string>
+ <string name="send_button" msgid="5070379600779031932">"Trimite"</string>
<string name="pause_prompt_yes" msgid="8184132073048369575">"Da"</string>
<string name="pause_prompt_no" msgid="2145264674774138579">"Nu"</string>
<string name="wild_prompt_str" msgid="5858910969703305375">"Înlocuiți metacaracterul cu"</string>
<string name="no_vm_number" msgid="6623853880546176930">"Lipsește numărul mesageriei vocale"</string>
<string name="no_vm_number_msg" msgid="5165161462411372504">"Niciun număr de mesagerie vocală nu este stocat pe cardul SIM."</string>
- <string name="add_vm_number_str" msgid="7368168964435881637">"Adăugați numărul"</string>
+ <string name="add_vm_number_str" msgid="7368168964435881637">"Adaugă numărul"</string>
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Setările pentru mesagerie vocală pot fi modificate numai de utilizatorul principal."</string>
- <string name="puk_unlocked" msgid="4627340655215746511">"Cardul dvs. SIM a fost deblocat. Telefonul dvs. se deblochează..."</string>
+ <string name="puk_unlocked" msgid="4627340655215746511">"Cardul tău SIM a fost deblocat. Telefonul tău se deblochează..."</string>
<string name="label_ndp" msgid="7617392683877410341">"Codul PIN de deblocare a rețelei SIM"</string>
<string name="label_phoneid" msgid="8775611434123577808">"Cardul SIM a fost blocat pentru operator"</string>
- <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Deblocați"</string>
- <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Renunțați"</string>
+ <string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Deblochează"</string>
+ <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Renunță"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Se solicită deblocarea rețelei..."</string>
<string name="unlock_failed" msgid="7103543844840661366">"Cererea de deblocare a rețelei a eșuat."</string>
<string name="unlock_success" msgid="32681089371067565">"Rețeaua a fost deblocată."</string>
@@ -64,25 +64,25 @@
<string name="apn_settings" msgid="1978652203074756623">"Numele punctelor de acces"</string>
<string name="settings_label" msgid="9101778088412567956">"Setări de rețea"</string>
<string name="phone_accounts" msgid="1216879437523774604">"Conturi pentru apelare"</string>
- <string name="phone_accounts_make_calls_with" msgid="16747814788918145">"Apelați cu"</string>
- <string name="phone_accounts_make_sip_calls_with" msgid="4691221006731847255">"Dați apeluri SIP cu"</string>
+ <string name="phone_accounts_make_calls_with" msgid="16747814788918145">"Apelează cu"</string>
+ <string name="phone_accounts_make_sip_calls_with" msgid="4691221006731847255">"Dai apeluri SIP cu"</string>
<string name="phone_accounts_ask_every_time" msgid="6192347582666047168">"Întreabă mai întâi"</string>
<string name="phone_accounts_default_account_label" msgid="5107598881335931101">"Nicio rețea disponibilă"</string>
<string name="phone_accounts_settings_header" msgid="6296501692964706536">"Setări"</string>
- <string name="phone_accounts_choose_accounts" msgid="4748805293314824974">"Alegeți conturile"</string>
+ <string name="phone_accounts_choose_accounts" msgid="4748805293314824974">"Alege conturile"</string>
<string name="phone_accounts_selection_header" msgid="2945830843104108440">"Conturi telefon"</string>
- <string name="phone_accounts_add_sip_account" msgid="1437634802033309305">"Adăugați un cont SIP"</string>
- <string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Configurați setările contului"</string>
+ <string name="phone_accounts_add_sip_account" msgid="1437634802033309305">"Adaugă un cont SIP"</string>
+ <string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"Configurează setările contului"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"Toate conturile pentru apelare"</string>
- <string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Selectați conturile care pot da apeluri"</string>
+ <string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"Selectează conturile care pot da apeluri"</string>
<string name="wifi_calling" msgid="3650509202851355742">"Apelare prin Wi-Fi"</string>
<string name="connection_service_default_label" msgid="7332739049855715584">"Serviciu de conectare încorporat"</string>
<string name="voicemail" msgid="7697769412804195032">"Mesagerie vocală"</string>
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"Mesagerie vocală (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="voicemail_abbreviated" msgid="7746778673131551185">"MV:"</string>
- <string name="make_and_receive_calls" msgid="4868913166494621109">"Inițiați și primiți apeluri"</string>
+ <string name="make_and_receive_calls" msgid="4868913166494621109">"Inițiază și primește apeluri"</string>
<string name="smart_forwarding_settings_menu" msgid="8850429887958938540">"Redirecționare intuitivă"</string>
- <string name="smart_forwarding_settings_menu_summary" msgid="5096947726032885325">"Când un număr nu este disponibil, redirecționați mereu apelurile către celălalt număr pe care îl aveți."</string>
+ <string name="smart_forwarding_settings_menu_summary" msgid="5096947726032885325">"Când un număr nu este disponibil, redirecționează mereu apelurile către celălalt număr pe care îl ai."</string>
<string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"Notificări"</string>
<string name="cell_broadcast_settings" msgid="8135324242541809924">"Transmisiuni de urgență"</string>
<string name="call_settings" msgid="3677282690157603818">"Setări pentru apeluri"</string>
@@ -96,7 +96,7 @@
<string name="sum_loading_settings" msgid="434063780286688775">"Se încarcă setările…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Număr ascuns în apelurile de ieșire"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Numărul afișat în apelurile de ieșire"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Utilizați setările prestabilite ale operatorului pentru a vă afișa numărul în apelurile efectuate"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Utilizează setările prestabilite ale operatorului pentru a-ți afișa numărul în apelurile efectuate"</string>
<string name="labelCW" msgid="8449327023861428622">"Apel în așteptare"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Anunță-mă dacă primesc un apel în timpul unei convorbiri"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Anunță-mă dacă primesc un apel în timpul unei convorbiri"</string>
@@ -113,22 +113,22 @@
<string name="messageCFB" msgid="1958017270393563388">"Număr pentru redirecționare dacă este ocupat"</string>
<string name="sum_cfb_enabled" msgid="332037613072049492">"Se redirecționează la <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfb_disabled" msgid="3589913334164866035">"Dezactivat"</string>
- <string name="disable_cfb_forbidden" msgid="4831494744351633961">"Operatorul dvs. nu acceptă ca redirecționarea apelurilor să fie dezactivată atunci când telefonul dvs. este ocupat."</string>
+ <string name="disable_cfb_forbidden" msgid="4831494744351633961">"Operatorul tău nu acceptă ca redirecționarea apelurilor să fie dezactivată atunci când telefonul tău este ocupat."</string>
<string name="labelCFNRy" msgid="3403533792248457946">"Când nu se răspunde"</string>
<string name="messageCFNRy" msgid="7644434155765359009">"Număr pentru redirecționare dacă nu se răspunde"</string>
<string name="sum_cfnry_enabled" msgid="3000500837493854799">"Se redirecționează la <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnry_disabled" msgid="1990563512406017880">"Dezactivat"</string>
- <string name="disable_cfnry_forbidden" msgid="3174731413216550689">"Operatorul dvs. nu acceptă ca redirecționarea apelurilor să fie dezactivată atunci când telefonul dvs. nu răspunde."</string>
+ <string name="disable_cfnry_forbidden" msgid="3174731413216550689">"Operatorul tău nu acceptă ca redirecționarea apelurilor să fie dezactivată atunci când telefonul tău nu răspunde."</string>
<string name="labelCFNRc" msgid="4163399350778066013">"Când nu este accesibil"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"Număr de redirecționare dacă telefonul nu este accesibil"</string>
<string name="sum_cfnrc_enabled" msgid="1799069234006073477">"Se redirecționează la <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"Dezactivat"</string>
- <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operatorul dvs. nu acceptă ca redirecționarea apelurilor să fie dezactivată atunci când telefonul nu este accesibil."</string>
- <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatorul dvs. nu acceptă redirecționarea apelurilor."</string>
- <string name="cdma_call_waiting" msgid="4565070960879673216">"Activați apelurile în așteptare?"</string>
- <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"În timpul unui apel, veți primi o notificare despre apelurile primite"</string>
- <string name="enable_cdma_cw" msgid="811047045863422232">"Activați"</string>
- <string name="disable_cdma_cw" msgid="7119290446496301734">"Anulați"</string>
+ <string name="disable_cfnrc_forbidden" msgid="775348748084726890">"Operatorul tău nu acceptă ca redirecționarea apelurilor să fie dezactivată atunci când telefonul nu este accesibil."</string>
+ <string name="registration_cf_forbidden" msgid="4386482610771190420">"Operatorul tău nu acceptă redirecționarea apelurilor."</string>
+ <string name="cdma_call_waiting" msgid="4565070960879673216">"Activezi apelurile în așteptare?"</string>
+ <string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"În timpul unui apel, vei primi o notificare despre apelurile primite"</string>
+ <string name="enable_cdma_cw" msgid="811047045863422232">"Activează"</string>
+ <string name="disable_cdma_cw" msgid="7119290446496301734">"Anulează"</string>
<string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"Apelurile în așteptare CDMA din IMS sunt activate"</string>
<string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"Apelurile în așteptare CDMA din IMS sunt dezactivate"</string>
<string name="updating_title" msgid="6130548922615719689">"Setări pentru apeluri"</string>
@@ -145,26 +145,26 @@
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"Schimbat cu o solicitare SS nouă"</string>
<string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"Solicitarea SS a fost schimbată cu un apel video"</string>
<string name="fdn_check_failure" msgid="1833769746374185247">"Setarea Numere cu apelări restricționate din aplicația Telefon este activată. Ca rezultat, unele funcții legate de apelare nu pot fi utilizate."</string>
- <string name="radio_off_error" msgid="8321564164914232181">"Activați semnalul radio, înainte de a vizualiza aceste setări."</string>
+ <string name="radio_off_error" msgid="8321564164914232181">"Activează semnalul radio, înainte de a vizualiza aceste setări."</string>
<string name="close_dialog" msgid="1074977476136119408">"OK"</string>
- <string name="enable" msgid="2636552299455477603">"Activați"</string>
- <string name="disable" msgid="1122698860799462116">"Dezactivați"</string>
- <string name="change_num" msgid="6982164494063109334">"Actualizați"</string>
+ <string name="enable" msgid="2636552299455477603">"Activează"</string>
+ <string name="disable" msgid="1122698860799462116">"Dezactivează"</string>
+ <string name="change_num" msgid="6982164494063109334">"Actualizează"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"Rețea prestabilită"</item>
- <item msgid="6813323051965618926">"Ascundeți numărul"</item>
- <item msgid="9150034130629852635">"Afișați numărul"</item>
+ <item msgid="6813323051965618926">"Ascunde numărul"</item>
+ <item msgid="9150034130629852635">"Afișează numărul"</item>
</string-array>
<string name="vm_changed" msgid="4739599044379692505">"Număr mesagerie vocală modificat."</string>
- <string name="vm_change_failed" msgid="7877733929455763566">"Nu s-a putut schimba numărul de mesagerie vocală.\nContactați operatorul în cazul în care această problemă persistă."</string>
- <string name="fw_change_failed" msgid="9179241823460192148">"Nu s-a putut schimba numărul de redirecționare.\nContactați operatorul dvs. în cazul în care această problemă persistă."</string>
- <string name="fw_get_in_vm_failed" msgid="2432678237218183844">"Nu s-au putut prelua și salva setările actuale ale numărului de redirecționare.\nDoriți să comutați oricum către un nou furnizor de servicii?"</string>
+ <string name="vm_change_failed" msgid="7877733929455763566">"Nu s-a putut schimba numărul de mesagerie vocală.\nContactează operatorul în cazul în care această problemă persistă."</string>
+ <string name="fw_change_failed" msgid="9179241823460192148">"Nu s-a putut schimba numărul de redirecționare.\nContactează operatorul tău în cazul în care această problemă persistă."</string>
+ <string name="fw_get_in_vm_failed" msgid="2432678237218183844">"Nu s-au putut prelua și salva setările actuale ale numărului de redirecționare.\nDorești să treci oricum către un nou furnizor de servicii?"</string>
<string name="no_change" msgid="3737264882821031892">"Nicio schimbare efectuată."</string>
- <string name="sum_voicemail_choose_provider" msgid="6750824719081403773">"Alegeți serviciul de mesagerie vocală"</string>
- <string name="voicemail_default" msgid="6427575113775462077">"Operatorul dvs."</string>
+ <string name="sum_voicemail_choose_provider" msgid="6750824719081403773">"Alege serviciul de mesagerie vocală"</string>
+ <string name="voicemail_default" msgid="6427575113775462077">"Operatorul tău"</string>
<string name="vm_change_pin_old_pin" msgid="7154951790929009241">"Codul PIN vechi"</string>
<string name="vm_change_pin_new_pin" msgid="2656200418481288069">"Codul PIN nou"</string>
- <string name="vm_change_pin_progress_message" msgid="626015184502739044">"Așteptați."</string>
+ <string name="vm_change_pin_progress_message" msgid="626015184502739044">"Așteaptă."</string>
<string name="vm_change_pin_error_too_short" msgid="1789139338449945483">"Codul PIN nou este prea scurt."</string>
<string name="vm_change_pin_error_too_long" msgid="3634907034310018954">"Codul PIN nou este prea lung."</string>
<string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"Codul PIN nou este prea slab. O parolă puternică nu ar trebui să aibă o secvență continuă sau cifre repetitive."</string>
@@ -176,21 +176,21 @@
<string name="label_available" msgid="1316084116670821258">"Rețele disponibile"</string>
<string name="load_networks_progress" msgid="4051433047717401683">"Se caută…"</string>
<string name="empty_networks_list" msgid="9216418268008582342">"Nicio rețea găsită."</string>
- <string name="network_query_error" msgid="3862515805115145124">"Nu s-au găsit rețele. Încercați din nou."</string>
+ <string name="network_query_error" msgid="3862515805115145124">"Nu s-au găsit rețele. Încearcă din nou."</string>
<string name="register_on_network" msgid="4194770527833960423">"Se înregistrează pe <xliff:g id="NETWORK">%s</xliff:g>..."</string>
- <string name="not_allowed" msgid="8541221928746104798">"Cardul dvs. SIM nu permite conexiunea la această rețea."</string>
- <string name="connect_later" msgid="1950138106010005425">"Nu se poate efectua conectarea la această rețea chiar acum. Încercați din nou mai târziu."</string>
+ <string name="not_allowed" msgid="8541221928746104798">"Cardul tău SIM nu permite conexiunea la această rețea."</string>
+ <string name="connect_later" msgid="1950138106010005425">"Nu se poate efectua conectarea la această rețea chiar acum. Încearcă din nou mai târziu."</string>
<string name="registration_done" msgid="5337407023566953292">"Înregistrat în rețea."</string>
<string name="already_auto" msgid="8607068290733079336">"Deja în selecție automată."</string>
- <string name="select_automatically" msgid="779750291257872651">"Selectați automat rețeaua"</string>
+ <string name="select_automatically" msgid="779750291257872651">"Selectează automat rețeaua"</string>
<string name="manual_mode_disallowed_summary" msgid="3970048592179890197">"Indisponibil când este conectat la %1$s"</string>
<string name="network_select_title" msgid="4117305053881611988">"Rețea"</string>
<string name="register_automatically" msgid="3907580547590554834">"Înregistrare automată..."</string>
<string name="preferred_network_mode_title" msgid="5253395265169539830">"Tipul de rețea preferat"</string>
- <string name="preferred_network_mode_summary" msgid="3787989000044330064">"Schimbați modul de operare a rețelei"</string>
+ <string name="preferred_network_mode_summary" msgid="3787989000044330064">"Schimbă modul de operare a rețelei"</string>
<string name="preferred_network_mode_dialogtitle" msgid="2781447433514459696">"Tipul de rețea preferat"</string>
<string name="forbidden_network" msgid="5081729819561333023">"(interzis)"</string>
- <string name="choose_network_title" msgid="5335832663422653082">"Alegeți o rețea"</string>
+ <string name="choose_network_title" msgid="5335832663422653082">"Alege o rețea"</string>
<string name="network_disconnected" msgid="8844141106841160825">"Deconectat"</string>
<string name="network_connected" msgid="2760235679963580224">"Conectat"</string>
<string name="network_connecting" msgid="160901383582774987">"Se conectează…"</string>
@@ -273,30 +273,30 @@
<string name="network_operator_category" msgid="4992217193732304680">"Rețea"</string>
<string name="enhanced_4g_lte_mode_title" msgid="4213420368777080540">"Mod 4G LTE îmbunătățit"</string>
<!-- no translation found for enhanced_4g_lte_mode_title_variant:0 (7240155150166394308) -->
- <string name="enhanced_4g_lte_mode_summary" msgid="7725708511804143638">"Folosiți servicii LTE pt. a îmbunătăți comunicări vocale și altele (recomandat)"</string>
- <string name="enhanced_4g_lte_mode_summary_o2" msgid="2521108446409016542">"Folosiți servicii 4G pentru a îmbunătăți comunicările vocale și altele (recomandat)"</string>
+ <string name="enhanced_4g_lte_mode_summary" msgid="7725708511804143638">"Folosește servicii LTE pt. a îmbunătăți comunicări vocale și altele (recomandat)"</string>
+ <string name="enhanced_4g_lte_mode_summary_o2" msgid="2521108446409016542">"Folosește servicii 4G pentru a îmbunătăți comunicările vocale și altele (recomandat)"</string>
<!-- no translation found for enhanced_4g_lte_mode_sumary_variant:0 (2943982616649705147) -->
<!-- no translation found for enhanced_4g_lte_mode_sumary_variant:1 (5262249464504131443) -->
<!-- no translation found for enhanced_4g_lte_mode_sumary_variant:2 (6356974241850241718) -->
<string name="data_enabled" msgid="22525832097434368">"Date activate"</string>
- <string name="data_enable_summary" msgid="696860063456536557">"Permiteți utilizarea datelor"</string>
+ <string name="data_enable_summary" msgid="696860063456536557">"Permite utilizarea datelor"</string>
<string name="dialog_alert_title" msgid="5260471806940268478">"Atenție"</string>
<string name="roaming" msgid="1576180772877858949">"Roaming"</string>
- <string name="roaming_enable" msgid="6853685214521494819">"Conectați-vă la serviciile de date în roaming"</string>
- <string name="roaming_disable" msgid="8856224638624592681">"Conectați-vă la serviciile de date în roaming"</string>
- <string name="roaming_reenable_message" msgid="1951802463885727915">"Roamingul de date este dezactivat. Atingeți pentru a-l activa."</string>
- <string name="roaming_enabled_message" msgid="9022249120750897">"Se pot aplica tarife de roaming. Atingeți pentru a modifica."</string>
+ <string name="roaming_enable" msgid="6853685214521494819">"Conectează-te la serviciile de date în roaming"</string>
+ <string name="roaming_disable" msgid="8856224638624592681">"Conectează-te la serviciile de date în roaming"</string>
+ <string name="roaming_reenable_message" msgid="1951802463885727915">"Roamingul de date este dezactivat. Atinge pentru a-l activa."</string>
+ <string name="roaming_enabled_message" msgid="9022249120750897">"Se pot aplica tarife de roaming. Atinge pentru a modifica."</string>
<string name="roaming_notification_title" msgid="3590348480688047320">"S-a pierdut conexiunea de date mobile"</string>
<string name="roaming_on_notification_title" msgid="7451473196411559173">"Roamingul de date este activat"</string>
<string name="roaming_warning" msgid="7855681468067171971">"Se pot acumula costuri mari."</string>
- <string name="roaming_check_price_warning" msgid="8212484083990570215">"Consultați furnizorul de rețea în privința prețurilor."</string>
- <string name="roaming_alert_title" msgid="5689615818220960940">"Permiteți roamingul de date?"</string>
+ <string name="roaming_check_price_warning" msgid="8212484083990570215">"Consultă furnizorul de rețea în privința prețurilor."</string>
+ <string name="roaming_alert_title" msgid="5689615818220960940">"Permiți roamingul de date?"</string>
<string name="limited_sim_function_notification_title" msgid="612715399099846281">"Funcționalitate SIM limitată"</string>
<string name="limited_sim_function_with_phone_num_notification_message" msgid="5928988883403677610">"Este posibil ca apelurile și serviciile de date de la <xliff:g id="CARRIER_NAME">%1$s</xliff:g> să fie blocate în timp ce se folosește <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>."</string>
- <string name="limited_sim_function_notification_message" msgid="5338638075496721160">"Apelurile și serviciile de date de la <xliff:g id="CARRIER_NAME">%1$s</xliff:g> pot fi blocate când folosiți alt card SIM"</string>
+ <string name="limited_sim_function_notification_message" msgid="5338638075496721160">"Apelurile și serviciile de date de la <xliff:g id="CARRIER_NAME">%1$s</xliff:g> pot fi blocate când folosești alt card SIM"</string>
<string name="sip_accounts_removed_notification_title" msgid="3528076957535736095">"Au fost găsite și eliminate conturi SIP învechite"</string>
- <string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Platforma Android nu mai acceptă apelarea SIP.\nConturile dvs. SIP existente <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> au fost eliminate.\nConfirmați setarea prestabilită pentru apelare a contului."</string>
- <string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"Accesați setările"</string>
+ <string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Platforma Android nu mai acceptă apelarea SIP.\nConturile tale SIP existente <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> au fost eliminate.\nConfirmă setarea prestabilită pentru apelare a contului."</string>
+ <string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"Accesează setările"</string>
<string name="data_usage_title" msgid="8438592133893837464">"Date utilizate de aplicație"</string>
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_1">%1$s</xliff:g> de date mobile utilizate în intervalul <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="advanced_options_title" msgid="9208195294513520934">"Avansate"</string>
@@ -304,11 +304,11 @@
<string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"operator, esim, sim, euicc, schimbare operatori, adăugare operator"</string>
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> — <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
<string name="mobile_data_settings_title" msgid="7228249980933944101">"Date mobile"</string>
- <string name="mobile_data_settings_summary" msgid="5012570152029118471">"Accesați datele folosind rețeaua mobilă"</string>
- <string name="data_usage_disable_mobile" msgid="5669109209055988308">"Dezactivați datele mobile?"</string>
- <string name="sim_selection_required_pref" msgid="6985901872978341314">"Selectați o opțiune"</string>
- <string name="sim_change_data_title" msgid="9142726786345906606">"Schimbați cartela SIM de date?"</string>
- <string name="sim_change_data_message" msgid="3567358694255933280">"Folosiți <xliff:g id="NEW_SIM">%1$s</xliff:g> în loc de <xliff:g id="OLD_SIM">%2$s</xliff:g> pentru datele mobile?"</string>
+ <string name="mobile_data_settings_summary" msgid="5012570152029118471">"Accesează datele folosind rețeaua mobilă"</string>
+ <string name="data_usage_disable_mobile" msgid="5669109209055988308">"Dezactivezi datele mobile?"</string>
+ <string name="sim_selection_required_pref" msgid="6985901872978341314">"Selectează o opțiune"</string>
+ <string name="sim_change_data_title" msgid="9142726786345906606">"Schimbi cartela SIM de date?"</string>
+ <string name="sim_change_data_message" msgid="3567358694255933280">"Folosești <xliff:g id="NEW_SIM">%1$s</xliff:g> în loc de <xliff:g id="OLD_SIM">%2$s</xliff:g> pentru datele mobile?"</string>
<string name="wifi_calling_settings_title" msgid="5800018845662016507">"Apelare prin Wi-Fi"</string>
<string name="video_calling_settings_title" msgid="342829454913266078">"Apelare video prin operator"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"Opțiuni GSM/UMTS"</string>
@@ -317,7 +317,7 @@
<string name="throttle_current_usage" msgid="7483859109708658613">"Datele utilizate în perioada curentă"</string>
<string name="throttle_time_frame" msgid="1813452485948918791">"Perioada de utilizare a datelor"</string>
<string name="throttle_rate" msgid="7641913901133634905">"Politica ratei de transfer a datelor"</string>
- <string name="throttle_help" msgid="2624535757028809735">"Aflați mai multe"</string>
+ <string name="throttle_help" msgid="2624535757028809735">"Află mai multe"</string>
<string name="throttle_status_subtext" msgid="1110276415078236687">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>٪) din <xliff:g id="USED_2">%3$s</xliff:g> perioada maximă\nUrmătoarea perioadă începe în <xliff:g id="USED_3">%4$d</xliff:g> zile (<xliff:g id="USED_4">%5$s</xliff:g>)"</string>
<string name="throttle_data_usage_subtext" msgid="3185429653996709840">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>٪) din <xliff:g id="USED_2">%3$s</xliff:g> perioadă maximă"</string>
<string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> maximum depășit\nRata de transfer se reduce la <xliff:g id="USED_1">%2$d</xliff:g> Kb/s"</string>
@@ -355,7 +355,7 @@
<string name="international_enable" msgid="8943466745792690340">"Știri internaționale activate"</string>
<string name="international_disable" msgid="4803498658100318265">"Știri internaționale dezactivate"</string>
<string name="list_language_title" msgid="1850167908665485738">"Limbă"</string>
- <string name="list_language_summary" msgid="7921756070782277559">"Selectați limba pentru știri"</string>
+ <string name="list_language_summary" msgid="7921756070782277559">"Selectează limba pentru știri"</string>
<string-array name="list_language_entries">
<item msgid="2347238508726934281">"Engleză"</item>
<item msgid="5172468397620875174">"Franceză"</item>
@@ -415,15 +415,15 @@
<string name="network_lte" msgid="7206879277095094280">"LTE (recomandat)"</string>
<string name="network_4G" msgid="6800527815504223913">"4G (recomandat)"</string>
<string name="network_global" msgid="3289646154407617631">"Global"</string>
- <string name="cdma_system_select_title" msgid="614165233552656431">"Selectați sistemul"</string>
- <string name="cdma_system_select_summary" msgid="3840420390242060407">"Schimbați modul de roaming CDMA"</string>
- <string name="cdma_system_select_dialogtitle" msgid="5524639510676501802">"Selectați sistemul"</string>
+ <string name="cdma_system_select_title" msgid="614165233552656431">"Selectează sistemul"</string>
+ <string name="cdma_system_select_summary" msgid="3840420390242060407">"Schimbă modul de roaming CDMA"</string>
+ <string name="cdma_system_select_dialogtitle" msgid="5524639510676501802">"Selectează sistemul"</string>
<string-array name="cdma_system_select_choices">
<item msgid="462340042928284921">"Doar domiciliu"</item>
<item msgid="6058010046783562674">"Automat"</item>
</string-array>
<string name="cdma_subscription_title" msgid="3449527179325589434">"Abonament CMDA"</string>
- <string name="cdma_subscription_summary" msgid="5681152534466169001">"Comutați între RUIM/SIM și NV"</string>
+ <string name="cdma_subscription_summary" msgid="5681152534466169001">"Treci între RUIM/SIM și NV"</string>
<string name="cdma_subscription_dialogtitle" msgid="8872086335839723980">"abonament"</string>
<string-array name="cdma_subscription_choices">
<item msgid="7989486897370727698">"RUIM/SIM"</item>
@@ -433,67 +433,67 @@
<item msgid="2953825013895327785">"0"</item>
<item msgid="7970797749269738435">"1"</item>
</string-array>
- <string name="cdma_activate_device" msgid="5914720276140097632">"Activați dispozitivul"</string>
- <string name="cdma_lte_data_service" msgid="359786441782404562">"Configurați serviciul de date"</string>
+ <string name="cdma_activate_device" msgid="5914720276140097632">"Activează dispozitivul"</string>
+ <string name="cdma_lte_data_service" msgid="359786441782404562">"Configurează serviciul de date"</string>
<string name="carrier_settings_title" msgid="6292869148169850220">"Setări operator"</string>
<string name="fdn" msgid="2545904344666098749">"Numere apeluri restricționate"</string>
<string name="fdn_with_label" msgid="6412087553365709494">"Numere pentru apeluri restricționate (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="manage_fdn_list" msgid="3341716430375195441">"Listă NAR"</string>
<string name="fdn_list_with_label" msgid="1409655283510382556">"Listă NAR (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
- <string name="fdn_activation" msgid="2178637004710435895">"Activați NAR"</string>
+ <string name="fdn_activation" msgid="2178637004710435895">"Activează NAR"</string>
<string name="fdn_enabled" msgid="7017355494808056447">"Numerele cu apelări restricționate sunt activate"</string>
<string name="fdn_disabled" msgid="6696468878037736600">"Numerele pentru apeluri restricționate sunt dezactivate"</string>
- <string name="enable_fdn" msgid="4830555730418033723">"Activați NAR"</string>
- <string name="disable_fdn" msgid="3918794950264647541">"Dezactivați NAR"</string>
- <string name="change_pin2" msgid="3110844547237754871">"Schimbați codul PIN2"</string>
- <string name="enable_fdn_ok" msgid="5080925177369329827">"Dezactivați NAR"</string>
- <string name="disable_fdn_ok" msgid="3745475926874838676">"Activați NAR"</string>
- <string name="sum_fdn" msgid="6152246141642323582">"Gestionați numerele cu apelări restricționate"</string>
- <string name="sum_fdn_change_pin" msgid="3510994280557335727">"Schimbați codul PIN pentru acces la NAR"</string>
- <string name="sum_fdn_manage_list" msgid="3311397063233992907">"Gestionați lista numerelor de telefon"</string>
+ <string name="enable_fdn" msgid="4830555730418033723">"Activează NAR"</string>
+ <string name="disable_fdn" msgid="3918794950264647541">"Dezactivează NAR"</string>
+ <string name="change_pin2" msgid="3110844547237754871">"Schimbă codul PIN2"</string>
+ <string name="enable_fdn_ok" msgid="5080925177369329827">"Dezactivează NAR"</string>
+ <string name="disable_fdn_ok" msgid="3745475926874838676">"Activează NAR"</string>
+ <string name="sum_fdn" msgid="6152246141642323582">"Gestionează numerele cu apelări restricționate"</string>
+ <string name="sum_fdn_change_pin" msgid="3510994280557335727">"Schimbă codul PIN pentru acces la NAR"</string>
+ <string name="sum_fdn_manage_list" msgid="3311397063233992907">"Gestionează lista numerelor de telefon"</string>
<string name="voice_privacy" msgid="7346935172372181951">"Confidențialitate voce"</string>
- <string name="voice_privacy_summary" msgid="3556460926168473346">"Activați modul avansat de confidențialitate"</string>
+ <string name="voice_privacy_summary" msgid="3556460926168473346">"Activează modul avansat de confidențialitate"</string>
<string name="tty_mode_option_title" msgid="3843817710032641703">"Mod TTY"</string>
- <string name="tty_mode_option_summary" msgid="4770510287236494371">"Setați modul TTY"</string>
+ <string name="tty_mode_option_summary" msgid="4770510287236494371">"Setează modul TTY"</string>
<string name="auto_retry_mode_title" msgid="2985801935424422340">"Reîncercare automată"</string>
- <string name="auto_retry_mode_summary" msgid="2863919925349511402">"Activați modul Reîncercare automată"</string>
+ <string name="auto_retry_mode_summary" msgid="2863919925349511402">"Activează modul Reîncercare automată"</string>
<string name="tty_mode_not_allowed_video_call" msgid="6551976083652752815">"Schimbarea modului TTY nu este permisă în timpul unui apel video"</string>
- <string name="menu_add" msgid="5616487894975773141">"Adăugați o persoană"</string>
- <string name="menu_edit" msgid="3593856941552460706">"Modificați informațiile despre persoana din agendă"</string>
- <string name="menu_delete" msgid="6326861853830546488">"Ștergeți persoana din agendă"</string>
- <string name="menu_dial" msgid="4178537318419450012">"Apelați persoana de contact"</string>
- <string name="get_pin2" msgid="4221654606863196332">"Introduceți codul PIN2"</string>
+ <string name="menu_add" msgid="5616487894975773141">"Adaugă o persoană"</string>
+ <string name="menu_edit" msgid="3593856941552460706">"Modifică informațiile despre persoana din agendă"</string>
+ <string name="menu_delete" msgid="6326861853830546488">"Șterge persoana din agendă"</string>
+ <string name="menu_dial" msgid="4178537318419450012">"Apelează persoana de contact"</string>
+ <string name="get_pin2" msgid="4221654606863196332">"Introdu codul PIN2"</string>
<string name="name" msgid="1347432469852527784">"Nume"</string>
<string name="number" msgid="1564053487748491000">"Număr"</string>
- <string name="save" msgid="983805790346099749">"Salvați"</string>
- <string name="add_fdn_contact" msgid="1169713422306640887">"Adăugați un număr cu apelări restricționate"</string>
+ <string name="save" msgid="983805790346099749">"Salvează"</string>
+ <string name="add_fdn_contact" msgid="1169713422306640887">"Adaugă un număr cu apelări restricționate"</string>
<string name="adding_fdn_contact" msgid="3112531600824361259">"Se adaugă numărul cu apelări restricționate..."</string>
<string name="fdn_contact_added" msgid="2840016151693394596">"Număr cu apelări restricționate adăugat."</string>
<string name="edit_fdn_contact" msgid="6030829994819587408">"Modificați numărul cu apelări restricționate"</string>
<string name="updating_fdn_contact" msgid="6989341376868227150">"Se actualizează numărul cu apelări restricționate..."</string>
<string name="fdn_contact_updated" msgid="6876330243323118937">"Număr cu apelări restricționate actualizat."</string>
- <string name="delete_fdn_contact" msgid="7027405651994507077">"Ștergeți numărul cu apelări restricționate"</string>
+ <string name="delete_fdn_contact" msgid="7027405651994507077">"Șterge numărul cu apelări restricționate"</string>
<string name="deleting_fdn_contact" msgid="6872320570844460428">"Se șterge numărul cu apelări restricționate..."</string>
<string name="fdn_contact_deleted" msgid="1680714996763848838">"Numărul cu apelări restricționate a fost șters."</string>
- <string name="pin2_invalid" msgid="2313954262684494442">"NAR nu a fost actualizat, deoarece ați introdus un cod PIN incorect."</string>
+ <string name="pin2_invalid" msgid="2313954262684494442">"NAR nu a fost actualizat, deoarece ai introdus un cod PIN incorect."</string>
<string name="fdn_invalid_number" msgid="9067189814657840439">"NAR nu a fost actualizat deoarece numărul depășește <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> cifre."</string>
<string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"NAR nu a fost actualizat. Codul PIN2 a fost incorect sau numărul de telefon a fost respins."</string>
<string name="fdn_failed" msgid="216592346853420250">"Operațiunea NAR nu a reușit."</string>
<string name="simContacts_emptyLoading" msgid="4989040293858675483">"Se citește de pe cardul SIM..."</string>
<string name="simContacts_empty" msgid="1135632055473689521">"Nicio persoană pe cardul SIM."</string>
- <string name="simContacts_title" msgid="2714029230160136647">"Selectați pentru import"</string>
- <string name="simContacts_airplaneMode" msgid="4654884030631503808">"Pentru a importa persoane de contact de pe cardul SIM, dezactivați modul Avion."</string>
- <string name="enable_pin" msgid="967674051730845376">"Activați/dezactivați codul PIN al cardului SIM"</string>
- <string name="change_pin" msgid="3657869530942905790">"Schimbați codul PIN pentru SIM"</string>
+ <string name="simContacts_title" msgid="2714029230160136647">"Selectează pentru import"</string>
+ <string name="simContacts_airplaneMode" msgid="4654884030631503808">"Pentru a importa persoane de contact de pe cardul SIM, dezactivează modul Avion."</string>
+ <string name="enable_pin" msgid="967674051730845376">"Activează/dezactivează codul PIN al cardului SIM"</string>
+ <string name="change_pin" msgid="3657869530942905790">"Schimbă codul PIN pentru SIM"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"Codul PIN pentru cardul SIM:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"Codul PIN vechi"</string>
<string name="newPinLabel" msgid="3585899083055354732">"Cod PIN nou"</string>
- <string name="confirmPinLabel" msgid="7783531218662473778">"Confirmați noul cod PIN"</string>
- <string name="badPin" msgid="4549286285015892321">"Codul PIN vechi pe care l-ați introdus nu este corect. Încercați din nou."</string>
- <string name="mismatchPin" msgid="1467254768290323845">"Codurile PIN introduse nu se potrivesc. Încercați din nou."</string>
- <string name="invalidPin" msgid="7363723429414001979">"Introduceți un cod PIN alcătuit din 4 până la 8 cifre."</string>
- <string name="disable_sim_pin" msgid="3112303905548613752">"Ștergeți codul PIN pentru SIM"</string>
- <string name="enable_sim_pin" msgid="445461050748318980">"Setați codul PIN pentru SIM"</string>
+ <string name="confirmPinLabel" msgid="7783531218662473778">"Confirmă noul cod PIN"</string>
+ <string name="badPin" msgid="4549286285015892321">"Codul PIN vechi pe care l-ai introdus nu este corect. Încearcă din nou."</string>
+ <string name="mismatchPin" msgid="1467254768290323845">"Codurile PIN introduse nu se potrivesc. Încearcă din nou."</string>
+ <string name="invalidPin" msgid="7363723429414001979">"Introdu un cod PIN alcătuit din 4 până la 8 cifre."</string>
+ <string name="disable_sim_pin" msgid="3112303905548613752">"Șterge codul PIN pentru SIM"</string>
+ <string name="enable_sim_pin" msgid="445461050748318980">"Setează codul PIN pentru SIM"</string>
<string name="enable_in_progress" msgid="4135305985717272592">"Se setează codul PIN…"</string>
<string name="enable_pin_ok" msgid="2877428038280804256">"Cod PIN setat"</string>
<string name="disable_pin_ok" msgid="888505244389647754">"Cod PIN șters"</string>
@@ -503,19 +503,19 @@
<string name="enter_pin2_text" msgid="7266379426804295979">"PIN2"</string>
<string name="oldPin2Label" msgid="4648543187859997203">"Codul PIN2 vechi"</string>
<string name="newPin2Label" msgid="1840905981784453939">"Cod PIN2 nou"</string>
- <string name="confirmPin2Label" msgid="4336025914667593762">"Confirmați noul cod PIN2"</string>
- <string name="badPuk2" msgid="6438182906645832235">"Codul PUK2 nu este corect. Încercați din nou."</string>
- <string name="badPin2" msgid="2760917538643074635">"Vechiul cod PIN2 nu este corect. Încercați din nou."</string>
- <string name="mismatchPin2" msgid="4952718725266700631">"Codurile PIN2 nu se potrivesc. Încercați din nou."</string>
- <string name="invalidPin2" msgid="6467957903056379343">"Introduceți un cod PIN2 format din 4 până la 8 cifre."</string>
- <string name="invalidPuk2" msgid="713729511903849544">"Introduceți un cod PUK2 format din 8 cifre."</string>
+ <string name="confirmPin2Label" msgid="4336025914667593762">"Confirmă noul cod PIN2"</string>
+ <string name="badPuk2" msgid="6438182906645832235">"Codul PUK2 nu este corect. Încearcă din nou."</string>
+ <string name="badPin2" msgid="2760917538643074635">"Vechiul cod PIN2 nu este corect. Încearcă din nou."</string>
+ <string name="mismatchPin2" msgid="4952718725266700631">"Codurile PIN2 nu se potrivesc. Încearcă din nou."</string>
+ <string name="invalidPin2" msgid="6467957903056379343">"Introdu un cod PIN2 format din 4 până la 8 cifre."</string>
+ <string name="invalidPuk2" msgid="713729511903849544">"Introdu un cod PUK2 format din 8 cifre."</string>
<string name="pin2_changed" msgid="5710551850481287821">"Codul PIN2 a fost actualizat"</string>
- <string name="label_puk2_code" msgid="2852217004288085562">"Introduceți codul PUK2"</string>
- <string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"Parola nu este corectă. Codul PIN2 a fost blocat. Pentru a încerca din nou, schimbați codul PIN2."</string>
- <string name="puk2_requested" msgid="6992374450720307514">"Parola nu este corectă. Cardul SIM a fost blocat. Introduceți codul PUK2."</string>
+ <string name="label_puk2_code" msgid="2852217004288085562">"Introdu codul PUK2"</string>
+ <string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"Parola nu este corectă. Codul PIN2 a fost blocat. Pentru a încerca din nou, schimbă codul PIN2."</string>
+ <string name="puk2_requested" msgid="6992374450720307514">"Parola nu este corectă. Cardul SIM a fost blocat. Introdu codul PUK2."</string>
<string name="puk2_blocked" msgid="3131139031779319911">"Codul PUK2 este blocat definitiv."</string>
<string name="pin2_attempts" msgid="5625178102026453023">\n"V-au rămas <xliff:g id="NUMBER">%d</xliff:g> (de) încercări."</string>
- <string name="puk2_locked" msgid="6497760825455461057">"Blocat cu PUK2. Contactați furnizorul de servicii pentru a debloca."</string>
+ <string name="puk2_locked" msgid="6497760825455461057">"Blocat cu PUK2. Contactează furnizorul de servicii pentru a debloca."</string>
<string name="pin2_unblocked" msgid="4481107908727789303">"Codul PIN2 nu mai este blocat"</string>
<string name="pin2_error_exception" msgid="8116103864600823641">"Eroare de rețea sau de card SIM"</string>
<string name="doneButton" msgid="7371209609238460207">"Terminat"</string>
@@ -530,21 +530,21 @@
<string name="card_title_in_call" msgid="8231896539567594265">"În timpul apelului"</string>
<string name="notification_voicemail_title" msgid="3932876181831601351">"Mesaj vocal nou"</string>
<string name="notification_voicemail_title_count" msgid="2806950319222327082">"Mesaj vocal nou (<xliff:g id="COUNT">%d</xliff:g>)"</string>
- <string name="notification_voicemail_text_format" msgid="5720947141702312537">"Apelați <xliff:g id="VOICEMAIL_NUMBER">%s</xliff:g>"</string>
+ <string name="notification_voicemail_text_format" msgid="5720947141702312537">"Apelează <xliff:g id="VOICEMAIL_NUMBER">%s</xliff:g>"</string>
<string name="notification_voicemail_no_vm_number" msgid="3423686009815186750">"Număr mesagerie vocală necunoscut"</string>
<string name="notification_network_selection_title" msgid="255595526707809121">"Fără serviciu"</string>
<string name="notification_network_selection_text" msgid="553288408722427659">"Rețeaua selectată (<xliff:g id="OPERATOR_NAME">%s</xliff:g>) nu este disponibilă"</string>
- <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Activați rețeaua mobilă, dezactivați modul avion sau modul de economisire a bateriei pentru a iniția un apel."</string>
- <string name="incall_error_power_off" product="default" msgid="8131672264311208673">"Pentru a apela, dezactivați modul Avion."</string>
- <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"Pentru a apela, dezactivați modul Avion sau conectați-vă la o rețea wireless."</string>
- <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"Telefonul este prea fierbinte"</b>\n\n"Nu se poate iniția apelul. Încercați din nou după ce telefonul se răcește.\n\nPuteți, totuși, să inițiați apeluri de urgență."</string>
- <string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Ieșiți din modul de apelare inversă de urgență pentru a efectua un apel care nu este de urgență."</string>
+ <string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"Activează rețeaua mobilă, dezactivează modul avion sau modul de economisire a bateriei pentru a iniția un apel."</string>
+ <string name="incall_error_power_off" product="default" msgid="8131672264311208673">"Pentru a apela, dezactivează modul Avion."</string>
+ <string name="incall_error_power_off_wfc" msgid="9125661184694727052">"Pentru a apela, dezactivează modul Avion sau conectează-te la o rețea wireless."</string>
+ <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"Telefonul este prea fierbinte"</b>\n\n"Nu se poate iniția apelul. Încearcă din nou după ce telefonul se răcește.\n\nPoți, totuși, să inițiezi apeluri de urgență."</string>
+ <string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Ieși din modul de apelare inversă de urgență pentru a efectua un apel care nu este de urgență."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Neînregistrat în rețea."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Rețeaua mobilă nu este disponibilă."</string>
- <string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"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="8680831089508851894">"Pentru a apela, introduceți un număr valid."</string>
+ <string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Rețeaua mobilă nu este disponibilă. Pentru a apela, conectează-te la o rețea wireless."</string>
+ <string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Pentru a apela, introdu un număr valid."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Apelul nu a fost inițiat."</string>
- <string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Apelul nu poate fi inițiat în acest moment. Puteți lua legătura cu persoana respectivă trimițându-i un mesaj."</string>
+ <string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Apelul nu poate fi inițiat în acest moment. Poți lua legătura cu persoana respectivă trimițându-i un mesaj."</string>
<string name="incall_error_supp_service_unknown" msgid="8751177117194592623">"Serviciul nu este compatibil"</string>
<string name="incall_error_supp_service_switch" msgid="5272822448189448479">"Apelurile nu pot fi comutate."</string>
<string name="incall_error_supp_service_resume" msgid="1276861499306817035">"Nu se poate relua apelul."</string>
@@ -554,50 +554,50 @@
<string name="incall_error_supp_service_reject" msgid="3044363092441655912">"Apelul nu poate fi respins."</string>
<string name="incall_error_supp_service_hangup" msgid="836524952243836735">"Apelurile nu pot fi eliberate."</string>
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Apelurile nu pot fi puse în așteptare."</string>
- <string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Pentru a apela, conectați-vă la o rețea wireless."</string>
- <string name="incall_error_promote_wfc" msgid="9164896813931363415">"Activați apelarea prin Wi-Fi pentru a iniția un apel."</string>
+ <string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Pentru a apela, conectează-te la o rețea wireless."</string>
+ <string name="incall_error_promote_wfc" msgid="9164896813931363415">"Activează apelarea prin Wi-Fi pentru a iniția un apel."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informații în caz de urgență"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Proprietar"</string>
- <string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Atingeți din nou pentru a vedea informațiile"</string>
+ <string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Atinge din nou pentru a vedea informațiile"</string>
<string name="emergency_enable_radio_dialog_title" msgid="2667568200755388829">"Apel de urgență"</string>
<string name="single_emergency_number_title" msgid="8413371079579067196">"Număr de urgență"</string>
<string name="numerous_emergency_numbers_title" msgid="8972398932506755510">"Numere de urgență"</string>
- <string name="emergency_call_shortcut_hint" msgid="1290485125107779500">"Atingeți din nou pentru a apela <xliff:g id="EMERGENCY_NUMBER">%s</xliff:g>"</string>
+ <string name="emergency_call_shortcut_hint" msgid="1290485125107779500">"Atinge din nou pentru a apela <xliff:g id="EMERGENCY_NUMBER">%s</xliff:g>"</string>
<string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"Se activează semnalul radio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"Fără semnal. Se încearcă din nou..."</string>
<string name="radio_off_during_emergency_call" msgid="8011154134040481609">"Nu se poate intra în modul avion în timpul unui apel de urgență."</string>
<string name="dial_emergency_error" msgid="825822413209026039">"Nu se poate apela. <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> nu este un număr de urgență."</string>
- <string name="dial_emergency_empty_error" msgid="2785803395047793634">"Nu se poate apela. Formați un număr de urgență."</string>
+ <string name="dial_emergency_empty_error" msgid="2785803395047793634">"Nu se poate apela. Formează un număr de urgență."</string>
<string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"Apelurile de urgență nu sunt disponibile."</string>
<string name="pin_puk_system_user_only" msgid="1045147220686867922">"Numai proprietarul dispozitivului poate să introducă respectivele coduri PIN/PUK."</string>
<string name="police_type_description" msgid="2819533883972081757">"Poliție"</string>
<string name="ambulance_type_description" msgid="6798237503553180461">"Ambulanță"</string>
<string name="fire_type_description" msgid="6565200468934914930">"Pompieri"</string>
<string name="description_concat_format" msgid="2014471565101724088">"%1$s, %2$s"</string>
- <string name="dialerKeyboardHintText" msgid="1115266533703764049">"Utilizați tastatura pentru a forma"</string>
- <string name="onscreenHoldText" msgid="4025348842151665191">"Rețineți"</string>
+ <string name="dialerKeyboardHintText" msgid="1115266533703764049">"Utilizează tastatura pentru a forma"</string>
+ <string name="onscreenHoldText" msgid="4025348842151665191">"Reține"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"Terminat"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"Tastatură numerică"</string>
- <string name="onscreenMuteText" msgid="5470306116733843621">"Dezactivați sunetul"</string>
- <string name="onscreenAddCallText" msgid="9075675082903611677">"Adăugați un apel"</string>
- <string name="onscreenMergeCallsText" msgid="3692389519611225407">"Îmbinați apelurile"</string>
- <string name="onscreenSwapCallsText" msgid="2682542150803377991">"Schimbați"</string>
- <string name="onscreenManageCallsText" msgid="1162047856081836469">"Gestionați apelurile"</string>
+ <string name="onscreenMuteText" msgid="5470306116733843621">"Dezactivează sunetul"</string>
+ <string name="onscreenAddCallText" msgid="9075675082903611677">"Adaugă un apel"</string>
+ <string name="onscreenMergeCallsText" msgid="3692389519611225407">"Îmbină apelurile"</string>
+ <string name="onscreenSwapCallsText" msgid="2682542150803377991">"Schimbă"</string>
+ <string name="onscreenManageCallsText" msgid="1162047856081836469">"Gestionează apelurile"</string>
<string name="onscreenManageConferenceText" msgid="4700574060601755137">"Gestion. conferința"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"Audio"</string>
<string name="onscreenVideoCallText" msgid="1743992456126258698">"Apel video"</string>
- <string name="importSimEntry" msgid="3892354284082689894">"Importați"</string>
- <string name="importAllSimEntries" msgid="2628391505643564007">"Importați-le pe toate"</string>
+ <string name="importSimEntry" msgid="3892354284082689894">"Importă"</string>
+ <string name="importAllSimEntries" msgid="2628391505643564007">"Importă-le pe toate"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"Se importă persoanele din agenda de pe cardul SIM"</string>
- <string name="importToFDNfromContacts" msgid="5068664870738407341">"Importați din Agendă"</string>
+ <string name="importToFDNfromContacts" msgid="5068664870738407341">"Importă din Agendă"</string>
<string name="singleContactImportedMsg" msgid="3619804066300998934">"Persoana de contact a fost importată"</string>
<string name="failedToImportSingleContactMsg" msgid="228095510489830266">"Persoana de contact nu a fost importată"</string>
<string name="hac_mode_title" msgid="4127986689621125468">"Aparate auditive"</string>
- <string name="hac_mode_summary" msgid="7774989500136009881">"Activați compatibilitatea cu aparatele auditive"</string>
+ <string name="hac_mode_summary" msgid="7774989500136009881">"Activează compatibilitatea cu aparatele auditive"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Apel de tipul Text în timp real (TTR)"</string>
- <string name="rtt_mode_summary" msgid="8631541375609989562">"Permiteți schimbul de mesaje în timpul unui apel vocal"</string>
- <string name="rtt_mode_more_information" msgid="587500128658756318">"TTR oferă asistență apelanților fără auz, cu deficiențe de auz, care au dizabilități de vorbire sau care au nevoie de mai mult decât de voce.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Aflați mai multe</a>\n <br><br> - Apelurile RTT sunt salvate ca transcrierea unui mesaj\n <br> - Serviciul TTR nu este disponibil pentru apelurile video."</string>
- <string name="no_rtt_when_roaming" msgid="5268008247378355389">"Notă: funcția TTR nu este disponibilă când sunteți în roaming"</string>
+ <string name="rtt_mode_summary" msgid="8631541375609989562">"Permite schimbul de mesaje în timpul unui apel vocal"</string>
+ <string name="rtt_mode_more_information" msgid="587500128658756318">"TTR oferă asistență apelanților fără auz, cu deficiențe de auz, care au dizabilități de vorbire sau care au nevoie de mai mult decât de voce.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>Află mai multe</a>\n <br><br> - Apelurile RTT sunt salvate ca transcrierea unui mesaj\n <br> - Serviciul TTR nu este disponibil pentru apelurile video."</string>
+ <string name="no_rtt_when_roaming" msgid="5268008247378355389">"Notă: funcția TTR nu este disponibilă când ești în roaming"</string>
<string-array name="tty_mode_entries">
<item msgid="3238070884803849303">"TTY dezactivat"</item>
<item msgid="1449091874731375214">"TTY integral"</item>
@@ -605,32 +605,32 @@
<item msgid="2131559553795606483">"TTY VCO"</item>
</string-array>
<string name="dtmf_tones_title" msgid="7874845461117175236">"Tonuri DTMF"</string>
- <string name="dtmf_tones_summary" msgid="2294822239899471201">"Setați lungimea tonurilor DTMF"</string>
+ <string name="dtmf_tones_summary" msgid="2294822239899471201">"Setează lungimea tonurilor DTMF"</string>
<string-array name="dtmf_tone_entries">
<item msgid="2271798469250155310">"Normală"</item>
<item msgid="6044210222666533564">"Lung"</item>
</string-array>
<string name="network_info_message" msgid="7599413947016532355">"Mesaj de rețea"</string>
<string name="network_error_message" msgid="4271579424089326618">"Mesaj de eroare"</string>
- <string name="ota_title_activate" msgid="4049645324841263423">"Activați-vă telefonul"</string>
- <string name="ota_touch_activate" msgid="838764494319694754">"Pentru a vă activa serviciul de telefonie, trebuie să efectuați un apel special. \n\nDupă ce apăsați „Activați”, ascultați instrucțiunile furnizate pentru a vă activa telefonul."</string>
+ <string name="ota_title_activate" msgid="4049645324841263423">"Activează-ți telefonul"</string>
+ <string name="ota_touch_activate" msgid="838764494319694754">"Pentru a-ți activa serviciul de telefonie, trebuie să efectuezi un apel special. \n\nDupă ce apeși „Activează”, ascultă instrucțiunile furnizate pentru a-ți activa telefonul."</string>
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Se activează..."</string>
- <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Serviciul de date mobile este în curs de activare pe telefonul dvs.\n\nAcest proces poate dura până la 5 minute."</string>
- <string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Omiteți activarea?"</string>
- <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Dacă omiteți activarea, nu puteți efectua apeluri și nici nu vă puteți conecta la o rețea de date mobilă (deși vă puteți conecta la rețele Wi-Fi). Până veți activa telefonul, vi se va solicita să-l activați de fiecare dată când îl porniți."</string>
- <string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Omiteți"</string>
- <string name="ota_activate" msgid="7939695753665438357">"Activați"</string>
+ <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Serviciul de date mobile este în curs de activare pe telefonul tău.\n\nAcest proces poate dura până la 5 minute."</string>
+ <string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Omiți activarea?"</string>
+ <string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Dacă omiți activarea, nu poți efectua apeluri și nici nu te poți conecta la o rețea de date mobilă (deși te poți conecta la rețele Wi-Fi). Până vei activa telefonul, ți se va solicita să-l activezi de fiecare dată când îl pornești."</string>
+ <string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Omite"</string>
+ <string name="ota_activate" msgid="7939695753665438357">"Activează"</string>
<string name="ota_title_activate_success" msgid="1272135024761004889">"Telefonul este activat."</string>
<string name="ota_title_problem_with_activation" msgid="7019745985413368726">"Problemă de activare"</string>
- <string name="ota_listen" msgid="2772252405488894280">"Urmăriți instrucțiunile rostite până când veți auzi că activarea este finalizată."</string>
+ <string name="ota_listen" msgid="2772252405488894280">"Urmărește instrucțiunile rostite până când vei auzi că activarea este finalizată."</string>
<string name="ota_speaker" msgid="1086766980329820528">"Difuzor"</string>
<string name="ota_progress" msgid="8837259285255700132">"Se programează telefonul…"</string>
<string name="ota_failure" msgid="5674217489921481576">"Telefonul nu a putut fi programat"</string>
- <string name="ota_successful" msgid="1106825981548107774">"Telefonul dvs. este acum activat. Poate să dureze până la 15 minute până la pornirea serviciului."</string>
- <string name="ota_unsuccessful" msgid="8531037653803955754">"Telefonul dvs. nu s-a activat. \nVă recomandăm să găsiți o zonă cu acoperire mai bună (lângă fereastră sau afară). \n\nPentru mai multe opțiuni, încercați din nou sau apelați serviciul pentru clienți."</string>
+ <string name="ota_successful" msgid="1106825981548107774">"Telefonul tău este acum activat. Poate să dureze până la 15 minute până la pornirea serviciului."</string>
+ <string name="ota_unsuccessful" msgid="8531037653803955754">"Telefonul tău nu s-a activat. \nÎți recomandăm să găsești o zonă cu acoperire mai bună (lângă fereastră sau afară). \n\nPentru mai multe opțiuni, încearcă din nou sau apelează serviciul pentru clienți."</string>
<string name="ota_spc_failure" msgid="904092035241370080">"ERORI DE DEPĂȘIRE SPC"</string>
<string name="ota_call_end" msgid="8657746378290737034">"Înapoi"</string>
- <string name="ota_try_again" msgid="6914781945599998550">"Încercați din nou"</string>
+ <string name="ota_try_again" msgid="6914781945599998550">"Încearcă din nou"</string>
<string name="ota_next" msgid="2041016619313475914">"Înainte"</string>
<string name="ecm_exit_dialog" msgid="4200691880721429078">"EcmExitDialog"</string>
<string name="phone_entered_ecm_text" msgid="8431238297843035842">"S-a activat modul de apelare inversă de urgență"</string>
@@ -643,7 +643,7 @@
<string name="progress_dialog_exiting_ecm" msgid="9159080081676927217">"Se iese din modul Apelare inversă de urgență"</string>
<string name="alert_dialog_yes" msgid="3532525979632841417">"Da"</string>
<string name="alert_dialog_no" msgid="1075632654085988420">"Nu"</string>
- <string name="alert_dialog_dismiss" msgid="1336356286354517054">"Renunțați"</string>
+ <string name="alert_dialog_dismiss" msgid="1336356286354517054">"Renunță"</string>
<string name="phone_in_ecm_call_notification_text_without_data_restriction_hint" msgid="3747860785153531225">"Telefonul va fi în modul Apelare inversă de urgență"</string>
<string name="phone_in_ecm_notification_complete_time_without_data_restriction_hint" msgid="3690292264812050858">"Până la <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
<!-- format error in translation for alert_dialog_exit_ecm_without_data_restriction_hint (7549850847524907932) -->
@@ -657,17 +657,17 @@
<string name="selectContact" msgid="1527612842599767382">"selectarea unei persoane din agendă"</string>
<string name="not_voice_capable" msgid="2819996734252084253">"Apelarea vocală nu este acceptată"</string>
<string name="description_dial_button" msgid="8614631902795087259">"apelare"</string>
- <string name="description_dialpad_button" msgid="7395114120463883623">"afișați tastatura numerică"</string>
+ <string name="description_dialpad_button" msgid="7395114120463883623">"afișează tastatura numerică"</string>
<string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Tastatură pentru apeluri de urgență"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"Mesagerie vocală vizuală"</string>
- <string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"Setați codul PIN"</string>
- <string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Schimbați codul PIN"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"Setează codul PIN"</string>
+ <string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Schimbă codul PIN"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"Ton de apel și vibrare"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"Carduri SIM încorporate"</string>
- <string name="enable_video_calling_title" msgid="7246600931634161830">"Activați apelurile video"</string>
- <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Pentru a activa apelarea video, trebuie să activați Modul 4G LTE îmbunătățit în setările pentru rețea."</string>
+ <string name="enable_video_calling_title" msgid="7246600931634161830">"Activează apelurile video"</string>
+ <string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"Pentru a activa apelarea video, trebuie să activezi Modul 4G LTE îmbunătățit în setările pentru rețea."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"Setări de rețea"</string>
- <string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Închideți"</string>
+ <string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Închide"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"Apeluri de urgență"</string>
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"Numai apeluri de urgență"</string>
<string name="sim_description_default" msgid="7474671114363724971">"Cardul SIM, slotul: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
@@ -676,22 +676,22 @@
<string name="status_hint_label_wifi_call" msgid="942993035689809853">"Apel prin Wi-Fi"</string>
<string name="message_decode_error" msgid="1061856591500290887">"A apărut o eroare la decodificarea mesajului."</string>
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"Un card SIM a activat serviciul și a actualizat funcțiile de roaming ale telefonului."</string>
- <string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Prea multe apeluri active. Încheiați sau îmbinați apeluri existente înainte de a iniția unul nou."</string>
- <string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Nu v-ați conectat. Inserați un card SIM valid."</string>
+ <string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"Prea multe apeluri active. Încheie sau îmbină apeluri existente înainte de a iniția unul nou."</string>
+ <string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"Nu te-ai conectat. Inserează un card SIM valid."</string>
<string name="callFailed_wifi_lost" msgid="1788036730589163141">"Conexiunea Wi-Fi s-a pierdut. Apelul a fost încheiat."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"Apelul video nu a putut fi inițiat din cauza epuizării bateriei."</string>
<string name="callFailed_low_battery" msgid="4056828320214416182">"Apelul video s-a încheiat din cauza epuizării bateriei."</string>
<string name="callFailed_emergency_call_over_wfc_not_available" msgid="5944309590693432042">"Apelurile de urgență inițiate prin apelarea prin Wi-Fi nu sunt disponibile în această locație."</string>
<string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"Apelarea prin Wi-fi nu este disponibilă în această locație."</string>
- <string name="change_pin_title" msgid="3564254326626797321">"Schimbați codul PIN pentru mesageria vocală"</string>
- <string name="change_pin_continue_label" msgid="5177011752453506371">"Continuați"</string>
- <string name="change_pin_cancel_label" msgid="2301711566758827936">"Anulați"</string>
+ <string name="change_pin_title" msgid="3564254326626797321">"Schimbă codul PIN pentru mesageria vocală"</string>
+ <string name="change_pin_continue_label" msgid="5177011752453506371">"Continuă"</string>
+ <string name="change_pin_cancel_label" msgid="2301711566758827936">"Anulează"</string>
<string name="change_pin_ok_label" msgid="6861082678817785330">"OK"</string>
- <string name="change_pin_enter_old_pin_header" msgid="853151335217594829">"Confirmați vechiul cod PIN"</string>
- <string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"Introduceți codul PIN pentru mesageria vocală pentru a continua."</string>
- <string name="change_pin_enter_new_pin_header" msgid="4739465616733486118">"Setați un cod PIN nou"</string>
+ <string name="change_pin_enter_old_pin_header" msgid="853151335217594829">"Confirmă vechiul cod PIN"</string>
+ <string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"Introdu codul PIN pentru mesageria vocală pentru a continua."</string>
+ <string name="change_pin_enter_new_pin_header" msgid="4739465616733486118">"Setează un cod PIN nou"</string>
<string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"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="2606303906320705726">"Confirmați codul PIN"</string>
+ <string name="change_pin_confirm_pin_header" msgid="2606303906320705726">"Confirmă codul PIN"</string>
<string name="change_pin_confirm_pins_dont_match" msgid="305164501222587215">"Codurile PIN nu corespund"</string>
<string name="change_pin_succeeded" msgid="2504705600693014403">"Codul PIN pentru mesageria vocală a fost actualizat"</string>
<string name="change_pin_system_error" msgid="7772788809875146873">"Nu s-a putut seta codul PIN"</string>
@@ -699,21 +699,21 @@
<string name="mobile_data_status_roaming_turned_on_subtext" msgid="5615757897768777865">"Roamingul de date este activat."</string>
<string name="mobile_data_status_roaming_without_plan_subtext" msgid="6536671968072284677">"În prezent, se folosește roaming. Este necesar un abonament de date."</string>
<string name="mobile_data_status_roaming_with_plan_subtext" msgid="2576177169108123095">"În prezent, se folosește roaming. Abonamentul de date este activ."</string>
- <string name="mobile_data_status_no_plan_subtext" msgid="170331026419263657">"Ați epuizat abonamentul de date mobile."</string>
- <string name="mobile_data_activate_prepaid" msgid="4276738964416795596">"Ați epuizat abonamentul de date mobile."</string>
- <string name="mobile_data_activate_prepaid_summary" msgid="6846085278531605925">"Adăugați date mobile prin <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
+ <string name="mobile_data_status_no_plan_subtext" msgid="170331026419263657">"Ai epuizat abonamentul de date mobile."</string>
+ <string name="mobile_data_activate_prepaid" msgid="4276738964416795596">"Ai epuizat abonamentul de date mobile."</string>
+ <string name="mobile_data_activate_prepaid_summary" msgid="6846085278531605925">"Adaugă date mobile prin <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
<string name="mobile_data_activate_roaming_plan" msgid="922290995866269366">"Niciun abonament de roaming"</string>
- <string name="mobile_data_activate_roaming_plan_summary" msgid="5379228493306235969">"Adăugați un abonament de roaming prin <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
- <string name="mobile_data_activate_footer" msgid="7895874069807204548">"Puteți adăuga un abonament de date mobile sau de roaming prin operatorul dvs., <xliff:g id="PROVIDER_NAME">%s</xliff:g>."</string>
- <string name="mobile_data_activate_diag_title" msgid="5401741936224757312">"Adăugați date?"</string>
- <string name="mobile_data_activate_diag_message" msgid="3527260988020415441">"Poate fi necesar să adăugați date prin <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
- <string name="mobile_data_activate_button" msgid="1139792516354374612">"ADĂUGAȚI DATE"</string>
- <string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"ANULAȚI"</string>
+ <string name="mobile_data_activate_roaming_plan_summary" msgid="5379228493306235969">"Adaugă un abonament de roaming prin <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
+ <string name="mobile_data_activate_footer" msgid="7895874069807204548">"Poți adăuga un abonament de date mobile sau de roaming prin operatorul tău, <xliff:g id="PROVIDER_NAME">%s</xliff:g>."</string>
+ <string name="mobile_data_activate_diag_title" msgid="5401741936224757312">"Adaugi date?"</string>
+ <string name="mobile_data_activate_diag_message" msgid="3527260988020415441">"Poate fi necesar să adaugi date prin <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
+ <string name="mobile_data_activate_button" msgid="1139792516354374612">"ADAUGĂ DATE"</string>
+ <string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"ANULEAZĂ"</string>
<string name="clh_card_title_call_ended_txt" msgid="5977978317527299698">"Apel încheiat"</string>
<string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"Modul Avion este activat"</string>
<string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"Nu se poate accesa cardul SIM"</string>
<string name="clh_incall_error_out_of_service_txt" msgid="2736010617446749869">"Rețeaua mobilă nu este disponibilă"</string>
- <string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"A apărut o problemă legată de numărul de telefon pe care încercați să-l apelați. Cod de eroare 1."</string>
+ <string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"A apărut o problemă legată de numărul de telefon pe care încerci să-l apelezi. Cod de eroare 1."</string>
<string name="clh_callFailed_no_route_to_destination_txt" msgid="4805015149822352308">"Nu s-a finalizat apelul. Cod de eroare 3."</string>
<string name="clh_callFailed_channel_unacceptable_txt" msgid="4062754579408613021">"Nu s-a finalizat apelul. Cod de eroare 6."</string>
<string name="clh_callFailed_operator_determined_barring_txt" msgid="4202077821465974286">"Nu s-a finalizat apelul. Cod de eroare 8."</string>
@@ -766,36 +766,36 @@
<string name="sum_call_barring_enabled" msgid="5184331188926370824">"Activat"</string>
<string name="sum_call_barring_disabled" msgid="5699448000600153096">"Dezactivat"</string>
<string name="call_barring_baoc" msgid="7400892586336429326">"Toate apelurile efectuate"</string>
- <string name="call_barring_baoc_enabled" msgid="3131509193386668182">"Dezactivați blocarea tuturor apelurilor efectuate?"</string>
- <string name="call_barring_baoc_disabled" msgid="8534224684091141509">"Blocați toate apelurile efectuate?"</string>
+ <string name="call_barring_baoc_enabled" msgid="3131509193386668182">"Dezactivezi blocarea tuturor apelurilor efectuate?"</string>
+ <string name="call_barring_baoc_disabled" msgid="8534224684091141509">"Blochezi toate apelurile efectuate?"</string>
<string name="call_barring_baoic" msgid="8668125428666851665">"Apeluri internaționale efectuate"</string>
- <string name="call_barring_baoic_enabled" msgid="1203758092657630123">"Dezactivați blocarea apelurilor internaționale efectuate?"</string>
- <string name="call_barring_baoic_disabled" msgid="5656889339002997449">"Blocați apelurile internaționale efectuate?"</string>
+ <string name="call_barring_baoic_enabled" msgid="1203758092657630123">"Dezactivezi blocarea apelurilor internaționale efectuate?"</string>
+ <string name="call_barring_baoic_disabled" msgid="5656889339002997449">"Blochezi apelurile internaționale efectuate?"</string>
<string name="call_barring_baoicr" msgid="8566167764432343487">"Roaming pentru apeluri internaționale efectuate"</string>
- <string name="call_barring_baoicr_enabled" msgid="1615324165512798478">"Dezactivați blocarea apelurilor internaționale efectuate prin roaming?"</string>
- <string name="call_barring_baoicr_disabled" msgid="172010175248142831">"Blocați apelurile internaționale efectuate prin roaming?"</string>
+ <string name="call_barring_baoicr_enabled" msgid="1615324165512798478">"Dezactivezi blocarea apelurilor internaționale efectuate prin roaming?"</string>
+ <string name="call_barring_baoicr_disabled" msgid="172010175248142831">"Blochează apelurile internaționale efectuate prin roaming?"</string>
<string name="call_barring_baic" msgid="7941393541678658566">"Toate primite"</string>
- <string name="call_barring_baic_enabled" msgid="4357332358020337470">"Dezactivați blocarea tuturor apelurilor primite?"</string>
- <string name="call_barring_baic_disabled" msgid="2355945245938240958">"Blocați toate apelurile primite?"</string>
+ <string name="call_barring_baic_enabled" msgid="4357332358020337470">"Dezactivezi blocarea tuturor apelurilor primite?"</string>
+ <string name="call_barring_baic_disabled" msgid="2355945245938240958">"Blochezi toate apelurile primite?"</string>
<string name="call_barring_baicr" msgid="8712249337313034226">"Roaming pentru apeluri internaționale primite"</string>
- <string name="call_barring_baicr_enabled" msgid="64774270234828175">"Dezactivați blocarea toate apelurile internaționale primite prin roaming?"</string>
- <string name="call_barring_baicr_disabled" msgid="3488129262744027262">"Blocați roamingul pentru apeluri internaționale primite?"</string>
- <string name="call_barring_deactivate_all" msgid="7837931580047157328">"Dezactivați tot"</string>
- <string name="call_barring_deactivate_all_description" msgid="4474119585042121604">"Dezactivați toate setările de restricționare a apelurilor"</string>
+ <string name="call_barring_baicr_enabled" msgid="64774270234828175">"Dezactivezi blocarea tuturor apelurilor internaționale primite prin roaming?"</string>
+ <string name="call_barring_baicr_disabled" msgid="3488129262744027262">"Blochează roamingul pentru apeluri internaționale primite?"</string>
+ <string name="call_barring_deactivate_all" msgid="7837931580047157328">"Dezactivează tot"</string>
+ <string name="call_barring_deactivate_all_description" msgid="4474119585042121604">"Dezactivează toate setările de restricționare a apelurilor"</string>
<string name="call_barring_deactivate_success" msgid="3545644320298275337">"Restricționarea apelurilor este dezactivată"</string>
- <string name="call_barring_change_pwd" msgid="1730691950940338387">"Schimbați parola"</string>
- <string name="call_barring_change_pwd_description" msgid="1274245130382054227">"Schimbați parola pentru restricționarea apelurilor"</string>
+ <string name="call_barring_change_pwd" msgid="1730691950940338387">"Schimbă parola"</string>
+ <string name="call_barring_change_pwd_description" msgid="1274245130382054227">"Schimbă parola pentru restricționarea apelurilor"</string>
<string name="call_barring_change_pwd_description_disabled" msgid="2911647051915343920">"Nu se poate schimba parola pentru restricționarea apelurilor"</string>
<string name="call_barring_pwd_not_match" msgid="7638198747579019826">"Parolele nu se potrivesc"</string>
- <string name="call_barring_right_pwd_number" msgid="3860630926460851330">"Introduceți o parolă cu 4 cifre"</string>
+ <string name="call_barring_right_pwd_number" msgid="3860630926460851330">"Introdu o parolă cu 4 cifre"</string>
<string name="call_barring_change_pwd_success" msgid="1837437691277936903">"Parola a fost modificată"</string>
<string name="call_barring_old_pwd" msgid="5500085633281388281">"Parolă veche"</string>
<string name="call_barring_new_pwd" msgid="2515524903813227732">"Parolă nouă"</string>
- <string name="call_barring_confirm_pwd" msgid="7552526161616461858">"Confirmați parola"</string>
- <string name="messageCallBarring" msgid="5537730400652466912">"Introduceți parola"</string>
+ <string name="call_barring_confirm_pwd" msgid="7552526161616461858">"Confirmă parola"</string>
+ <string name="messageCallBarring" msgid="5537730400652466912">"Introdu parola"</string>
<string name="call_barring_settings" msgid="4616607285790258919">"Setări de restricționare a apelurilor"</string>
- <string name="callFailed_NetworkBusy" msgid="5437103975842913681">"Rețeaua este ocupată. Încercați să apelați din nou mai târziu."</string>
- <string name="callFailed_NetworkCongested" msgid="6801283142342775380">"Rețeaua este aglomerată. Contactați operatorul de telefonie mobilă pentru a cere asistență."</string>
+ <string name="callFailed_NetworkBusy" msgid="5437103975842913681">"Rețeaua este ocupată. Încearcă să apelezi din nou mai târziu."</string>
+ <string name="callFailed_NetworkCongested" msgid="6801283142342775380">"Rețeaua este aglomerată. Contactează operatorul de telefonie mobilă pentru a cere asistență."</string>
<string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"Apelul a fost deviat."</string>
<string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"Apelul a fost redirecționat."</string>
<string name="supp_service_notification_call_waiting" msgid="4577403881609445324">"Apelul este în așteptare."</string>
@@ -811,34 +811,36 @@
<string name="supp_service_call_resumed" msgid="3786864005920743546">"S-a reluat apelul."</string>
<string name="supp_service_deflected_call" msgid="7565979024562921707">"Apelul a fost deviat."</string>
<string name="supp_service_forwarded_call" msgid="6475776013771821457">"Apel redirecționat"</string>
- <string name="supp_service_conference_call" msgid="4004193534408317148">"Vă conectați la conferința telefonică."</string>
+ <string name="supp_service_conference_call" msgid="4004193534408317148">"Te conectezi la conferința telefonică."</string>
<string name="supp_service_held_call_released" msgid="2847835124639112410">"Apelul în așteptare a fost deconectat."</string>
<string name="callFailed_otasp_provisioning_in_process" msgid="3345666183602879326">"Nu se poate iniția un apel, deoarece, momentan, are loc provizionarea dispozitivului."</string>
<string name="callFailed_already_dialing" msgid="7250591188960691086">"Nu se poate iniția un apel când se efectuează deja alt apel."</string>
- <string name="callFailed_already_ringing" msgid="2376603543544289303">"Nu se poate iniția un apel când primiți un apel la care nu ați răspuns. Răspundeți sau respingeți apelul primit înainte de a iniția un apel nou."</string>
+ <string name="callFailed_already_ringing" msgid="2376603543544289303">"Nu se poate iniția un apel când primești un apel la care nu ai răspuns. Răspunde sau respinge apelul primit înainte de a iniția un apel nou."</string>
<string name="callFailed_calling_disabled" msgid="5010992739401206283">"Nu se poate iniția un apel deoarece apelarea a fost dezactivată folosindu-se funcția de sistem ro.telephony.disable-call."</string>
- <string name="callFailed_too_many_calls" msgid="2761754044990799580">"Nu se poate iniția un apel când există deja două apeluri în desfășurare. Deconectați unul dintre ele sau îmbinați-le într-o conferință înainte de a iniția un apel nou."</string>
- <string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"Pentru a folosi <xliff:g id="SUPP_SERVICE">%s</xliff:g>, datele mobile trebuie să fie activate. Puteți modifica acest lucru în setările rețelei mobile."</string>
- <string name="supp_service_over_ut_precautions_roaming" msgid="670342104569972327">"Pentru a folosi <xliff:g id="SUPP_SERVICE">%s</xliff:g>, datele mobile și roamingul de date trebuie să fie activate. Puteți modifica acest lucru în setările rețelei mobile."</string>
- <string name="supp_service_over_ut_precautions_dual_sim" msgid="5166866975550910474">"Pentru a folosi <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, datele mobile trebuie să fie activate pentru cardul SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g>. Puteți modifica acest lucru în setările rețelei mobile."</string>
- <string name="supp_service_over_ut_precautions_roaming_dual_sim" msgid="6627654855191817965">"Pentru a folosi <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, datele mobile și roamingul de date trebuie să fie activate pentru cardul SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g>. Puteți modifica acest lucru în setările rețelei mobile."</string>
- <string name="supp_service_over_ut_precautions_dialog_dismiss" msgid="5934541487903081652">"Închideți"</string>
- <string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Activați conexiunea de date"</string>
- <string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Dezactivați conexiunea de date"</string>
+ <string name="callFailed_too_many_calls" msgid="2761754044990799580">"Nu se poate iniția un apel când există deja două apeluri în desfășurare. Deconectează unul dintre ele sau îmbină-le într-o conferință înainte de a iniția un apel nou."</string>
+ <string name="supp_service_over_ut_precautions" msgid="2145018231396701311">"Pentru a folosi <xliff:g id="SUPP_SERVICE">%s</xliff:g>, datele mobile trebuie să fie activate. Poți modifica acest lucru în setările rețelei mobile."</string>
+ <string name="supp_service_over_ut_precautions_roaming" msgid="670342104569972327">"Pentru a folosi <xliff:g id="SUPP_SERVICE">%s</xliff:g>, datele mobile și roamingul de date trebuie să fie activate. Poți modifica acest lucru în setările rețelei mobile."</string>
+ <string name="supp_service_over_ut_precautions_dual_sim" msgid="5166866975550910474">"Pentru a folosi <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, datele mobile trebuie să fie activate pentru cardul SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g>. Poți modifica acest lucru în setările rețelei mobile."</string>
+ <string name="supp_service_over_ut_precautions_roaming_dual_sim" msgid="6627654855191817965">"Pentru a folosi <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, datele mobile și roamingul de date trebuie să fie activate pentru cardul SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g>. Poți modifica acest lucru în setările rețelei mobile."</string>
+ <string name="supp_service_over_ut_precautions_dialog_dismiss" msgid="5934541487903081652">"Închide"</string>
+ <string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Activează conexiunea de date"</string>
+ <string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Dezactivează conexiunea de date"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"Oferit de VoLTE"</string>
<string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Apelarea video este configurată"</string>
<string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"Apelarea prin Wi-Fi este configurată"</string>
<string name="eab_provisioned_switch_string" msgid="4449676720736033035">"Setări configurate pentru EAB/prezență"</string>
<string name="cbrs_data_switch_string" msgid="6060356430838077653">"Date CBRS"</string>
- <string name="dsds_switch_string" msgid="7564769822086764796">"Activați DSDS"</string>
- <string name="dsds_dialog_title" msgid="8494569893941847575">"Reporniți dispozitivul?"</string>
- <string name="dsds_dialog_message" msgid="4047480385678538850">"Trebuie să reporniți dispozitivul pentru a modifica setarea."</string>
- <string name="dsds_dialog_confirm" msgid="9032004888134129885">"Reporniți"</string>
- <string name="dsds_dialog_cancel" msgid="3245958947099586655">"Anulați"</string>
+ <string name="dsds_switch_string" msgid="7564769822086764796">"Activează DSDS"</string>
+ <string name="dsds_dialog_title" msgid="8494569893941847575">"Repornești dispozitivul?"</string>
+ <string name="dsds_dialog_message" msgid="4047480385678538850">"Trebuie să repornești dispozitivul pentru a modifica setarea."</string>
+ <string name="dsds_dialog_confirm" msgid="9032004888134129885">"Repornește"</string>
+ <string name="dsds_dialog_cancel" msgid="3245958947099586655">"Anulează"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Setează cartela eSIM portabilă drept prestabilită"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Alimentare radio celular"</string>
- <string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Afișați agenda de pe SIM"</string>
- <string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Afișați numerele pentru apeluri restricționate"</string>
- <string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Vedeți numere de apelare de serviciu"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulează modul în afara ariei de acoperire (numai în versiunea pentru remedierea erorilor)"</string>
+ <string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Afișează agenda de pe SIM"</string>
+ <string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Afișează numerele pentru apeluri restricționate"</string>
+ <string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Vezi numere de apelare de serviciu"</string>
<string name="radioInfo_menu_getIMS" msgid="1950869267853198232">"Starea serviciului IMS"</string>
<string name="radio_info_ims_reg_status_title" msgid="6875885401313992007">"Stare IMS"</string>
<string name="radio_info_ims_reg_status_registered" msgid="7095182114078864326">"Înregistrat"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Conectat"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Suspendat"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Necunoscut"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Principal"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pachete"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"byți"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -886,39 +889,40 @@
<string name="radio_info_ppp_sent_label" msgid="6542208429356199695">"Date trimise:"</string>
<string name="radio_info_message_waiting_label" msgid="1886549432566952078">"Mesaj în așteptare:"</string>
<string name="radio_info_phone_number_label" msgid="2533852539562512203">"Număr de telefon:"</string>
- <string name="radio_info_band_mode_label" msgid="23480556225515290">"Selectați banda radio"</string>
+ <string name="radio_info_band_mode_label" msgid="23480556225515290">"Selectează banda radio"</string>
<string name="radio_info_voice_network_type_label" msgid="2395347336419593265">"Tipul rețelei de voce:"</string>
<string name="radio_info_data_network_type_label" msgid="8886597029237501929">"Tipul rețelei de date:"</string>
- <string name="radio_info_override_network_type_label" msgid="4176280017221092005">"Modificați tipul de rețea:"</string>
- <string name="phone_index_label" msgid="6222406512768964268">"Selectați indexul telefonului"</string>
+ <string name="radio_info_override_network_type_label" msgid="4176280017221092005">"Modifică tipul de rețea:"</string>
+ <string name="phone_index_label" msgid="6222406512768964268">"Selectează indexul telefonului"</string>
<string name="radio_info_set_perferred_label" msgid="7408131389363136210">"Setați tipul preferat de rețea:"</string>
- <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Dați ping adresei IPv4 a numelui de gazdă (www.google.com):"</string>
- <string name="radio_info_ping_hostname_v6" msgid="2748637889486554603">"Dați ping adresei IPv6 a numelui de gazdă (www.google.com):"</string>
+ <string name="radio_info_ping_hostname_v4" msgid="6951237885381284790">"Dă ping adresei IPv4 a numelui de gazdă (www.google.com):"</string>
+ <string name="radio_info_ping_hostname_v6" msgid="2748637889486554603">"Dă ping adresei IPv6 a numelui de gazdă (www.google.com):"</string>
<string name="radio_info_http_client_test" msgid="1329583721088428238">"Test client HTTP:"</string>
- <string name="ping_test_label" msgid="448617502935719694">"Efectuați testul de ping"</string>
+ <string name="ping_test_label" msgid="448617502935719694">"Efectuează testul de ping"</string>
<string name="radio_info_smsc_label" msgid="3749927072726033763">"SMSC:"</string>
- <string name="radio_info_smsc_update_label" msgid="5141996256097115753">"Actualizați"</string>
- <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualizați"</string>
- <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Activați/dezactivați verificarea DNS"</string>
+ <string name="radio_info_smsc_update_label" msgid="5141996256097115753">"Actualizează"</string>
+ <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"Actualizează"</string>
+ <string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"Activează/dezactivează verificarea DNS"</string>
<string name="oem_radio_info_label" msgid="2914167475119997456">"Informații/Setări caracteristice OEM"</string>
<string name="radio_info_endc_available" msgid="2983767110681230019">"Disponibil EN-DC (NSA):"</string>
<string name="radio_info_dcnr_restricted" msgid="7147511536420148173">"Restricționat DCNR (NSA):"</string>
<string name="radio_info_nr_available" msgid="3383388088451237182">"Disponibil NR (NSA):"</string>
<string name="radio_info_nr_state" msgid="4158805093187555149">"Stare NR (NSA):"</string>
<string name="radio_info_nr_frequency" msgid="1201156032796584128">"Frecvență NR:"</string>
- <string name="band_mode_title" msgid="7988822920724576842">"Setați Modul bandă radio"</string>
+ <string name="band_mode_title" msgid="7988822920724576842">"Setează Modul bandă radio"</string>
<string name="band_mode_loading" msgid="795923726636735967">"Se încarcă lista de benzi…"</string>
- <string name="band_mode_set" msgid="6657819412803771421">"Setați"</string>
+ <string name="band_mode_set" msgid="6657819412803771421">"Setează"</string>
<string name="band_mode_failed" msgid="1707488541847192924">"Nereușit"</string>
<string name="band_mode_succeeded" msgid="2230018000534761063">"Reușit"</string>
<string name="phone_info_label" product="tablet" msgid="7477478709388477397">"Informații tabletă"</string>
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informații despre telefon"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informații despre provizionarea operatorului"</string>
- <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Declanșați provizionarea operatorului"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Cod pentru dreptul de acces WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Actualizați"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Actualizați"</string>
- <string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Semnalul Bluetooth este slab. Încercați să folosiți difuzorul."</string>
+ <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Declanșează provizionarea operatorului"</string>
+ <string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Semnalul Bluetooth este slab. Încearcă să folosești difuzorul."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notificare privind calitatea apelului"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Conturi SIP învechite"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Nu se poate trimite un mesaj de pe acest profil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Politica privind activitatea îți permite să trimiți mesaje numai din profilul de serviciu"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Anulează"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Comută la profilul de serviciu"</string>
</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index 7353539..3fd7d03 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -670,7 +670,7 @@
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"Закрыть"</string>
<string name="sim_label_emergency_calls" msgid="9078241989421522310">"Экстренные вызовы"</string>
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"Только экстренные вызовы"</string>
- <string name="sim_description_default" msgid="7474671114363724971">"SIM-карта, слот: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
+ <string name="sim_description_default" msgid="7474671114363724971">"SIM-карта <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"Специальные возможности"</string>
<string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Вызов по Wi-Fi от"</string>
<string name="status_hint_label_wifi_call" msgid="942993035689809853">"Wi-Fi-звонок"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Чтобы изменить эту настройку, перезапустите устройство."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Перезапустить"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Отмена"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Установить съемную eSIM-карту в качестве используемой по умолчанию"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Мощность радиосигнала"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Моделирование нахождения вне зоны обслуживания (только отладочная сборка)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Посмотреть адресную книгу на SIM-карте"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Список разрешенных номеров"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Посмотреть номера служебного набора"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Подключено"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Заблокировано"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Неизвестно"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Основной"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"байт"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,13 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Информация о телефоне"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Сведения о синхронизации оператора"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Запустить синхронизацию оператора"</string>
- <!-- no translation found for provisioning_info_wfc_entitlement_id (8845188780811890910) -->
- <skip />
- <!-- no translation found for update_provisioning_info_wfc_entitlement_id (7044171908781134221) -->
- <skip />
- <!-- no translation found for refresh_provisioning_info_wfc_entitlement_id (738894335351353407) -->
- <skip />
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Слабый сигнал Bluetooth. Попробуйте переключиться на громкую связь."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Уведомление о качестве связи"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Неподдерживаемые SIP-аккаунты"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Нельзя отправить сообщение из этого профиля"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Согласно правилам вашей организации вы можете отправлять сообщения только из рабочего профиля."</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Отмена"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Перейти в рабочий профиль"</string>
</resources>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 2d387f4..735a538 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"මෙම සැකසීම වෙනස් කිරීමට ඔබ ඔබේ උපාංගය යළි ඇරඹීමට අවශ්යයි."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"යළි අරඹන්න"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"අවලංගු කරන්න"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"ඉවත් කළ හැකි eSIM පෙරනිමිය ලෙස සකසන්න"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"ජංගම රේඩියෝ බලය"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"සේවයෙන් බැහැරව අනුකරණය කරන්න (නිදොස් තැනුම පමණි)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM ලිපින පොත බලන්න"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ස්ථාවර ඇමතුම් අංක පෙන්වන්න"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"සේවා ඩයල් කිරීමේ අංක පෙන්වන්න"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"සම්බන්ධිතයි"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"අත්හිටුවා ඇත"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"නොදන්නා"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"මූලික"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"බයිට"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"දුරකථන තොරතුරු"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"වාහක ප්රතිපාදන තතු"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"උත්ප්රේරක වාහක ප්රතිපාදන"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC හිමිකම් ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"යාවත්කාලීන කරන්න"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"නැවුම් කරන්න"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"ඔබේ බ්ලූටූත් සංඥාව දුර්වලයි. ස්පීකර් දුරකථනයට මාරු වීමට උත්සාහ කරන්න."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"ඇමතුම් ගුණත්ව දැනුම්දීම"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"අතහැර දැමූ SIP ගිණුම්"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"මෙම පැතිකඩෙන් පණිවිඩ යැවිය නොහැක"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"ඔබේ වැඩ ප්රතිපත්තිය ඔබට කාර්යාල පැතිකඩෙන් පමණක් පණිවිඩ යැවීමට ඉඩ දෙයි"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"අවලංගු කරන්න"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"කාර්යාල පැතිකඩ වෙත මාරු වන්න"</string>
</resources>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index f4b13e7..68a873f 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Ak chcete zmeniť nastavenie, musíte reštartovať zariadenie."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Reštartovať"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Zrušiť"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Nastaviť odoberateľnú eSIM kartu ako predvolenú"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Sila signálu GSM"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulácia nefungujúceho zariadenia (možné iba v ladiacej zostave)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Zobraziť adresár SIM karty"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Zobraziť povolené čísla"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Zobraziť čísla volaní služieb"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Pripojené"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Pozastavené"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Neznáme"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primárne"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pakety"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"B"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informácie o telefóne"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informácie o poskytovaní služieb operátorom"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Spustiť poskytovanie služieb operátorom"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Identifikátor oprávnenia služby WFC"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Aktualizovať"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Obnoviť"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Signál Bluetooth je slabý. Skúste prepnúť na reproduktor."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Upozornenie o kvalite hovoru"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Účty SIP s ukončenou podporou"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Z tohto profilu nemôžete odosielať správy"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Pracovné pravidlá vám umožňujú odosielať správy iba v pracovnom profile"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Zrušiť"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Prepnúť na pracovný profil"</string>
</resources>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 89ca6d5..2fdbf8e 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Če želite spremeniti to nastavitev, znova zaženite napravo."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Vnovičen zagon"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Prekliči"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Nastavi izmenljivo kartico e-SIM kot privzeto"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Moč radia mobilne naprave"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulacija nedelovanja (samo za gradnjo za odpravljanje napak)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Prikaži imenik na kartici SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Prikaži številke za zaporo odhodnih klicev"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Prikaži številke za klicanje storitev"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Povezano"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Onemogočeno"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Neznano"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Glavno"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"B"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacije o telefonu"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Podatki o omogočanju uporabe operaterja"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Sproži omogočanje uporabe operaterja"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID upravičenosti za WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Posodobi"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Osveži"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Signal povezave Bluetooth je šibek. Poskusite preklopiti na zvočnik."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Obvestilo o kakovosti klica"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Opuščeni računi SIP"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Sporočila ni mogoče poslati iz tega profila"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Službeni pravilnik dovoljuje pošiljanje sporočil le iz delovnega profila."</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Prekliči"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Preklopi na delovni profil"</string>
</resources>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 11fa7a9..7b3be3a 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -631,7 +631,7 @@
<string name="ota_spc_failure" msgid="904092035241370080">"DËSHTIME TË SHUMTA SPC"</string>
<string name="ota_call_end" msgid="8657746378290737034">"Prapa"</string>
<string name="ota_try_again" msgid="6914781945599998550">"Provo sërish"</string>
- <string name="ota_next" msgid="2041016619313475914">"Përpara"</string>
+ <string name="ota_next" msgid="2041016619313475914">"Para"</string>
<string name="ecm_exit_dialog" msgid="4200691880721429078">"EcmExitDialog"</string>
<string name="phone_entered_ecm_text" msgid="8431238297843035842">"Hyri në modalitetin e \"Kthimit të telefonatës së urgjencës\""</string>
<string name="phone_in_ecm_notification_title" msgid="6825016389926367946">"Modaliteti i \"Kthimit të telefonatës së urgjencës\""</string>
@@ -660,7 +660,7 @@
<string name="description_dialpad_button" msgid="7395114120463883623">"shfaq bllokun e formimit të numrit"</string>
<string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"Blloku i formimit të numrit të urgjencës"</string>
<string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"Posta zanore vizuale"</string>
- <string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"Konfiguro kodin PIN"</string>
+ <string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"Cakto kodin PIN"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"Ndrysho kodin PIN"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"Me zile dhe me dridhje"</string>
<string name="pstn_connection_service_label" msgid="9200102709997537069">"Kartat e integruara SIM"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Duhet të rinisësh pajisjen tënde për të ndryshuar këtë cilësim."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Rinis"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Anulo"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Caktoje kartën e lëvizshme eSIM si të parazgjedhur"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Fuqia e radios së rrjetit celular"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulo gjendjen jashtë shërbimit (vetëm versioni i korrigjimit)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Shiko librin e adresave të kartës SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Shiko numrat me telefonim të përzgjedhur"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Shiko numrat e telefonit të shërbimit"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Lidhur"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Pezulluar"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"E panjohur"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Kryesore"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"paketa"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bajte"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Informacioni i telefonit"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Informacionet e përgatitjes së operatorit celular"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktivizo përgatitjen e operatorit celular"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ID-ja e të drejtës për WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Përditëso"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Rifresko"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Sinjali i Bluetooth-it është i dobët. Provo të kalosh te altoparlanti."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Njoftim për cilësinë e telefonatës"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Llogaritë e zhvlerësuara SIP"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Mesazhi nuk mund të dërgohet nga ky profil"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Politika jote e punës të lejon të dërgosh mesazhe vetëm nga profili i punës"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Anulo"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Kalo te profili i punës"</string>
</resources>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index aefc325..e8376b6 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -305,7 +305,7 @@
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> – <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
<string name="mobile_data_settings_title" msgid="7228249980933944101">"Мобилни подаци"</string>
<string name="mobile_data_settings_summary" msgid="5012570152029118471">"Користи податке преко мобилне мреже"</string>
- <string name="data_usage_disable_mobile" msgid="5669109209055988308">"Желите ли да искључите мобилне податке?"</string>
+ <string name="data_usage_disable_mobile" msgid="5669109209055988308">"Желите да искључите мобилне податке?"</string>
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Потребно је да изаберете нешто"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"Да променимо SIM за податке?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"Желите ли да за мобилне податке користите <xliff:g id="NEW_SIM">%1$s</xliff:g> уместо <xliff:g id="OLD_SIM">%2$s</xliff:g>?"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Треба да рестартујте уређај да бисте променили ово подешавање."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Рестартуј"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Откажи"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Подеси преносиви eSIM као подразумевани"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Напајање за радио на мобилним уређајима"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Симулација не функционише (само верзија са отклоњеним грешкама)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Прикажи адресар SIM-а"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Прикажи бројеве за фиксно бирање"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Прикажи бројеве за сервисно бирање"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Повезано"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Суспендовано"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Непознато"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Примарно"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"пак."</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"бајт(ов)а"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Информације о телефону"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Информације о додели мобилног оператера"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Покретање доделе мобилног оператера"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"ИД права на WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Ажурирај"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Освежи"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth сигнал је слаб. Пробајте да пређете на спикерфон."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Обавештење о квалитету позива"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Застарели SIP налози"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Не можете да пошаљете поруку са овог профила"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Смернице за посао вам омогућавају да шаљете поруке само са пословног профила"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Откажи"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Пређи на пословни профил"</string>
</resources>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 9c9f495..a3c6e2c 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Du måste starta om enheten för att ändra den här inställningen."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Starta om"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Avbryt"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Ställ in Flyttbart eSIM som standard"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Strömförsörjning för mobilradio"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Simulera ur funktion (endast felsökningsversion)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Visa SIM-adressbok"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Visa Fasta nummer"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Visa tjänstenummer"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Ansluten"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Tillfälligt avstängt"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Okänt"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Primär"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"paket"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefoninformation"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Information om operatörsadministration"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Aktivera operatörsadministration"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC-berättigande-ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Uppdatera"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Uppdatera"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Svag Bluetooth-signal. Försök med att växla till högtalartelefon."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Avisering om samtalskvalitet"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Utfasade SIP-konton"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Det går inte att skicka meddelanden från den här profilen"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Jobbprincipen tillåter endast att skicka meddelanden från jobbprofilen"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Avbryt"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Byt till jobbprofilen"</string>
</resources>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index c2db54a..f276570 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Unahitaji kuzima kifaa chako na ukiwashe tena ili ubadilishe mipangilio hii."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Zima kisha uwashe"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Ghairi"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Weka eSIM Inayoweza Kuondolewa kama Chaguomsingi"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Nishati ya Redio ya Vifaa vya Mkononi"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Kifaa cha Kuiga Hakifanyi Kazi (Muundo wa Utatuzi pekee)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Angalia Kitabu cha Anwani katika SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Ona Nambari za Simu Zilizobainishwa"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Angalia Nambari Zilizowekwa na Mtoa Huduma"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Imeunganishwa"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Imesimamishwa"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Haijulikani"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Msingi"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"baiti"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Maelezo ya simu"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Maelezo ya Utaratibu wa Kutayarisha Mtandao"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Anzisha Utaratibu wa Kutayarisha Mtandao"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Kitambulisho cha Idhini ya WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Sasisha"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Onyesha upya"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Muunganisho wako wa bluetooth ni dhaifu. Jaribu kubadilisha ili utumie spika ya simu."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Arifa ya Ubora wa Simu"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Akaunti za SIP ambazo zimefungwa"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Huwezi kutuma ujumbe kutoka kwenye wasifu huu"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Sera ya mahali pako pa kazi inakuruhusu utume ujumbe kutoka kwenye wasifu wa kazini pekee"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Ghairi"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Tumia wasifu wa kazini"</string>
</resources>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 5da0add..b1e7e29 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"இந்த அமைப்பை மாற்ற சாதனத்தை மீண்டும் தொடங்க வேண்டும்."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"மீண்டும் தொடங்கு"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"ரத்துசெய்"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"அகற்றக்கூடிய eSIMமை இயல்பாக அமை"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"மொபைல் ரேடியோ பவர்"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"சாதனம் \'வேலை செய்யவில்லை\' என்பதை சிமுலேட் செய்தல் (பிழைதிருத்தப் பதிப்பில் மட்டும்)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"சிம் முகவரிப் புத்தகத்தைக் காட்டு"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"நிலையான அழைப்பு எண்களைக் காட்டு"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"சேவை அழைப்பு எண்களைக் காட்டு"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"இணைக்கப்பட்டுள்ளது"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"இடைநீக்கப்பட்டது"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"தெரியாதது"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"முதன்மை"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"பைட்டுகள்"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"மொபைலின் தகவல்"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Carrier Provisioning Info"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Trigger Carrier Provisioning"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC உரிமை வழங்கல் ஐடி:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"புதுப்பி"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ரெஃப்ரெஷ் செய்"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"புளூடூத் சிக்னல் வலுவற்றதாக உள்ளது. ஸ்பீக்கர் ஃபோனிற்கு மாற்றவும்."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"அழைப்பின் தரம் தொடர்பான அறிவிப்பு"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"நிறுத்தப்பட்ட SIP கணக்குகள்"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"இந்தச் சுயவிவரத்தில் இருந்து மெசேஜ் அனுப்ப முடியாது"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"உங்கள் பணிக் கொள்கையின்படி நீங்கள் பணிக் கணக்கில் இருந்து மட்டுமே மெசேஜ் அனுப்ப முடியும்"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"ரத்துசெய்"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"பணிக் கணக்கிற்கு மாறு"</string>
</resources>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index ccb1a5a..20589c1 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -30,7 +30,7 @@
<string name="mmiStarted" msgid="9212975136944568623">"MMI కోడ్ ప్రారంభించబడింది"</string>
<string name="ussdRunning" msgid="1163586813106772717">"USSD కోడ్ అమలు చేయబడుతోంది…"</string>
<string name="mmiCancelled" msgid="5339191899200678272">"MMI కోడ్ రద్దు చేయబడింది"</string>
- <string name="cancel" msgid="8984206397635155197">"రద్దు చేయి"</string>
+ <string name="cancel" msgid="8984206397635155197">"రద్దు చేయండి"</string>
<string name="enter_input" msgid="6193628663039958990">"USSD మెసేజ్ తప్పనిసరిగా <xliff:g id="MIN_LEN">%1$d</xliff:g> మరియు <xliff:g id="MAX_LEN">%2$d</xliff:g> అక్షరాల మధ్య ఉండాలి. దయచేసి మళ్లీ ప్రయత్నించండి."</string>
<string name="manageConferenceLabel" msgid="8415044818156353233">"కాన్ఫరెన్స్ కాల్ను నిర్వహించండి"</string>
<string name="ok" msgid="7818974223666140165">"సరే"</string>
@@ -46,13 +46,13 @@
<string name="wild_prompt_str" msgid="5858910969703305375">"దీనితో వైల్డ్ అక్షరాన్ని భర్తీ చేయండి"</string>
<string name="no_vm_number" msgid="6623853880546176930">"వాయిస్ మెయిల్ నంబర్ లేదు"</string>
<string name="no_vm_number_msg" msgid="5165161462411372504">"సిమ్ కార్డులో వాయిస్ మెయిల్ నంబర్ ఏదీ నిల్వ చేయబడలేదు."</string>
- <string name="add_vm_number_str" msgid="7368168964435881637">"నంబర్ను జోడించు"</string>
- <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"వాయిస్ మెయిల్ సెట్టింగ్లను ప్రాథమిక వినియోగదారు మాత్రమే సవరించగలరు."</string>
+ <string name="add_vm_number_str" msgid="7368168964435881637">"నంబర్ను జోడించండి"</string>
+ <string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"వాయిస్ మెయిల్ సెట్టింగ్లను ప్రాథమిక వినియోగదారు మాత్రమే ఎడిట్ చేయగలరు."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"మీ SIM కార్డు అన్బ్లాక్ చేయబడింది. మీ ఫోన్ అన్లాక్ చేయబడుతోంది…"</string>
<string name="label_ndp" msgid="7617392683877410341">"SIM నెట్వర్క్ అన్లాక్ పిన్"</string>
<string name="label_phoneid" msgid="8775611434123577808">"ఈ ఆపరేటర్కు సంబంధించి SIM లాక్ చేయబడింది"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"అన్లాక్ చేయి"</string>
- <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"తీసివేయి"</string>
+ <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"తీసివేయండి"</string>
<string name="requesting_unlock" msgid="930512210309437741">"నెట్వర్క్ అన్లాక్ను అభ్యర్థిస్తోంది…"</string>
<string name="unlock_failed" msgid="7103543844840661366">"నెట్వర్క్ అన్లాక్ రిక్వెస్ట్ విఫలమైంది."</string>
<string name="unlock_success" msgid="32681089371067565">"నెట్వర్క్ అన్లాక్ విజయవంతమైంది."</string>
@@ -71,7 +71,7 @@
<string name="phone_accounts_settings_header" msgid="6296501692964706536">"సెట్టింగ్లు"</string>
<string name="phone_accounts_choose_accounts" msgid="4748805293314824974">"ఖాతాలను ఎంచుకోండి"</string>
<string name="phone_accounts_selection_header" msgid="2945830843104108440">"ఫోన్ ఖాతాలు"</string>
- <string name="phone_accounts_add_sip_account" msgid="1437634802033309305">"SIP ఖాతాను జోడించు"</string>
+ <string name="phone_accounts_add_sip_account" msgid="1437634802033309305">"SIP ఖాతాను జోడించండి"</string>
<string name="phone_accounts_configure_account_settings" msgid="6622119715253196586">"ఖాతా సెట్టింగ్లను కాన్ఫిగర్ చేయి"</string>
<string name="phone_accounts_all_calling_accounts" msgid="1609600743500618823">"అన్ని కాలింగ్ ఖాతాలు"</string>
<string name="phone_accounts_all_calling_accounts_summary" msgid="2214134955430107240">"ఏ ఖాతాల నుండి కాల్స్ చేయవచ్చనే దాన్ని ఎంచుకోండి"</string>
@@ -81,7 +81,7 @@
<string name="voicemail_settings_with_label" msgid="4228431668214894138">"వాయిస్ మెయిల్ (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="voicemail_abbreviated" msgid="7746778673131551185">"VM:"</string>
<string name="make_and_receive_calls" msgid="4868913166494621109">"కాల్స్ను చేయండి & స్వీకరించండి"</string>
- <string name="smart_forwarding_settings_menu" msgid="8850429887958938540">"స్మార్ట్ ఫార్వర్డ్ను ప్రారంభించు"</string>
+ <string name="smart_forwarding_settings_menu" msgid="8850429887958938540">"స్మార్ట్ ఫార్వర్డ్ను ప్రారంభించండి"</string>
<string name="smart_forwarding_settings_menu_summary" msgid="5096947726032885325">"ఒక నంబర్ను చేరుకోలేకపోయినప్పుడు, మీ ఇతర నంబర్లకు కాల్స్ను ఎల్లప్పుడూ ఫార్వర్డ్ చేయబడతాయి."</string>
<string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"నోటిఫికేషన్లు"</string>
<string name="cell_broadcast_settings" msgid="8135324242541809924">"అత్యవసర ప్రసారాలు"</string>
@@ -96,7 +96,7 @@
<string name="sum_loading_settings" msgid="434063780286688775">"సెట్టింగ్లను లోడ్ చేస్తోంది…"</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"అవుట్గోయింగ్ కాల్స్లో నంబర్ దాచబడుతుంది"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"అవుట్గోయింగ్ కాల్స్లో నంబర్ ప్రదర్శించబడుతుంది"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"అవుట్గోయింగ్ కాల్స్లో నా నంబర్ను ప్రదర్శించడానికి ఆటోమేటిక్ ఆపరేటర్ సెట్టింగ్లను ఉపయోగించు"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"అవుట్గోయింగ్ కాల్స్లో నా నంబర్ను ప్రదర్శించడానికి ఆటోమేటిక్ ఆపరేటర్ సెట్టింగ్లను ఉపయోగించండి"</string>
<string name="labelCW" msgid="8449327023861428622">"కాల్ నిరీక్షణ"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"కాల్ సమయంలో, ఇన్కమింగ్ కాల్స్ల గురించి నాకు తెలియజేయి"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"కాల్ సమయంలో, ఇన్కమింగ్ కాల్స్ల గురించి నాకు తెలియజేయి"</string>
@@ -104,31 +104,31 @@
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"కాల్ ఫార్వార్డింగ్ సెట్టింగ్లు (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"కాల్ ఫార్వార్డింగ్"</string>
<string name="labelCFU" msgid="8870170873036279706">"ఎల్లప్పుడూ ఫార్వర్డ్ చేయి"</string>
- <string name="messageCFU" msgid="1361806450979589744">"ఎల్లప్పుడూ ఈ నంబర్ను ఉపయోగించు"</string>
- <string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"అన్ని కాల్స్ను ఫార్వార్డ్ చేస్తోంది"</string>
- <string name="sum_cfu_enabled" msgid="5806923046528144526">"అన్ని కాల్స్ను <xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వార్డ్ చేస్తోంది"</string>
+ <string name="messageCFU" msgid="1361806450979589744">"ఎల్లప్పుడూ ఈ నంబర్ను ఉపయోగించండి"</string>
+ <string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"అన్ని కాల్స్ను ఫార్వర్డ్ చేస్తోంది"</string>
+ <string name="sum_cfu_enabled" msgid="5806923046528144526">"అన్ని కాల్స్ను <xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వర్డ్ చేస్తోంది"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"నంబర్ అందుబాటులో లేదు"</string>
<string name="sum_cfu_disabled" msgid="5010617134210809853">"ఆఫ్లో ఉంది"</string>
<string name="labelCFB" msgid="615265213360512768">"బిజీగా ఉన్నప్పుడు"</string>
<string name="messageCFB" msgid="1958017270393563388">"బిజీగా ఉన్నప్పుడు ఫార్వర్డ్ చేయాల్సిన నంబర్"</string>
- <string name="sum_cfb_enabled" msgid="332037613072049492">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వార్డ్ చేస్తోంది"</string>
+ <string name="sum_cfb_enabled" msgid="332037613072049492">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వర్డ్ చేస్తోంది"</string>
<string name="sum_cfb_disabled" msgid="3589913334164866035">"ఆఫ్లో ఉంది"</string>
<string name="disable_cfb_forbidden" msgid="4831494744351633961">"మీ ఫోన్ బిజీగా ఉన్నప్పుడు కాల్ ఫార్వర్డింగ్ను నిలిపివేయడానికి మీ ఆపరేటర్ మద్దతు ఇవ్వరు."</string>
<string name="labelCFNRy" msgid="3403533792248457946">"సమాధానం ఇవ్వనప్పుడు"</string>
<string name="messageCFNRy" msgid="7644434155765359009">"సమాధానం ఇవ్వనప్పుడు నంబర్"</string>
- <string name="sum_cfnry_enabled" msgid="3000500837493854799">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వార్డ్ చేస్తోంది"</string>
+ <string name="sum_cfnry_enabled" msgid="3000500837493854799">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వర్డ్ చేస్తోంది"</string>
<string name="sum_cfnry_disabled" msgid="1990563512406017880">"ఆఫ్లో ఉంది"</string>
<string name="disable_cfnry_forbidden" msgid="3174731413216550689">"మీ ఫోన్ సమాధానం ఇవ్వలేనప్పుడు కాల్ ఫార్వర్డింగ్ను నిలిపివేయడానికి మీ ఆపరేటర్ మద్దతు ఇవ్వరు."</string>
<string name="labelCFNRc" msgid="4163399350778066013">"చేరుకోలేనప్పుడు"</string>
<string name="messageCFNRc" msgid="6980340731313007250">"చేరుకోవడం సాధ్యపడనప్పుడు నంబర్"</string>
- <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వార్డ్ చేస్తోంది"</string>
+ <string name="sum_cfnrc_enabled" msgid="1799069234006073477">"<xliff:g id="PHONENUMBER">{0}</xliff:g>కి ఫార్వర్డ్ చేస్తోంది"</string>
<string name="sum_cfnrc_disabled" msgid="739289696796917683">"ఆఫ్లో ఉంది"</string>
<string name="disable_cfnrc_forbidden" msgid="775348748084726890">"మీ ఫోన్ను చేరుకోవడం సాధ్యపడనప్పుడు కాల్ ఫార్వర్డింగ్ను నిలిపివేయడానికి మీ క్యారియర్ మద్దతు ఇవ్వదు."</string>
<string name="registration_cf_forbidden" msgid="4386482610771190420">"కాల్ ఫార్వర్డింగ్ను మీ క్యారియర్ సపోర్ట్ చేయదు."</string>
<string name="cdma_call_waiting" msgid="4565070960879673216">"కాల్ వెయిటింగ్ను ఆన్ చేయాలా?"</string>
<string name="enable_cdma_call_waiting_setting" msgid="5906811747921744307">"మీరు కాల్స్లో ఉండగా, ఇన్కమింగ్ కాల్స్ల గురించి మీకు తెలియజేయబడుతుంది"</string>
<string name="enable_cdma_cw" msgid="811047045863422232">"ఆన్ చేయి"</string>
- <string name="disable_cdma_cw" msgid="7119290446496301734">"రద్దు చేయి"</string>
+ <string name="disable_cdma_cw" msgid="7119290446496301734">"రద్దు చేయండి"</string>
<string name="cdma_call_waiting_in_ims_on" msgid="6390979414188659218">"IMSలో CDMA కాల్ వెయిటింగ్ ఆన్లో ఉంది"</string>
<string name="cdma_call_waiting_in_ims_off" msgid="1099246114368636334">"IMSలో CDMA కాల్ వెయిటింగ్ ఆఫ్లో ఉంది"</string>
<string name="updating_title" msgid="6130548922615719689">"కాల్ సెట్టింగ్లు"</string>
@@ -145,7 +145,7 @@
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"కొత్త SS రిక్వెస్ట్కు మార్చబడింది"</string>
<string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"SS రిక్వెస్ట్ వీడియో కాల్కి మార్చబడింది"</string>
<string name="fdn_check_failure" msgid="1833769746374185247">"మీ ఫోన్ యాప్ యొక్క ఫిక్స్డ్ డయలింగ్ నంబర్ల సెట్టింగ్ ప్రారంభించబడింది. తత్ఫలితంగా, కాల్ సంబంధిత లక్షణాల్లో కొన్ని పని చేయడం లేదు."</string>
- <string name="radio_off_error" msgid="8321564164914232181">"ఈ సెట్టింగ్లను వీక్షించడానికి ముందు రేడియోను ప్రారంభించండి."</string>
+ <string name="radio_off_error" msgid="8321564164914232181">"ఈ సెట్టింగ్లను చూడటానికి ముందు రేడియోను ప్రారంభించండి."</string>
<string name="close_dialog" msgid="1074977476136119408">"సరే"</string>
<string name="enable" msgid="2636552299455477603">"ఆన్ చేయి"</string>
<string name="disable" msgid="1122698860799462116">"ఆఫ్ చేయి"</string>
@@ -167,7 +167,7 @@
<string name="vm_change_pin_progress_message" msgid="626015184502739044">"దయచేసి వేచి ఉండండి."</string>
<string name="vm_change_pin_error_too_short" msgid="1789139338449945483">"కొత్త PIN చాలా చిన్నదిగా ఉంది."</string>
<string name="vm_change_pin_error_too_long" msgid="3634907034310018954">"కొత్త PIN చాలా పొడవు ఉంది."</string>
- <string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"కొత్త PIN చాలా బలహీనంగా ఉంది. శక్తివంతమైన పాస్వర్డ్లో వరుస శ్రేణిలో అక్షరాలు/అంకెలు లేదా పునరావృత అంకెలు ఉండకూడదు."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"కొత్త PIN చాలా బలహీనంగా ఉంది. శక్తివంతమైన పాస్వర్డ్లో వరుస శ్రేణిలో అక్షరాలు/అంకెలు లేదా రిపీట్ అంకెలు ఉండకూడదు."</string>
<string name="vm_change_pin_error_mismatch" msgid="5364847280026257331">"పాత PIN సరిపోలలేదు."</string>
<string name="vm_change_pin_error_invalid" msgid="5230002671175580674">"కొత్త PIN చెల్లని అక్షరాలను కలిగి ఉంది."</string>
<string name="vm_change_pin_error_system_error" msgid="9116483527909681791">"PINని మార్చడం సాధ్యపడలేదు"</string>
@@ -199,8 +199,8 @@
<item msgid="4531933377509551889">"GSM/WCDMAకు ప్రాధాన్యత"</item>
<item msgid="5120532750027435355">"GSM మాత్రమే"</item>
<item msgid="8973311380798000102">"WCDMA మాత్రమే"</item>
- <item msgid="4139961027147085705">"GSM/WCDMA స్వయంచాలకం"</item>
- <item msgid="4024581977690585814">"CDMA/EvDo స్వయంచాలకం"</item>
+ <item msgid="4139961027147085705">"GSM/WCDMA ఆటోమేటిక్"</item>
+ <item msgid="4024581977690585814">"CDMA/EvDo ఆటోమేటిక్"</item>
<item msgid="7199560024080522581">"EvDo లేని CDMA"</item>
<item msgid="3160291725308400608">"EvDo మాత్రమే"</item>
<item msgid="2319217472852426965">"CDMA/EvDo/GSM/WCDMA"</item>
@@ -273,13 +273,13 @@
<string name="network_operator_category" msgid="4992217193732304680">"నెట్వర్క్"</string>
<string name="enhanced_4g_lte_mode_title" msgid="4213420368777080540">"మెరుగుపరిచిన 4G LTE మోడ్"</string>
<!-- no translation found for enhanced_4g_lte_mode_title_variant:0 (7240155150166394308) -->
- <string name="enhanced_4g_lte_mode_summary" msgid="7725708511804143638">"వాయిస్, ఇతర కమ్యూనికే. మెరుగుపరచడానికి LTE సేవలను ఉపయోగించు (సిఫార్సు చేయబడింది)"</string>
+ <string name="enhanced_4g_lte_mode_summary" msgid="7725708511804143638">"వాయిస్, ఇతర కమ్యూనికే. మెరుగుపరచడానికి LTE సేవలను ఉపయోగించండి (సిఫార్సు చేయబడింది)"</string>
<string name="enhanced_4g_lte_mode_summary_o2" msgid="2521108446409016542">"వాయిస్, ఇతర కమ్యూనికేషన్లను మెరుగుపరచడానికి 4G సేవలను ఉపయోగించండి (సిఫార్సు చేయబడింది)"</string>
<!-- no translation found for enhanced_4g_lte_mode_sumary_variant:0 (2943982616649705147) -->
<!-- no translation found for enhanced_4g_lte_mode_sumary_variant:1 (5262249464504131443) -->
<!-- no translation found for enhanced_4g_lte_mode_sumary_variant:2 (6356974241850241718) -->
<string name="data_enabled" msgid="22525832097434368">"డేటా ప్రారంభించబడింది"</string>
- <string name="data_enable_summary" msgid="696860063456536557">"డేటా వినియోగాన్ని అనుమతించు"</string>
+ <string name="data_enable_summary" msgid="696860063456536557">"డేటా వినియోగాన్ని అనుమతించండి"</string>
<string name="dialog_alert_title" msgid="5260471806940268478">"హెచ్చరిక"</string>
<string name="roaming" msgid="1576180772877858949">"రోమింగ్"</string>
<string name="roaming_enable" msgid="6853685214521494819">"రోమింగ్లో ఉన్నప్పుడు డేటా సర్వీసులకు కనెక్ట్ చేయండి"</string>
@@ -301,11 +301,11 @@
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_2">%2$s</xliff:g> మధ్య కాలంలో <xliff:g id="ID_1">%1$s</xliff:g> మొబైల్ డేటా ఉపయోగించబడింది"</string>
<string name="advanced_options_title" msgid="9208195294513520934">"అధునాతన సెట్టింగ్లు"</string>
<string name="carrier_settings_euicc" msgid="1190237227261337749">"క్యారియర్"</string>
- <string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"క్యారియర్, ఇసిమ్, సిమ్, ఇయుక్, క్యారియర్లను మార్చు, క్యారియర్ను జోడించు"</string>
+ <string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"క్యారియర్, ఇసిమ్, సిమ్, ఇయుక్, క్యారియర్లను మార్చు, క్యారియర్ను జోడించండి"</string>
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> — <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
<string name="mobile_data_settings_title" msgid="7228249980933944101">"మొబైల్ డేటా"</string>
<string name="mobile_data_settings_summary" msgid="5012570152029118471">"మొబైల్ నెట్వర్క్ను ఉపయోగించి డేటాను యాక్సెస్ చేయండి"</string>
- <string name="data_usage_disable_mobile" msgid="5669109209055988308">"మొబైల్ డేటాని ఆఫ్ చేయాలా?"</string>
+ <string name="data_usage_disable_mobile" msgid="5669109209055988308">"మొబైల్ డేటాను ఆఫ్ చేయాలా?"</string>
<string name="sim_selection_required_pref" msgid="6985901872978341314">"ఎంపిక అవసరం"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"డేటా SIMని మార్చాలా?"</string>
<string name="sim_change_data_message" msgid="3567358694255933280">"మొబైల్ డేటా కోసం <xliff:g id="OLD_SIM">%2$s</xliff:g>కి బదులుగా <xliff:g id="NEW_SIM">%1$s</xliff:g>ని ఉపయోగించాలా?"</string>
@@ -433,7 +433,7 @@
<item msgid="2953825013895327785">"0"</item>
<item msgid="7970797749269738435">"1"</item>
</string-array>
- <string name="cdma_activate_device" msgid="5914720276140097632">"పరికరాన్ని సక్రియం చేయండి"</string>
+ <string name="cdma_activate_device" msgid="5914720276140097632">"పరికరాన్ని యాక్టివేట్ చేయండి"</string>
<string name="cdma_lte_data_service" msgid="359786441782404562">"డేటా సేవను సెటప్ చేయండి"</string>
<string name="carrier_settings_title" msgid="6292869148169850220">"క్యారియర్ సెట్టింగ్లు"</string>
<string name="fdn" msgid="2545904344666098749">"ఫిక్సెడ్ డయలింగ్ నంబర్లు"</string>
@@ -443,11 +443,11 @@
<string name="fdn_activation" msgid="2178637004710435895">"FDN సక్రియం"</string>
<string name="fdn_enabled" msgid="7017355494808056447">"ఫిక్సెడ్ డయలింగ్ నంబర్లు ప్రారంభించబడ్డాయి"</string>
<string name="fdn_disabled" msgid="6696468878037736600">"ఫిక్సెడ్ డయలింగ్ నంబర్లు నిలిపివేయబడ్డాయి"</string>
- <string name="enable_fdn" msgid="4830555730418033723">"FDNని ప్రారంభించు"</string>
+ <string name="enable_fdn" msgid="4830555730418033723">"FDNని ప్రారంభించండి"</string>
<string name="disable_fdn" msgid="3918794950264647541">"FDNని నిలిపివేయి"</string>
<string name="change_pin2" msgid="3110844547237754871">"పిన్2ని మార్చు"</string>
<string name="enable_fdn_ok" msgid="5080925177369329827">"FDNని నిలిపివేయి"</string>
- <string name="disable_fdn_ok" msgid="3745475926874838676">"FDNని ప్రారంభించు"</string>
+ <string name="disable_fdn_ok" msgid="3745475926874838676">"FDNని ప్రారంభించండి"</string>
<string name="sum_fdn" msgid="6152246141642323582">"ఫిక్స్డ్ డయలింగ్ నంబర్లను నిర్వహించండి"</string>
<string name="sum_fdn_change_pin" msgid="3510994280557335727">"FDN యాక్సెస్ కోసం పిన్ను మార్చండి"</string>
<string name="sum_fdn_manage_list" msgid="3311397063233992907">"ఫోన్ నంబర్ లిస్ట్ను నిర్వహించండి"</string>
@@ -465,19 +465,19 @@
<string name="get_pin2" msgid="4221654606863196332">"PIN2ని టైప్ చేయండి"</string>
<string name="name" msgid="1347432469852527784">"పేరు"</string>
<string name="number" msgid="1564053487748491000">"నంబర్"</string>
- <string name="save" msgid="983805790346099749">"సేవ్ చేయి"</string>
+ <string name="save" msgid="983805790346099749">"సేవ్ చేయండి"</string>
<string name="add_fdn_contact" msgid="1169713422306640887">"ఫిక్స్డ్ డయలింగ్ నంబర్ను జోడించండి"</string>
<string name="adding_fdn_contact" msgid="3112531600824361259">"ఫిక్స్డ్ డయలింగ్ నంబర్ను జోడిస్తోంది..."</string>
<string name="fdn_contact_added" msgid="2840016151693394596">"ఫిక్స్డ్ డయలింగ్ నంబర్ జోడించబడింది."</string>
<string name="edit_fdn_contact" msgid="6030829994819587408">"ఫిక్స్డ్ డయలింగ్ నంబర్ను ఎడిట్ చేయండి"</string>
<string name="updating_fdn_contact" msgid="6989341376868227150">"ఫిక్స్డ్ డయలింగ్ నంబర్ను అప్డేట్ చేస్తోంది..."</string>
- <string name="fdn_contact_updated" msgid="6876330243323118937">"ఫిక్స్డ్ డయలింగ్ నంబర్ నవీకరించబడింది."</string>
+ <string name="fdn_contact_updated" msgid="6876330243323118937">"ఫిక్స్డ్ డయలింగ్ నంబర్ అప్డేట్ చేయబడింది."</string>
<string name="delete_fdn_contact" msgid="7027405651994507077">"ఫిక్స్డ్ డయలింగ్ నంబర్ను తొలగించండి"</string>
<string name="deleting_fdn_contact" msgid="6872320570844460428">"ఫిక్స్డ్ డయలింగ్ నంబర్ను తొలగిస్తోంది..."</string>
<string name="fdn_contact_deleted" msgid="1680714996763848838">"ఫిక్స్డ్ డయలింగ్ నంబర్ తొలగించబడింది."</string>
- <string name="pin2_invalid" msgid="2313954262684494442">"మీరు చెల్లని PINను టైప్ చేసినందున FDN నవీకరించబడలేదు."</string>
+ <string name="pin2_invalid" msgid="2313954262684494442">"మీరు చెల్లని PINను టైప్ చేసినందున FDN అప్డేట్ చేయబడలేదు."</string>
<string name="fdn_invalid_number" msgid="9067189814657840439">"నంబర్ <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g> అంకెలను మించినందున FDN అప్డేట్ చేయబడలేదు."</string>
- <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"FDN నవీకరించబడలేదు. PIN2 చెల్లదు లేదా ఫోన్ నంబర్ తిరస్కరించబడింది."</string>
+ <string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"FDN అప్డేట్ చేయబడలేదు. PIN2 చెల్లదు లేదా ఫోన్ నంబర్ తిరస్కరించబడింది."</string>
<string name="fdn_failed" msgid="216592346853420250">"FDN చర్య విఫలమైంది."</string>
<string name="simContacts_emptyLoading" msgid="4989040293858675483">"SIM కార్డు నుండి చదువుతోంది…"</string>
<string name="simContacts_empty" msgid="1135632055473689521">"మీ SIM కార్డులో కాంటాక్ట్లు ఏవీ లేవు."</string>
@@ -498,7 +498,7 @@
<string name="enable_pin_ok" msgid="2877428038280804256">"PIN సెట్ చేయబడింది"</string>
<string name="disable_pin_ok" msgid="888505244389647754">"PIN తీసివేయబడింది"</string>
<string name="pin_failed" msgid="4527347792881939652">"PIN చెల్లదు"</string>
- <string name="pin_changed" msgid="7291153750090452808">"PIN నవీకరించబడింది"</string>
+ <string name="pin_changed" msgid="7291153750090452808">"PIN అప్డేట్ చేయబడింది"</string>
<string name="puk_requested" msgid="2061337960609806851">"పాస్వర్డ్ చెల్లదు. PIN ఇప్పుడు బ్లాక్ చేయబడింది. PUK రిక్వెస్ట్ చేయబడింది."</string>
<string name="enter_pin2_text" msgid="7266379426804295979">"PIN2"</string>
<string name="oldPin2Label" msgid="4648543187859997203">"పాత PIN2"</string>
@@ -509,7 +509,7 @@
<string name="mismatchPin2" msgid="4952718725266700631">"PIN2లు సరిపోలలేదు. మళ్లీ ప్రయత్నించండి."</string>
<string name="invalidPin2" msgid="6467957903056379343">"4 నుండి 8 సంఖ్యలు ఉండే PIN2ని నమోదు చేయండి."</string>
<string name="invalidPuk2" msgid="713729511903849544">"8 సంఖ్యలు ఉండే PUK2ను నమోదు చేయండి."</string>
- <string name="pin2_changed" msgid="5710551850481287821">"PIN2 నవీకరించబడింది"</string>
+ <string name="pin2_changed" msgid="5710551850481287821">"PIN2 అప్డేట్ చేయబడింది"</string>
<string name="label_puk2_code" msgid="2852217004288085562">"PUK2 కోడ్ను నమోదు చేయండి"</string>
<string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"పాస్వర్డ్ చెల్లదు. PIN2 ఇప్పుడు బ్లాక్ చేయబడింది. మళ్లీ ప్రయత్నించడానికి, PIN 2ను మార్చండి."</string>
<string name="puk2_requested" msgid="6992374450720307514">"పాస్వర్డ్ చెల్లదు. SIM ఇప్పుడు లాక్ చేయబడింది. PUK2ని నమోదు చేయండి."</string>
@@ -579,17 +579,17 @@
<string name="onscreenEndCallText" msgid="6138725377654842757">"ముగించు"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"డయల్ప్యాడ్"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"మ్యూట్ చేయి"</string>
- <string name="onscreenAddCallText" msgid="9075675082903611677">"కాల్ను జోడించు"</string>
+ <string name="onscreenAddCallText" msgid="9075675082903611677">"కాల్ను జోడించండి"</string>
<string name="onscreenMergeCallsText" msgid="3692389519611225407">"కాల్స్ను విలీనం చేయి"</string>
<string name="onscreenSwapCallsText" msgid="2682542150803377991">"స్వాప్ చేయి"</string>
- <string name="onscreenManageCallsText" msgid="1162047856081836469">"కాల్స్ను నిర్వహించు"</string>
- <string name="onscreenManageConferenceText" msgid="4700574060601755137">"కాన్ఫరెన్స్ను నిర్వహించు"</string>
+ <string name="onscreenManageCallsText" msgid="1162047856081836469">"కాల్స్ను మేనేజ్ చేయండి"</string>
+ <string name="onscreenManageConferenceText" msgid="4700574060601755137">"కాన్ఫరెన్స్ను మేనేజ్ చేయండి"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"ఆడియో"</string>
<string name="onscreenVideoCallText" msgid="1743992456126258698">"వీడియో కాల్"</string>
- <string name="importSimEntry" msgid="3892354284082689894">"దిగుమతి చేయి"</string>
- <string name="importAllSimEntries" msgid="2628391505643564007">"అన్నింటినీ దిగుమతి చేయి"</string>
+ <string name="importSimEntry" msgid="3892354284082689894">"దిగుమతి చేయండి"</string>
+ <string name="importAllSimEntries" msgid="2628391505643564007">"అన్నింటినీ దిగుమతి చేయండి"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"SIM కాంటాక్ట్లను దిగుమతి చేస్తోంది"</string>
- <string name="importToFDNfromContacts" msgid="5068664870738407341">"కాంటాక్ట్ల నుండి దిగుమతి చేయి"</string>
+ <string name="importToFDNfromContacts" msgid="5068664870738407341">"కాంటాక్ట్ల నుండి దిగుమతి చేయండి"</string>
<string name="singleContactImportedMsg" msgid="3619804066300998934">"కాంటాక్ట్ దిగుమతి చేయబడింది"</string>
<string name="failedToImportSingleContactMsg" msgid="228095510489830266">"కాంటాక్ట్ను దిగుమతి చేయడంలో విఫలమైంది"</string>
<string name="hac_mode_title" msgid="4127986689621125468">"వినికిడి సహాయక సాధనాలు"</string>
@@ -612,13 +612,13 @@
</string-array>
<string name="network_info_message" msgid="7599413947016532355">"నెట్వర్క్ మెసేజ్"</string>
<string name="network_error_message" msgid="4271579424089326618">"లోప మెసేజ్"</string>
- <string name="ota_title_activate" msgid="4049645324841263423">"మీ ఫోన్ను సక్రియం చేయండి"</string>
- <string name="ota_touch_activate" msgid="838764494319694754">"మీ ఫోన్ సేవను సక్రియం చేయడానికి ప్రత్యేక కాల్ చేయాల్సి ఉంటుంది. \n\n“సక్రియం చేయి” నొక్కిన తర్వాత, మీ ఫోన్ను సక్రియం చేయడానికి అందించబడే సూచనలను వినండి."</string>
+ <string name="ota_title_activate" msgid="4049645324841263423">"మీ ఫోన్ను యాక్టివేట్ చేయండి"</string>
+ <string name="ota_touch_activate" msgid="838764494319694754">"మీ ఫోన్ సేవను సక్రియం చేయడానికి ప్రత్యేక కాల్ చేయాల్సి ఉంటుంది. \n\n“యాక్టివేట్ చేయండి” నొక్కిన తర్వాత, మీ ఫోన్ను సక్రియం చేయడానికి అందించబడే సూచనలను వినండి."</string>
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"సక్రియం చేస్తోంది..."</string>
<string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"ఫోన్ మీ మొబైల్ డేటా సేవను సక్రియం చేస్తోంది.\n\nదీనికి గరిష్టంగా 5 నిమిషాలు పట్టవచ్చు."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"సక్రియం చేయడాన్ని దాటవేయాలా?"</string>
<string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"మీరు సక్రియం చేయడాన్ని దాటవేస్తే, కాల్స్ చేయలేరు లేదా మొబైల్ డేటా నెట్వర్క్లకు కనెక్ట్ చేయలేరు (మీరు Wi-Fi నెట్వర్క్లకు కనెక్ట్ చేయగలిగినప్పటికీ). మీరు మీ ఫోన్ను సక్రియం చేసేవరకు, దాన్ని ప్రారంభించే ప్రతిసారీ సక్రియం చేయమని మిమ్మల్ని అడుగుతుంది."</string>
- <string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"దాటవేయి"</string>
+ <string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"స్కిప్ చేయండి"</string>
<string name="ota_activate" msgid="7939695753665438357">"యాక్టివేట్ చేయండి"</string>
<string name="ota_title_activate_success" msgid="1272135024761004889">"ఫోన్ సక్రియం చేయబడింది."</string>
<string name="ota_title_problem_with_activation" msgid="7019745985413368726">"సక్రియం చేయడంలో సమస్య"</string>
@@ -643,7 +643,7 @@
<string name="progress_dialog_exiting_ecm" msgid="9159080081676927217">"అత్యవసర కాల్బ్యాక్ మోడ్ నుండి నిష్క్రమిస్తోంది"</string>
<string name="alert_dialog_yes" msgid="3532525979632841417">"అవును"</string>
<string name="alert_dialog_no" msgid="1075632654085988420">"కాదు"</string>
- <string name="alert_dialog_dismiss" msgid="1336356286354517054">"తీసివేయి"</string>
+ <string name="alert_dialog_dismiss" msgid="1336356286354517054">"తీసివేయండి"</string>
<string name="phone_in_ecm_call_notification_text_without_data_restriction_hint" msgid="3747860785153531225">"ఫోన్ అత్యవసర కాల్బ్యాక్ మోడ్లో ఉంది"</string>
<string name="phone_in_ecm_notification_complete_time_without_data_restriction_hint" msgid="3690292264812050858">"<xliff:g id="COMPLETETIME">%s</xliff:g> వరకు"</string>
<string name="alert_dialog_exit_ecm_without_data_restriction_hint" msgid="7549850847524907932">"{count,plural, =1{ఫోన్ ఒక నిమిషం పాటు ఎమర్జెన్సీ కాల్బ్యాక్ మోడ్లో ఉంటుంది.\nమీరు ఇప్పుడే నిష్క్రమించాలనుకుంటున్నారా?}other{ఫోన్ %s నిమిషాల పాటు ఎమర్జెన్సీ కాల్బ్యాక్ మోడ్లో ఉంటుంది.\nమీరు ఇప్పుడే నిష్క్రమించాలనుకుంటున్నారా?}}"</string>
@@ -675,8 +675,8 @@
<string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"వీరి నుండి Wi-Fi కాల్"</string>
<string name="status_hint_label_wifi_call" msgid="942993035689809853">"Wi-Fi కాల్"</string>
<string name="message_decode_error" msgid="1061856591500290887">"మెసేజ్ను డీకోడ్ చేస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది."</string>
- <string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM కార్డ్ మీ సేవను సక్రియం చేసింది మరియు మీ ఫోన్ రోమింగ్ సామర్థ్యాలను నవీకరించింది."</string>
- <string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"చాలా ఎక్కువ కాల్స్ సక్రియంగా ఉన్నాయి. దయచేసి మరొక కొత్త కాల్ చేసే ముందు ఇప్పటికే ఉన్న కాల్స్ను ముగించండి లేదా విలీనం చేయండి."</string>
+ <string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM కార్డ్ మీ సేవను సక్రియం చేసింది మరియు మీ ఫోన్ రోమింగ్ సామర్థ్యాలను అప్డేట్ చేసింది."</string>
+ <string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"చాలా ఎక్కువ కాల్స్ యాక్టివ్గా ఉన్నాయి. దయచేసి మరొక కొత్త కాల్ చేసే ముందు ఇప్పటికే ఉన్న కాల్స్ను ముగించండి లేదా విలీనం చేయండి."</string>
<string name="callFailed_imei_not_accepted" msgid="7257903653685147251">"కనెక్ట్ చేయడం సాధ్యపడలేదు, దయచేసి చెల్లుబాటు అయ్యే SIM కార్డ్ను చొప్పించండి."</string>
<string name="callFailed_wifi_lost" msgid="1788036730589163141">"Wi-Fi కనెక్షన్ పోయింది. కాల్ ముగిసింది."</string>
<string name="dialFailed_low_battery" msgid="6857904237423407056">"తక్కువ బ్యాటరీ కారణంగా మీ వీడియో కాల్ చేయడం సాధ్యపడదు."</string>
@@ -685,7 +685,7 @@
<string name="callFailed_wfc_service_not_available_in_this_location" msgid="3624536608369524988">"ఈ లొకేషన్లో Wi-Fi కాలింగ్ అందుబాటులో లేదు."</string>
<string name="change_pin_title" msgid="3564254326626797321">"వాయిస్ మెయిల్ PINని మార్చండి"</string>
<string name="change_pin_continue_label" msgid="5177011752453506371">"కొనసాగించండి"</string>
- <string name="change_pin_cancel_label" msgid="2301711566758827936">"రద్దు చేయి"</string>
+ <string name="change_pin_cancel_label" msgid="2301711566758827936">"రద్దు చేయండి"</string>
<string name="change_pin_ok_label" msgid="6861082678817785330">"సరే"</string>
<string name="change_pin_enter_old_pin_header" msgid="853151335217594829">"మీ పాత PINని నిర్ధారించండి"</string>
<string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"కొనసాగించడానికి మీ వాయిస్ మెయిల్ PINని నమోదు చేయండి."</string>
@@ -693,12 +693,12 @@
<string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"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="2606303906320705726">"మీ PINని నిర్ధారించండి"</string>
<string name="change_pin_confirm_pins_dont_match" msgid="305164501222587215">"PINలు సరిపోలలేదు"</string>
- <string name="change_pin_succeeded" msgid="2504705600693014403">"వాయిస్ మెయిల్ PIN నవీకరించబడింది"</string>
+ <string name="change_pin_succeeded" msgid="2504705600693014403">"వాయిస్ మెయిల్ PIN అప్డేట్ చేయబడింది"</string>
<string name="change_pin_system_error" msgid="7772788809875146873">"PINని సెట్ చేయడం సాధ్యపడలేదు"</string>
<string name="mobile_data_status_roaming_turned_off_subtext" msgid="6840673347416227054">"డేటా రోమింగ్ ఆఫ్ చేయబడింది"</string>
<string name="mobile_data_status_roaming_turned_on_subtext" msgid="5615757897768777865">"డేటా రోమింగ్ ఆన్ చేయబడింది"</string>
<string name="mobile_data_status_roaming_without_plan_subtext" msgid="6536671968072284677">"ప్రస్తుతం రోమింగ్లో ఉంది, డేటా ప్లాన్ అవసరం"</string>
- <string name="mobile_data_status_roaming_with_plan_subtext" msgid="2576177169108123095">"ప్రస్తుతం రోమింగ్లో ఉంది, డేటా ప్లాన్ సక్రియంగా ఉంది"</string>
+ <string name="mobile_data_status_roaming_with_plan_subtext" msgid="2576177169108123095">"ప్రస్తుతం రోమింగ్లో ఉంది, డేటా ప్లాన్ యాక్టివ్గా ఉంది"</string>
<string name="mobile_data_status_no_plan_subtext" msgid="170331026419263657">"మొబైల్ డేటా ఏదీ మిగిలి లేదు"</string>
<string name="mobile_data_activate_prepaid" msgid="4276738964416795596">"మొబైల్ డేటా ఏదీ మిగిలి లేదు"</string>
<string name="mobile_data_activate_prepaid_summary" msgid="6846085278531605925">"<xliff:g id="PROVIDER_NAME">%s</xliff:g> ద్వారా మొబైల్ డేటాను జోడించండి"</string>
@@ -707,8 +707,8 @@
<string name="mobile_data_activate_footer" msgid="7895874069807204548">"మీరు మీ క్యారియర్ <xliff:g id="PROVIDER_NAME">%s</xliff:g> ద్వారా మొబైల్ డేటా లేదా రోమింగ్ ప్లాన్ను జోడించవచ్చు."</string>
<string name="mobile_data_activate_diag_title" msgid="5401741936224757312">"డేటాను జోడించాలా?"</string>
<string name="mobile_data_activate_diag_message" msgid="3527260988020415441">"మీరు <xliff:g id="PROVIDER_NAME">%s</xliff:g> ద్వారా డేటాను జోడించాల్సి ఉండవచ్చు"</string>
- <string name="mobile_data_activate_button" msgid="1139792516354374612">"డేటాను జోడించు"</string>
- <string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"రద్దు చేయి"</string>
+ <string name="mobile_data_activate_button" msgid="1139792516354374612">"డేటాను జోడించండి"</string>
+ <string name="mobile_data_activate_cancel_button" msgid="3530174817572005860">"రద్దు చేయండి"</string>
<string name="clh_card_title_call_ended_txt" msgid="5977978317527299698">"కాల్ ముగిసింది"</string>
<string name="clh_callFailed_powerOff_txt" msgid="8279934912560765361">"విమానం మోడ్ ఆన్లో ఉంది"</string>
<string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"SIM కార్డ్ని యాక్సెస్ చేయడం సాధ్యపడలేదు"</string>
@@ -797,20 +797,20 @@
<string name="callFailed_NetworkBusy" msgid="5437103975842913681">"నెట్వర్క్ బిజీగా ఉంది. దయచేసి తిరిగి తర్వాత కాల్ చేయండి."</string>
<string name="callFailed_NetworkCongested" msgid="6801283142342775380">"నెట్వర్క్లో అంతరాయం ఏర్పడింది. సహాయం కోసం మీ మొబైల్ ఆపరేటర్ను సంప్రదించండి."</string>
<string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"కాల్ మళ్లించబడింది."</string>
- <string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"కాల్ ఫార్వార్డ్ చేయబడింది."</string>
+ <string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"కాల్ ఫార్వర్డ్ చేయబడింది."</string>
<string name="supp_service_notification_call_waiting" msgid="4577403881609445324">"కాల్ నిరీక్షణలో ఉంది."</string>
<string name="supp_service_clir_suppression_rejected" msgid="6105737020194776121">"నంబర్ బ్లాకింగ్ తిరస్కరించబడింది."</string>
<string name="supp_service_closed_user_group_call" msgid="2811636666505250689">"దగ్గరి వినియోగదారు సమూహ కాల్."</string>
<string name="supp_service_incoming_calls_barred" msgid="2034627421274447674">"ఇన్కమింగ్ కాల్స్ నిరోధించబడ్డాయి"</string>
<string name="supp_service_outgoing_calls_barred" msgid="5205725332394087112">"అవుట్గోయింగ్ కాల్స్ నిరోధించబడ్డాయి."</string>
- <string name="supp_service_call_forwarding_active" msgid="7910162960395132464">"కాల్ ఫార్వర్డింగ్ సక్రియంగా ఉంది."</string>
- <string name="supp_service_additional_call_forwarded" msgid="8772753260008398632">"అదనపు కాల్ ఫార్వార్డ్ చేయబడింది."</string>
+ <string name="supp_service_call_forwarding_active" msgid="7910162960395132464">"కాల్ ఫార్వర్డింగ్ యాక్టివ్గా ఉంది."</string>
+ <string name="supp_service_additional_call_forwarded" msgid="8772753260008398632">"అదనపు కాల్ ఫార్వర్డ్ చేయబడింది."</string>
<string name="supp_service_additional_ect_connected" msgid="8525934162945220237">"అభ్యంతరకరమైన కాల్ బదిలీ పూర్తయింది."</string>
<string name="supp_service_additional_ect_connecting" msgid="7046240728781222753">"అభ్యంతరకరమైన కాల్ బదిలీ ప్రోగ్రెస్లో ఉంది."</string>
<string name="supp_service_call_on_hold" msgid="2836811319594503059">"కాల్ హోల్డ్లో ఉంది."</string>
<string name="supp_service_call_resumed" msgid="3786864005920743546">"కాల్ మళ్లీ ప్రారంభించబడింది."</string>
<string name="supp_service_deflected_call" msgid="7565979024562921707">"కాల్ మళ్లించబడింది."</string>
- <string name="supp_service_forwarded_call" msgid="6475776013771821457">"కాల్ ఫార్వార్డ్ చేయబడింది."</string>
+ <string name="supp_service_forwarded_call" msgid="6475776013771821457">"కాల్ ఫార్వర్డ్ చేయబడింది."</string>
<string name="supp_service_conference_call" msgid="4004193534408317148">"కాన్ఫరెన్స్ కాల్లో చేరుతున్నారు"</string>
<string name="supp_service_held_call_released" msgid="2847835124639112410">"హోల్డ్లో ఉంచిన కాల్ ప్రారంభించబడింది."</string>
<string name="callFailed_otasp_provisioning_in_process" msgid="3345666183602879326">"వినియోగదారుకు ప్రస్తుతం ఏ సేవలు అందుబాటులో ఉన్నాయనే విచారణ పనిలో పరికరం ఉన్నందున కాల్ చేయడం సాధ్యం కాదు."</string>
@@ -822,7 +822,7 @@
<string name="supp_service_over_ut_precautions_roaming" msgid="670342104569972327">"<xliff:g id="SUPP_SERVICE">%s</xliff:g>ని ఉపయోగించడానికి, మొబైల్ డేటా మరియు డేటా రోమింగ్ని తప్పకుండా ఆన్ చేసారని నిర్ధారించుకోండి. మీరు వీటిని మొబైల్ నెట్వర్క్ సెట్టింగ్లలో మార్చవచ్చు."</string>
<string name="supp_service_over_ut_precautions_dual_sim" msgid="5166866975550910474">"<xliff:g id="SUPP_SERVICE">%1$s</xliff:g>ని ఉపయోగించడానికి, SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g> కోసం మొబైల్ డేటాను తప్పకుండా ఆన్ చేసారని నిర్ధారించుకోండి. మీరు దీనిని మొబైల్ నెట్వర్క్ సెట్టింగ్లలో మార్చవచ్చు."</string>
<string name="supp_service_over_ut_precautions_roaming_dual_sim" msgid="6627654855191817965">"<xliff:g id="SUPP_SERVICE">%1$s</xliff:g>ని ఉపయోగించడానికి, SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g> కోసం మొబైల్ డేటా మరియు డేటా రోమింగ్ని తప్పకుండా ఆన్ చేసారని నిర్ధారించుకోండి. మీరు వీటిని మొబైల్ నెట్వర్క్ సెట్టింగ్లలో మార్చవచ్చు."</string>
- <string name="supp_service_over_ut_precautions_dialog_dismiss" msgid="5934541487903081652">"తీసివేయి"</string>
+ <string name="supp_service_over_ut_precautions_dialog_dismiss" msgid="5934541487903081652">"తీసివేయండి"</string>
<string name="radio_info_data_connection_enable" msgid="6183729739783252840">"డేటా కనెక్షన్ను ప్రారంభించండి"</string>
<string name="radio_info_data_connection_disable" msgid="6404751291511368706">"డేటా కనెక్షన్ను నిలిపివేయండి"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"VoLTE సదుపాయం ఉంది"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"మీరు ఈ సెట్టింగ్ను మార్చడానికి మీ పరికరాన్ని మళ్లీ ప్రారంభించాలి."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"పునఃప్రారంభించు"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"రద్దు చేయండి"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"తీసివేయగలిగే eSIMని ఆటోమేటిక్ సెట్టింగ్గా సెట్ చేయండి"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"మొబైల్ రేడియో పవర్"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"పరికరాన్ని సిమ్యులేట్ చేయడం అందుబాటులో లేదు (డీబగ్ బిల్డ్ మోడ్లో మాత్రమే)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM అడ్రస్ పుస్తకాన్ని చూడండి"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ఫిక్స్డ్ డయలింగ్ నంబర్లను చూడండి"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"సర్వీస్ డయలింగ్ నంబర్లను చూడండి"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"కనెక్ట్ చేయబడింది"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"తాత్కాలికంగా నిలిపివేయబడింది"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"తెలియదు"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"ప్రాథమిక"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"బైట్లు"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -898,7 +901,7 @@
<string name="ping_test_label" msgid="448617502935719694">"పింగ్ పరీక్షను అమలు చేయండి"</string>
<string name="radio_info_smsc_label" msgid="3749927072726033763">"SMSC:"</string>
<string name="radio_info_smsc_update_label" msgid="5141996256097115753">"అప్డేట్ చేయండి"</string>
- <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"రిఫ్రెష్ చేయి"</string>
+ <string name="radio_info_smsc_refresh_label" msgid="8409923721451604560">"రిఫ్రెష్ చేయండి"</string>
<string name="radio_info_toggle_dns_check_label" msgid="1394078554927787350">"DNS తనిఖీని టోగుల్ చేయండి"</string>
<string name="oem_radio_info_label" msgid="2914167475119997456">"OEM-నిర్దిష్ట సమాచారం/సెట్టింగ్లు"</string>
<string name="radio_info_endc_available" msgid="2983767110681230019">"EN-DC అందుబాటులో ఉన్న (NSA):"</string>
@@ -914,11 +917,12 @@
<string name="phone_info_label" product="tablet" msgid="7477478709388477397">"టాబ్లెట్ సమాచారం"</string>
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ఫోన్ సమాచారం"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"క్యారియర్ కేటాయింపు సమాచారం"</string>
- <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"క్యారియర్ కేటాయింపు సక్రియం చేయండి"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC ఎన్టైటిల్మెంట్ ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"అప్డేట్ చేయండి"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"రిఫ్రెష్ చేయండి"</string>
+ <string name="trigger_carrier_provisioning" msgid="1301829588620638234">"క్యారియర్ కేటాయింపు యాక్టివేట్ చేయండి"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"మీ బ్లూటూత్ సిగ్నల్ బలహీనంగా ఉంది. స్పీకర్ఫోన్కు స్విచ్ అవ్వడానికి ట్రై చేయండి."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"కాల్ క్వాలిటీ నోటిఫికేషన్"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"తీసివేయబడిన SIP ఖాతాలు"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ఈ ప్రొఫైల్ నుండి మెసేజ్ పంపడం సాధ్యపడలేదు"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"మీ వర్క్ పాలసీ మిమ్మల్ని వర్క్ ప్రొఫైల్ నుండి మాత్రమే మెసేజ్ పంపడానికి అనుమతిస్తుంది"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"రద్దు చేయండి"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"వర్క్ ప్రొఫైల్కు స్విచ్ అవ్వండి"</string>
</resources>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index d58b5f9..176dea6 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -559,7 +559,7 @@
<string name="emergency_information_hint" msgid="9208897544917793012">"ข้อมูลสำหรับกรณีฉุกเฉิน"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"เจ้าของ"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"แตะอีกครั้งเพื่อดูข้อมูล"</string>
- <string name="emergency_enable_radio_dialog_title" msgid="2667568200755388829">"หมายเลขฉุกเฉิน"</string>
+ <string name="emergency_enable_radio_dialog_title" msgid="2667568200755388829">"โทรฉุกเฉิน"</string>
<string name="single_emergency_number_title" msgid="8413371079579067196">"หมายเลขฉุกเฉิน"</string>
<string name="numerous_emergency_numbers_title" msgid="8972398932506755510">"หมายเลขฉุกเฉิน"</string>
<string name="emergency_call_shortcut_hint" msgid="1290485125107779500">"แตะอีกครั้งเพื่อโทรหา <xliff:g id="EMERGENCY_NUMBER">%s</xliff:g>"</string>
@@ -585,7 +585,7 @@
<string name="onscreenManageCallsText" msgid="1162047856081836469">"จัดการการโทร"</string>
<string name="onscreenManageConferenceText" msgid="4700574060601755137">"จัดการการประชุม"</string>
<string name="onscreenAudioText" msgid="7224226735052019986">"เสียง"</string>
- <string name="onscreenVideoCallText" msgid="1743992456126258698">" Hangouts วิดีโอ"</string>
+ <string name="onscreenVideoCallText" msgid="1743992456126258698">"วิดีโอคอล"</string>
<string name="importSimEntry" msgid="3892354284082689894">"นำเข้า"</string>
<string name="importAllSimEntries" msgid="2628391505643564007">"นำเข้าทั้งหมด"</string>
<string name="importingSimContacts" msgid="4995457122107888932">"กำลังนำเข้าสมุดโทรศัพท์ในซิม"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"คุณต้องรีสตาร์ทอุปกรณ์เพื่อเปลี่ยนการตั้งค่านี้"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"รีสตาร์ท"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"ยกเลิก"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"กำหนดให้ eSIM แบบนำออกได้เป็นค่าเริ่มต้น"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"กำลังส่งของวิทยุเครือข่ายมือถือ"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"จําลองความไม่พร้อมให้บริการ (บิลด์การแก้ไขข้อบกพร่องเท่านั้น)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ดูสมุดที่อยู่ของซิม"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ดูการจำกัดหมายเลขโทรออก"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ดูหมายเลขรับบริการโทรออก"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"เชื่อมต่อแล้ว"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"ถูกระงับ"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"ไม่รู้จัก"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"หลัก"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"ไบต์"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"ข้อมูลโทรศัพท์"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"ข้อมูลการจัดสรรผู้ให้บริการ"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ทริกเกอร์การจัดสรรผู้ให้บริการ"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"รหัสการให้สิทธิ์ WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"อัปเดต"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"รีเฟรช"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"สัญญาณบลูทูธอ่อน ลองเปลี่ยนไปใช้ลำโพงแทน"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"การแจ้งเตือนคุณภาพการโทร"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"บัญชี SIP ที่เลิกใช้งาน"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"ส่งข้อความจากโปรไฟล์นี้ไม่ได้"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"นโยบายการทำงานอนุญาตให้คุณส่งข้อความได้จากโปรไฟล์งานเท่านั้น"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"ยกเลิก"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"สลับไปใช้โปรไฟล์งาน"</string>
</resources>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index fb63129..433d247 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -511,7 +511,7 @@
<string name="invalidPuk2" msgid="713729511903849544">"Maglagay ng PUK2 na 8 numero."</string>
<string name="pin2_changed" msgid="5710551850481287821">"Na-update na ang PIN2"</string>
<string name="label_puk2_code" msgid="2852217004288085562">"Ilagay ang PUK2 code"</string>
- <string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"Mali ang password. Naka-block na ngayon ang PIN2. Upang subukang muli, baguhin ang PIN 2."</string>
+ <string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"Mali ang password. Naka-block na ngayon ang PIN2. Upang subukan ulit, baguhin ang PIN 2."</string>
<string name="puk2_requested" msgid="6992374450720307514">"Mali ang password. Naka-lock na ngayon ang SIM. Ilagay ang PUK2."</string>
<string name="puk2_blocked" msgid="3131139031779319911">"Permanenteng na-block ang PUK2."</string>
<string name="pin2_attempts" msgid="5625178102026453023">\n"Mayroon ka na lang <xliff:g id="NUMBER">%d</xliff:g> (na) natitirang pagsubok."</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Kailangan mong i-restart ang device para mabago ang setting."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"I-restart"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Kanselahin"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Itakda na Default ang Naaalis na eSIM"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobile Radio Power"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Mag-simulate ng Hindi Gumagana (Build sa Pag-debug lang)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Tingnan ang Address Book ng SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Tingnan ang Mga Fixed Dialing Number"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Tingnan ang Mga Service Dialing Number"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Konektado"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Sinuspinde"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Hindi alam"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Pangunahin"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bytes"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Impormasyon ng telepono"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Impormasyon sa Provisioning ng Carrier"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"I-trigger ang Provisioning ng Carrier"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"I-update"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"I-refresh"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Mahina ang signal ng iyong bluetooth. Subukang lumipat sa speakerphone."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Notification sa Kalidad ng Tawag"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Mga hindi na ginagamit na SIP account"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Hindi makakapagpadala ng mensahe mula sa profile na ito"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Pinapayagan ka ng iyong patakaran sa trabaho na magpadala ng mensahe mula lang sa profile sa trabaho"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Kanselahin"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Lumipat sa profile sa trabaho"</string>
</resources>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 41a997b..db8e1ca 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Bu ayarı değiştirmek için cihazınızı yeniden başlatın."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Yeniden başlat"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"İptal"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Çıkarılabilir eSIM\'i Varsayılan Yap"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Mobil Radyo Gücü"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Hizmet Dışı Simülasyonu (Yalnızca Hata Ayıklama Derlemesi)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM Adres Defterini Görüntüle"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Sabit Arama Numaralarını Görüntüle"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Hizmet Arama Numaralarını Görüntüle"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Bağlı"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Askıya alındı"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Bilinmiyor"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Birincil"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkt"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bayt"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefon bilgileri"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operatör Temel Hazırlık Bilgileri"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Tetikleyici Operatör Temel Hazırlığı"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Yararlanma Hakkı Kimliği:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Güncelle"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Yenile"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth sinyaliniz zayıf. Hoparlöre geçmeyi deneyin."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Arama Kalitesiyle İlgili Bildirim"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Kullanımdan kaldırılan SIP hesapları"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Bu profilden mesaj gönderilemiyor"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"İşletme politikanız yalnızca iş profilinden mesaj göndermenize izin veriyor"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"İptal"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"İş profiline geç"</string>
</resources>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 17c01a6..c9f26c8 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -52,7 +52,7 @@
<string name="label_ndp" msgid="7617392683877410341">"Розбл. PIN-код мережі SIM"</string>
<string name="label_phoneid" msgid="8775611434123577808">"Заблокована SIM-карта оператора"</string>
<string name="sim_ndp_unlock_text" msgid="7737338355451978338">"Розблок."</string>
- <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Відхилити"</string>
+ <string name="sim_ndp_dismiss_text" msgid="89667342248929777">"Закрити"</string>
<string name="requesting_unlock" msgid="930512210309437741">"Запитув. розблок. мережі..."</string>
<string name="unlock_failed" msgid="7103543844840661366">"Не здійсн. запит розблокування мережі"</string>
<string name="unlock_success" msgid="32681089371067565">"Мережу успішно розблоковано."</string>
@@ -643,7 +643,7 @@
<string name="progress_dialog_exiting_ecm" msgid="9159080081676927217">"Вихід із режиму екстреного зворотного виклику"</string>
<string name="alert_dialog_yes" msgid="3532525979632841417">"Так"</string>
<string name="alert_dialog_no" msgid="1075632654085988420">"Ні"</string>
- <string name="alert_dialog_dismiss" msgid="1336356286354517054">"Відхилити"</string>
+ <string name="alert_dialog_dismiss" msgid="1336356286354517054">"Закрити"</string>
<string name="phone_in_ecm_call_notification_text_without_data_restriction_hint" msgid="3747860785153531225">"Телефон перебуває в режимі екстреного зворотного виклику"</string>
<string name="phone_in_ecm_notification_complete_time_without_data_restriction_hint" msgid="3690292264812050858">"До <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
<!-- format error in translation for alert_dialog_exit_ecm_without_data_restriction_hint (7549850847524907932) -->
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Щоб змінити це налаштування, перезапустіть пристрій."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Перезапустити"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Скасувати"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Установити знімну eSIM-карту як карту за умовчанням"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Потужність мобільного радіо"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Імітація знаходження поза зоною обслуговування (лише складання для налагодження)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Переглянути адресну книгу SIM-карти"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Переглянути фіксовані номери"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Переглянути службові номери"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Підключено"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Заблоковано"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Невідомо"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Основний"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"пак."</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"байт"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"дБм"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Інформація про телефон"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Інформація про ініціалізацію оператора"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Запустити ініціалізацію оператора"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Ідентифікатор доступу WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Оновити"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Оновити"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Сигнал Bluetooth заслабкий. Спробуйте переключитися на гучний зв\'язок."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Сповіщення про якість виклику"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Облікові записи SIP, що не підтримуються"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Надіслати повідомлення з цього профілю не можна"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Відповідно до правил організації ви можете надсилати повідомлення лише з робочого профілю"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Скасувати"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Перейти в робочий профіль"</string>
</resources>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index e54b8eb..9ed0675 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"یہ ترتیب تبدیل کرنے کیلئے آپ کو اپنا آلہ ریسٹارٹ کرنا ہوگا۔"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"دوبارہ شروع کریں"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"منسوخ کریں"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"ہٹانے لائق eSIM کو بطور ڈیفالٹ سیٹ کریں"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"موبائل ریڈیو پاور"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"\'سروس دستیاب نہیں ہے\' موڈ کو سمیولیٹ کریں (صرف ڈیبگ بلڈ کیلئے)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM ایڈریس بک دیکھیں"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"فکسڈ ڈائلنگ نمبرز دیکھیں"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"سروس ڈائلنگ نمبرز دیکھیں"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"منسلک"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"معطل کر دیا گیا"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"نامعلوم"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"بنیادی"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"پیکٹس"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"بائٹس"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"فون کی معلومات"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"کیرئیر فراہمی معلومات"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"ٹرگر کیرئیر فراہمی"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC Entitlement ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"اپ ڈیٹ کریں"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"ریفریش کریں"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"آپ کا بلوٹوتھ سگنل کمزور ہے۔ اسپیکر فون پر سوئچ کر کے آزمائیں۔"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"کال کی کوالٹی کی اطلاع"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"فرسودہ SIP اکاؤنٹس"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"اس پروفائل سے پیغام نہیں بھیج سکتے"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"آپ کے کام سے متعلق پالیسی آپ کو صرف دفتری پروفائل سے پیغام بھیجنے کی اجازت دیتی ہے"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"منسوخ کریں"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"دفتری پروفائل پر سوئچ کریں"</string>
</resources>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 5803846..e9de41e 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Bu sozlamani o‘zgartirish uchun qurilmangizni o‘chirib yoqing."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"O‘chirib yoqish"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Bekor qilish"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Olinadigan eSIM kartani birlamchi qilib belgilash"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Radio signal quvvati"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Xizmatdan tashqari simulyatsiya (faqat nosozliklarni aniqlash dasturi uchun)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"SIM kartadagi abonentlar ro‘yxatini ochish"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Ruxsat etilgan raqamlar ro‘yxatini ochish"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Xizmatlarni terish raqamlarini ochish"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Ulangan"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Bloklangan"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Noma’lum"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Asosiy"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"bayt"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Telefon haqida"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Operator sinxronizatsiyasi haqida"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Operator sinxronizatsiyasini yoqish/o‘chirish"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC ruxsat identifikatori:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Yangilash"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Yangilash"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Bluetooth signali kuchsiz. Baland ovoz rejimini yoqish tavsiya etiladi."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Chaqiruv sifati haqida bildirishnoma"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"To‘xtatilgan SIP hisoblar"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Bu profildan xabar yuborish imkonsiz"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Ishga oid siyosatingiz faqat ish profilidan xabar yuborish imkonini beradi"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Bekor qilish"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Ish profiliga almashish"</string>
</resources>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index 4fcd4d8..d573c69 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Bạn cần khởi động lại thiết bị để thay đổi chế độ cài đặt này."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Khởi động lại"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Hủy"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Đặt eSIM có thể tháo rời là Mặc định"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Cường độ của sóng di động"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Mô phỏng thiết bị không hoạt động (chỉ dành cho bản gỡ lỗi)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Xem sổ địa chỉ trên SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Xem số gọi định sẵn"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Xem số quay số dịch vụ"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Đã kết nối"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Bị tạm ngưng"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Không xác định"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Chính"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"byte"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Thông tin điện thoại"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Thông tin cấp phép của nhà mạng"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Kích hoạt dịch vụ cấp phép của nhà mạng"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"Mã quyền đối với WFC:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Cập nhật"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Làm mới"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Tín hiệu Bluetooth của bạn đang yếu. Hãy thử chuyển sang loa ngoài."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Thông báo về chất lượng cuộc gọi"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Tài khoản SIP không dùng nữa"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Không gửi được tin nhắn từ hồ sơ này"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Chính sách của nơi làm việc chỉ cho phép bạn gửi tin nhắn từ hồ sơ công việc"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Huỷ"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Chuyển sang hồ sơ công việc"</string>
</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index bea64da..456fef4 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -575,7 +575,7 @@
<string name="fire_type_description" msgid="6565200468934914930">"火警"</string>
<string name="description_concat_format" msgid="2014471565101724088">"%1$s、%2$s"</string>
<string name="dialerKeyboardHintText" msgid="1115266533703764049">"使用键盘拨号"</string>
- <string name="onscreenHoldText" msgid="4025348842151665191">"保持"</string>
+ <string name="onscreenHoldText" msgid="4025348842151665191">"保持通话"</string>
<string name="onscreenEndCallText" msgid="6138725377654842757">"挂断"</string>
<string name="onscreenShowDialpadText" msgid="658465753816164079">"拨号键盘"</string>
<string name="onscreenMuteText" msgid="5470306116733843621">"静音"</string>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"您需要重启设备才能让这项设置更改生效。"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"重启"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"取消"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"将可卸载的 eSIM 卡设为默认 eSIM 卡"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"移动无线装置电源"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"模拟服务终止(仅限调试 build)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"查看 SIM 卡通讯录"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"查看固定拨号号码"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"查看服务拨号号码"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"已连接"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"已暂停"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"未知"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"主要"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"字节"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"手机信息"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"运营商配置信息"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"触发运营商配置"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC 权限 ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"更新"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"刷新"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"您的蓝牙信号较弱。请尝试切换为扬声器模式。"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"通话质量通知"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"已弃用的 SIP 帐号"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"无法通过此资料发送消息"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"根据您的工作政策,您只能通过工作资料发送消息"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"取消"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"切换到工作资料"</string>
</resources>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 6d42019..b0e8797 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"您需要重新啟動裝置,才可變更此設定。"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"重新啟動"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"取消"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"將可移除的 eSIM 卡設為預設值"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"流動無線電的電源"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"模擬沒有服務 (僅限偵錯版本)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"查看 SIM 卡通訊錄"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"查看固定撥號"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"查看服務撥號"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"已連線"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"已停用"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"不明"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"主要"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkt"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"位元組"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"手機資訊"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"流動網絡供應商佈建資料"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"觸發流動網絡供應商佈建程序"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC 授權 ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"更新"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"重新整理"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"您的藍牙訊號微弱。請改用擴音器。"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"通話品質通知"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"已停用的 SIP 帳戶"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"無法從此個人檔案傳送訊息"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"您的工作政策只允許透過工作設定檔傳送訊息"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"取消"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"切換至工作設定檔"</string>
</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index c3d4bf4..3789f8a 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"你必須重新啟動裝置,才能變更這項設定。"</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"重新啟動"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"取消"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"將可移除的 eSIM 卡設為預設 eSIM 卡"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"行動無線電電源"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"模擬無法使用服務的情況 (僅限偵錯版本)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"查看 SIM 通訊錄"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"查看固定撥號"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"查看服務撥號號碼"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"已連線"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"待命"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"不明"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"主要"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"pkts"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"位元組"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"手機資訊"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"電信業者佈建資訊"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"觸發電信業者佈建程序"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"WFC 授權 ID:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"更新"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"重新整理"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"你的藍牙訊號微弱,建議你改用擴音模式。"</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"通話品質通知"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"不適用的 SIP 帳戶"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"無法透過這個資料夾傳送訊息"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"貴公司政策僅允許透過工作資料夾傳送訊息"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"取消"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"切換至工作資料夾"</string>
</resources>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index fbedd2b..8838b04 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -357,13 +357,13 @@
<string name="list_language_title" msgid="1850167908665485738">"Ulimi"</string>
<string name="list_language_summary" msgid="7921756070782277559">"Khetha ulimi lwezindaba"</string>
<string-array name="list_language_entries">
- <item msgid="2347238508726934281">"i-English"</item>
+ <item msgid="2347238508726934281">"English"</item>
<item msgid="5172468397620875174">"isi-French"</item>
<item msgid="3978110664146015398">"isi-Spanish"</item>
<item msgid="2637764545851526369">"isi-Japanese"</item>
- <item msgid="6103816221834932751">"isi-Korean"</item>
- <item msgid="3127367370005168399">"isi-Chinese"</item>
- <item msgid="9130651361816196355">"isi-Hebrew"</item>
+ <item msgid="6103816221834932751">"Korean"</item>
+ <item msgid="3127367370005168399">"Chinese"</item>
+ <item msgid="9130651361816196355">"Hebrew"</item>
</string-array>
<string-array name="list_language_values">
<item msgid="798673247233934667">"1"</item>
@@ -835,7 +835,9 @@
<string name="dsds_dialog_message" msgid="4047480385678538850">"Udinga ukuqalisa kabusha idivayisi yakho ukushintsha lesi silungiselelo."</string>
<string name="dsds_dialog_confirm" msgid="9032004888134129885">"Qala kabusha"</string>
<string name="dsds_dialog_cancel" msgid="3245958947099586655">"Khansela"</string>
+ <string name="removable_esim_string" msgid="7931369811671787649">"Setha i-eSim Esusekayo Njengezenzakalelayo"</string>
<string name="radio_info_radio_power" msgid="8805595022160471587">"Amandla erediyo yeselula"</string>
+ <string name="simulate_out_of_service_string" msgid="7787925611727597193">"Lingisa okuthi Ayikho Isevisi (Umakhiwo Wokususa Iphutha kuphela)"</string>
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"Buka incwadi yekheli le-SIM"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"Buka Izinombolo Zokudayela Okungaguquki"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"Buka Izinombolo Zokudayela Isevisi"</string>
@@ -860,6 +862,7 @@
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Ixhunyiwe"</string>
<string name="radioInfo_data_suspended" msgid="8695262782642002785">"Kumiswe okwesikhashana"</string>
<string name="radioInfo_unknown" msgid="5401423738500672850">"Akwaziwa"</string>
+ <string name="radioInfo_imei_primary" msgid="5948747378637224400">"Okuyinhloko"</string>
<string name="radioInfo_display_packets" msgid="6794302192441084157">"amaphakethe"</string>
<string name="radioInfo_display_bytes" msgid="7701006329222413797">"amabhaythi"</string>
<string name="radioInfo_display_dbm" msgid="7491944975710865703">"dBm"</string>
@@ -915,10 +918,11 @@
<string name="phone_info_label" product="default" msgid="1784175881556791433">"Ulwazi lwefoni"</string>
<string name="carrier_provisioning" msgid="2668065041869578376">"Ulwazi lokuhlinzeka lenkampani yenethiwekhi"</string>
<string name="trigger_carrier_provisioning" msgid="1301829588620638234">"Cupha ukunikezwa kwenkampani yenethiwekhi"</string>
- <string name="provisioning_info_wfc_entitlement_id" msgid="8845188780811890910">"I-ID WFC Entitlement:"</string>
- <string name="update_provisioning_info_wfc_entitlement_id" msgid="7044171908781134221">"Vuselela"</string>
- <string name="refresh_provisioning_info_wfc_entitlement_id" msgid="738894335351353407">"Vuselela"</string>
<string name="call_quality_notification_bluetooth_details" msgid="8348950331707346711">"Isignali yakho ye-bluetooth ayiqinile. Zama ukushintshela kusipikhasefoni."</string>
<string name="call_quality_notification_name" msgid="3476828289553948830">"Isaziso Sekhwalithi"</string>
<string name="notification_channel_sip_account" msgid="1261816025156179637">"Ama-akhawunti we-SIP ehlisiwe"</string>
+ <string name="send_from_work_profile_title" msgid="9201528838448432473">"Ayikwazi ukuthumela umyalezo kusukela kule phrofayela"</string>
+ <string name="send_from_work_profile_description" msgid="5002701841936861636">"Inqubomgomo yakho yomsebenzi ikuvumela ukuthi uthumele umyalezo kuphela usuka kuphrofayela yomsebenzi"</string>
+ <string name="send_from_work_profile_cancel" msgid="177746511030381711">"Khansela"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"Shintshela kuphrofayela yomsebenzi"</string>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 19252c0..ba65302 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -317,4 +317,8 @@
<!-- The package names which can request thermal mitigation. -->
<string-array name="thermal_mitigation_allowlisted_packages" translatable="false">
</string-array>
+
+ <!-- Flag specifying whether the AOSP domain selection is enabled or
+ the device should fallback to the modem based domain selection architecture. -->
+ <bool name="config_enable_aosp_domain_selection">false</bool>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 38a86f9..e21f761 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2010,6 +2010,9 @@
<!-- Title for controlling on/off for Mobile phone's radio power. Only shown in diagnostic screen, so precise translation is not needed. -->
<string name="radio_info_radio_power">Mobile Radio Power</string>
+ <!-- Title for simulating device out of service. -->
+ <string name="simulate_out_of_service_string">Simulate Out of Service (Debug Build only)</string>
+
<!-- Phone Info screen. Menu item label. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radioInfo_menu_viewADN">View SIM Address Book</string>
<!-- Phone Info screen. Menu item label. Used for diagnostic info screens, precise translation isn't needed -->
@@ -2067,6 +2070,8 @@
<!-- Used for diagnostic info screens, precise translation isn't needed -->
<string name="radioInfo_unknown">Unknown</string>
+ <!-- Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radioInfo_imei_primary">Primary</string>
<!-- Phone Info screen. Units shown after a value. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radioInfo_display_packets">pkts</string>
<!-- Phone Info screen. Units shown after a value. Used for diagnostic info screens, precise translation isn't needed -->
@@ -2198,4 +2203,10 @@
<!-- Telephony notification channel name for a channel containing SIP accounts removed
notificatios -->
<string name="notification_channel_sip_account">Deprecated SIP accounts</string>
+
+ <string name="send_from_work_profile_title">Can\'t send message from this profile</string>
+ <string name="send_from_work_profile_description">Your work policy allows you to send message only from the work profile</string>
+ <string name="send_from_work_profile_cancel">Cancel</string>
+ <string name="send_from_work_profile_action_str">Switch to work profile</string>
+
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index d0f427c..19798f0 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -309,6 +309,17 @@
<item name="android:backgroundDimEnabled">false</item>
</style>
+ <style name="Theme.Telephony.Transparent" parent="@android:style/Theme.DeviceDefault.Light">
+ <item name="android:forceDarkAllowed">true</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:backgroundDimEnabled">true</item>
+ <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
+ </style>
+
<style name="CallSettingsWithoutDividerTheme" parent="DialerSettingsLight">
<item name="android:listDivider">@null</item>
</style>
diff --git a/src/com/android/phone/CLIRListPreference.java b/src/com/android/phone/CLIRListPreference.java
old mode 100755
new mode 100644
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index fdd610e..145df41 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -16,6 +16,7 @@
package com.android.phone;
+import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -268,6 +269,12 @@
getActionBar(), getResourcesForSubId(), R.string.call_settings_with_label);
mTelecomManager = getSystemService(TelecomManager.class);
mTelephonyCallback = new CallFeaturesTelephonyCallback();
+
+ ActionBar actionBar = getActionBar();
+ if (actionBar != null) {
+ // sets the talkback voice prompt to say "Back" instead of "Navigate Up"
+ actionBar.setHomeActionContentDescription(R.string.ota_call_end);
+ }
}
private void updateImsManager(Phone phone) {
diff --git a/src/com/android/phone/CallForwardEditPreference.java b/src/com/android/phone/CallForwardEditPreference.java
index 2cbb7c5..96915d4 100644
--- a/src/com/android/phone/CallForwardEditPreference.java
+++ b/src/com/android/phone/CallForwardEditPreference.java
@@ -28,6 +28,7 @@
import com.android.internal.telephony.Phone;
import java.util.HashMap;
+import java.util.Locale;
public class CallForwardEditPreference extends EditPhoneNumberPreference {
private static final String LOG_TAG = "CallForwardEditPreference";
@@ -287,7 +288,7 @@
if (telephonyManager == null) {
return "";
}
- return telephonyManager.getNetworkCountryIso().toUpperCase();
+ return telephonyManager.getNetworkCountryIso().toUpperCase(Locale.ROOT);
}
// Message protocol:
diff --git a/src/com/android/phone/CallNotifier.java b/src/com/android/phone/CallNotifier.java
index 7f61f78..14db930 100644
--- a/src/com/android/phone/CallNotifier.java
+++ b/src/com/android/phone/CallNotifier.java
@@ -40,10 +40,12 @@
import com.android.internal.telephony.CallManager;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaDisplayInfoRec;
import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec;
import com.android.internal.telephony.cdma.SignalToneUtil;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import java.util.ArrayList;
import java.util.Collections;
@@ -487,9 +489,16 @@
}
public void updatePhoneStateListeners(boolean isRefresh, int updateType, int subIdToUpdate) {
- List<SubscriptionInfo> subInfos = SubscriptionController.getInstance()
- .getActiveSubscriptionInfoList(mApplication.getOpPackageName(),
- mApplication.getAttributionTag());
+ List<SubscriptionInfo> subInfos;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ subInfos = SubscriptionManagerService.getInstance()
+ .getActiveSubscriptionInfoList(mApplication.getOpPackageName(),
+ mApplication.getAttributionTag());
+ } else {
+ subInfos = SubscriptionController.getInstance()
+ .getActiveSubscriptionInfoList(mApplication.getOpPackageName(),
+ mApplication.getAttributionTag());
+ }
// Sort sub id list based on slot id, so that CFI/MWI notifications will be updated for
// slot 0 first then slot 1. This is needed to ensure that when CFI or MWI is enabled for
@@ -498,8 +507,8 @@
List<Integer> subIdList = new ArrayList<Integer>(mTelephonyCallback.keySet());
Collections.sort(subIdList, new Comparator<Integer>() {
public int compare(Integer sub1, Integer sub2) {
- int slotId1 = SubscriptionController.getInstance().getSlotIndex(sub1);
- int slotId2 = SubscriptionController.getInstance().getSlotIndex(sub2);
+ int slotId1 = SubscriptionManager.getSlotIndex(sub1);
+ int slotId2 = SubscriptionManager.getSlotIndex(sub2);
return slotId1 > slotId2 ? 0 : -1;
}
});
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 69f29bd..9d11dfc 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -52,6 +52,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.LocalLog;
@@ -61,9 +62,11 @@
import com.android.internal.telephony.ICarrierConfigLoader;
import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConfigurationManager;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SubscriptionInfoUpdater;
import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.telephony.Rlog;
@@ -126,7 +129,7 @@
// SubscriptionInfoUpdater
@NonNull private final SubscriptionInfoUpdater mSubscriptionInfoUpdater;
- // Broadcast receiver for system events (BootCompleted, MultiSimConfigChanged etc.)
+ // Broadcast receiver for system events
@NonNull
private final BroadcastReceiver mSystemBroadcastReceiver = new ConfigLoaderBroadcastReceiver();
@NonNull private final LocalLog mCarrierConfigLoadingLog = new LocalLog(100);
@@ -308,7 +311,7 @@
// smoothly.
mConfigFromDefaultApp[phoneId] = new PersistableBundle();
// Send broadcast if bind fails.
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
// TODO: We *must* call unbindService even if bindService returns false.
// (And possibly if SecurityException was thrown.)
loge("binding to default app: "
@@ -343,7 +346,7 @@
if (resultCode == RESULT_ERROR || resultData == null) {
// On error, abort config fetching.
loge("Failed to get carrier config");
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
return;
}
PersistableBundle config =
@@ -392,7 +395,7 @@
}
// Put a stub bundle in place so that the rest of the logic continues smoothly.
mConfigFromDefaultApp[phoneId] = new PersistableBundle();
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
break;
}
@@ -408,7 +411,7 @@
logd("Found carrier config app: " + carrierPackageName);
sendMessage(obtainMessage(EVENT_DO_FETCH_CARRIER, phoneId, -1));
} else {
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
}
break;
}
@@ -442,7 +445,7 @@
// Send broadcast if bind fails.
broadcastConfigChangedIntent(phoneId);
loge("Bind to carrier app: " + carrierPackageName + " fails");
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
}
}
break;
@@ -475,7 +478,7 @@
loge("Failed to get carrier config from carrier app: "
+ getCarrierPackageForPhoneId(phoneId));
broadcastConfigChangedIntent(phoneId);
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
return;
}
PersistableBundle config =
@@ -532,7 +535,7 @@
}
// Put a stub bundle in place so that the rest of the logic continues smoothly.
mConfigFromCarrierApp[phoneId] = new PersistableBundle();
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
break;
}
case EVENT_FETCH_CARRIER_DONE: {
@@ -542,7 +545,7 @@
&& mServiceConnection[phoneId] == null) {
break;
}
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
break;
}
@@ -695,7 +698,8 @@
*/
@VisibleForTesting
/* package */ CarrierConfigLoader(@NonNull Context context,
- @NonNull SubscriptionInfoUpdater subscriptionInfoUpdater, @NonNull Looper looper) {
+ //TODO: Remove SubscriptionInfoUpdater.
+ @Nullable SubscriptionInfoUpdater subscriptionInfoUpdater, @NonNull Looper looper) {
mContext = context;
mPlatformCarrierConfigPackage =
mContext.getString(R.string.platform_carrier_config_package);
@@ -703,7 +707,6 @@
IntentFilter systemEventsFilter = new IntentFilter();
systemEventsFilter.addAction(Intent.ACTION_BOOT_COMPLETED);
- systemEventsFilter.addAction(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED);
context.registerReceiver(mSystemBroadcastReceiver, systemEventsFilter);
mNumPhones = TelephonyManager.from(context).getActiveModemCount();
@@ -726,6 +729,10 @@
}
logd("CarrierConfigLoader has started");
mSubscriptionInfoUpdater = subscriptionInfoUpdater;
+
+ PhoneConfigurationManager.registerForMultiSimConfigChange(
+ mHandler, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
+
mHandler.sendEmptyMessage(EVENT_CHECK_SYSTEM_UPDATE);
}
@@ -760,6 +767,11 @@
}
}
+ if (mConfigFromDefaultApp.length <= phoneId) {
+ Log.wtf(LOG_TAG, "Invalid phone id " + phoneId);
+ return;
+ }
+
mConfigFromDefaultApp[phoneId] = null;
mConfigFromCarrierApp[phoneId] = null;
mServiceConnection[phoneId] = null;
@@ -773,17 +785,18 @@
}
}
- private void notifySubscriptionInfoUpdater(int phoneId) {
- String configPackagename;
+ private void updateSubscriptionDatabase(int phoneId) {
+ logd("updateSubscriptionDatabase: phoneId=" + phoneId);
+ String configPackageName;
PersistableBundle configToSend;
int carrierId = getSpecificCarrierIdForPhoneId(phoneId);
// Prefer the carrier privileged carrier app, but if there is not one, use the platform
// default carrier app.
if (mConfigFromCarrierApp[phoneId] != null) {
- configPackagename = getCarrierPackageForPhoneId(phoneId);
+ configPackageName = getCarrierPackageForPhoneId(phoneId);
configToSend = mConfigFromCarrierApp[phoneId];
} else {
- configPackagename = mPlatformCarrierConfigPackage;
+ configPackageName = mPlatformCarrierConfigPackage;
configToSend = mConfigFromDefaultApp[phoneId];
}
@@ -798,9 +811,16 @@
configToSend.putAll(config);
}
- mSubscriptionInfoUpdater.updateSubscriptionByCarrierConfigAndNotifyComplete(
- phoneId, configPackagename, configToSend,
- mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1));
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ SubscriptionManagerService.getInstance().updateSubscriptionByCarrierConfig(
+ phoneId, configPackageName, configToSend,
+ () -> mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1)
+ .sendToTarget());
+ } else {
+ mSubscriptionInfoUpdater.updateSubscriptionByCarrierConfigAndNotifyComplete(
+ phoneId, configPackageName, configToSend,
+ mHandler.obtainMessage(EVENT_SUBSCRIPTION_INFO_UPDATED, phoneId, -1));
+ }
}
private void broadcastConfigChangedIntent(int phoneId) {
@@ -808,33 +828,39 @@
}
private void broadcastConfigChangedIntent(int phoneId, boolean addSubIdExtra) {
+ int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+ int specificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+
Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
Intent.FLAG_RECEIVER_FOREGROUND);
if (addSubIdExtra) {
- int simApplicationState = TelephonyManager.SIM_STATE_UNKNOWN;
- int subId = SubscriptionManager.getSubscriptionId(phoneId);
- if (SubscriptionManager.isValidSubscriptionId(subId)) {
- TelephonyManager telMgr = TelephonyManager.from(mContext)
- .createForSubscriptionId(subId);
- simApplicationState = telMgr.getSimApplicationState();
- }
- logd("Broadcast CARRIER_CONFIG_CHANGED for phone " + phoneId
- + " simApplicationState " + simApplicationState);
+ int simApplicationState = getSimApplicationStateForPhone(phoneId);
// Include subId/carrier id extra only if SIM records are loaded
if (simApplicationState != TelephonyManager.SIM_STATE_UNKNOWN
&& simApplicationState != TelephonyManager.SIM_STATE_NOT_READY) {
+ subId = SubscriptionManager.getSubscriptionId(phoneId);
+ carrierId = getCarrierIdForPhoneId(phoneId);
+ specificCarrierId = getSpecificCarrierIdForPhoneId(phoneId);
+ intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID, specificCarrierId);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId);
- intent.putExtra(TelephonyManager.EXTRA_SPECIFIC_CARRIER_ID,
- getSpecificCarrierIdForPhoneId(phoneId));
- intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, getCarrierIdForPhoneId(phoneId));
+ intent.putExtra(TelephonyManager.EXTRA_CARRIER_ID, carrierId);
}
}
intent.putExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, phoneId);
intent.putExtra(CarrierConfigManager.EXTRA_REBROADCAST_ON_UNLOCK,
mFromSystemUnlocked[phoneId]);
+
+ TelephonyRegistryManager trm = mContext.getSystemService(TelephonyRegistryManager.class);
+ // Unlike broadcast, we wouldn't notify registrants on carrier config change when device is
+ // unlocked. Only real carrier config change will send the notification to registrants.
+ if (trm != null && !mFromSystemUnlocked[phoneId]) {
+ trm.notifyCarrierConfigChanged(phoneId, subId, carrierId, specificCarrierId);
+ }
+
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
- int subId = SubscriptionManager.getSubscriptionId(phoneId);
+
if (SubscriptionManager.isValidSubscriptionId(subId)) {
logd("Broadcast CARRIER_CONFIG_CHANGED for phone " + phoneId + ", subId=" + subId);
} else {
@@ -844,6 +870,17 @@
mFromSystemUnlocked[phoneId] = false;
}
+ private int getSimApplicationStateForPhone(int phoneId) {
+ int simApplicationState = TelephonyManager.SIM_STATE_UNKNOWN;
+ int subId = SubscriptionManager.getSubscriptionId(phoneId);
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ TelephonyManager telMgr = TelephonyManager.from(mContext)
+ .createForSubscriptionId(subId);
+ simApplicationState = telMgr.getSimApplicationState();
+ }
+ return simApplicationState;
+ }
+
/** Binds to the default or carrier config app. */
private boolean bindToConfigPackage(@NonNull String pkgName, int phoneId, int eventId) {
logdWithLocalLog("Binding to " + pkgName + " for phone " + phoneId);
@@ -987,7 +1024,7 @@
if (isNoSimConfig) {
fileName = getFilenameForNoSimConfig(packageName);
} else {
- if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
+ if (TelephonyManager.getSimStateForSlotIndex(phoneId)
!= TelephonyManager.SIM_STATE_LOADED) {
loge("Skip save config because SIM records are not loaded.");
return;
@@ -1078,7 +1115,7 @@
if (isNoSimConfig) {
fileName = getFilenameForNoSimConfig(packageName);
} else {
- if (SubscriptionManager.getSimStateForSlotIndex(phoneId)
+ if (TelephonyManager.getSimStateForSlotIndex(phoneId)
!= TelephonyManager.SIM_STATE_LOADED) {
loge("Skip restore config because SIM records are not loaded.");
return null;
@@ -1179,12 +1216,24 @@
});
if (packageFiles == null || packageFiles.length < 1) return false;
for (File f : packageFiles) {
- logd("Deleting " + f.getName());
+ logd("Deleting " + getFilePathForLogging(f.getName()));
f.delete();
}
return true;
}
+ private String getFilePathForLogging(String filePath) {
+ if (!TextUtils.isEmpty(filePath)) {
+ String[] fileTokens = filePath.split("-");
+ if (fileTokens != null && fileTokens.length > 2) {
+ String iccid = fileTokens[fileTokens.length -2];
+ return getFilePathForLogging(filePath, iccid);
+ }
+ return filePath;
+ }
+ return filePath;
+ }
+
/** Builds a canonical file name for a config file. */
@NonNull
private static String getFilenameForConfig(
@@ -1344,17 +1393,18 @@
}
for (String key : keys) {
Objects.requireNonNull(key, "Config key must be non-null");
- // TODO(b/261776046): validate provided key which may has no default value.
- // For now, return empty bundle if any required key is not supported
- if (!allConfigs.containsKey(key)) {
- return new PersistableBundle();
- }
}
PersistableBundle configSubset = new PersistableBundle(
keys.length + CONFIG_SUBSET_METADATA_KEYS.length);
for (String carrierConfigKey : keys) {
Object value = allConfigs.get(carrierConfigKey);
+ if (value == null) {
+ // Filter out keys without values.
+ // In history, many AOSP or OEMs/carriers private configs didn't provide default
+ // values. We have to continue supporting them for now. See b/261776046 for details.
+ continue;
+ }
// Config value itself could be PersistableBundle which requires different API to put
if (value instanceof PersistableBundle) {
configSubset.putPersistableBundle(carrierConfigKey, (PersistableBundle) value);
@@ -1376,7 +1426,6 @@
boolean persistent) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.MODIFY_PHONE_STATE, null);
- //TODO: Also check for SHELL UID to restrict this method to testing only (b/131326259)
int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
@@ -1404,7 +1453,7 @@
fileToDelete.delete();
}
}
- notifySubscriptionInfoUpdater(phoneId);
+ updateSubscriptionDatabase(phoneId);
});
}
@@ -1784,10 +1833,6 @@
case Intent.ACTION_BOOT_COMPLETED:
mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_UNLOCKED, null));
break;
-
- case TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED:
- mHandler.sendEmptyMessage(EVENT_MULTI_SIM_CONFIG_CHANGED);
- break;
}
}
}
diff --git a/src/com/android/phone/EmergencyCallbackModeExitDialog.java b/src/com/android/phone/EmergencyCallbackModeExitDialog.java
index fc0e513..6901789 100644
--- a/src/com/android/phone/EmergencyCallbackModeExitDialog.java
+++ b/src/com/android/phone/EmergencyCallbackModeExitDialog.java
@@ -43,6 +43,8 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.telephony.domainselection.DomainSelectionResolver;
+import com.android.internal.telephony.emergency.EmergencyStateTracker;
import java.util.HashMap;
import java.util.Map;
@@ -244,9 +246,16 @@
.setMessage(text)
.setPositiveButton(R.string.alert_dialog_yes,
new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog,int whichButton) {
+ public void onClick(DialogInterface dialog,
+ int whichButton) {
// User clicked Yes. Exit Emergency Callback Mode.
- mPhone.exitEmergencyCallbackMode();
+ if (DomainSelectionResolver.getInstance()
+ .isDomainSelectionSupported()) {
+ EmergencyStateTracker.getInstance()
+ .exitEmergencyCallbackMode();
+ } else {
+ mPhone.exitEmergencyCallbackMode();
+ }
// Show progress dialog
showDialog(EXIT_ECM_PROGRESS_DIALOG);
diff --git a/src/com/android/phone/ErrorDialogActivity.java b/src/com/android/phone/ErrorDialogActivity.java
new file mode 100644
index 0000000..11a92a8
--- /dev/null
+++ b/src/com/android/phone/ErrorDialogActivity.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import android.app.Activity;
+import android.app.ActivityOptions;
+import android.app.AlertDialog;
+import android.app.role.RoleManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import java.util.List;
+
+/** Used to display an error dialog from Telephony service. */
+public class ErrorDialogActivity extends Activity {
+
+ private static final String TAG = ErrorDialogActivity.class.getSimpleName();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow()
+ .addSystemFlags(
+ android.view.WindowManager.LayoutParams
+ .SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+ showDialog();
+ }
+
+ @Override
+ public void finish() {
+ super.finish();
+ // Don't show the return to previous task animation to avoid showing a black screen.
+ // Just dismiss the dialog and undim the previous activity immediately.
+ overridePendingTransition(0, 0);
+ }
+
+ private void showDialog() {
+ final DialogInterface.OnClickListener listener =
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ switchToManagedProfile();
+ finish();
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ default:
+ finish();
+ }
+ }
+ };
+
+ new AlertDialog.Builder(this)
+ .setTitle(R.string.send_from_work_profile_title)
+ .setMessage(R.string.send_from_work_profile_description)
+ .setPositiveButton(R.string.send_from_work_profile_action_str, listener)
+ .setNegativeButton(R.string.send_from_work_profile_cancel, listener)
+ .setOnCancelListener(
+ new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ finish();
+ }
+ })
+ .show();
+ }
+
+ private void switchToManagedProfile() {
+ try {
+ int managedProfileUserId =
+ getManagedProfileUserId(
+ getApplicationContext(), getApplicationContext().getUserId());
+ if (managedProfileUserId == UserHandle.USER_NULL) {
+ finish();
+ }
+
+ String defaultMessagesAppPackage =
+ getBaseContext()
+ .getSystemService(RoleManager.class)
+ .getSmsRoleHolder(managedProfileUserId);
+
+ Intent sendIntent = new Intent(Intent.ACTION_MAIN);
+ sendIntent.addCategory(Intent.CATEGORY_DEFAULT);
+ sendIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+ sendIntent.addCategory(Intent.CATEGORY_APP_MESSAGING);
+
+ sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ if (defaultMessagesAppPackage != null) {
+ sendIntent.setPackage(defaultMessagesAppPackage);
+ }
+
+ startActivityAsUser(sendIntent,
+ ActivityOptions.makeOpenCrossProfileAppsAnimation().toBundle(),
+ UserHandle.of(managedProfileUserId));
+ } catch (Exception e) {
+ Log.e(TAG, "Failed to switch to managed profile.", e);
+ }
+ }
+
+ private static int getManagedProfileUserId(Context context, int userId) {
+ UserManager um = context.getSystemService(UserManager.class);
+ List<UserInfo> userProfiles = um.getProfiles(userId);
+ for (UserInfo uInfo : userProfiles) {
+ if (uInfo.id == userId) {
+ continue;
+ }
+ if (uInfo.isManagedProfile()) {
+ return uInfo.id;
+ }
+ }
+ return UserHandle.USER_NULL;
+ }
+}
diff --git a/src/com/android/phone/ImsProvisioningController.java b/src/com/android/phone/ImsProvisioningController.java
index 696f567..a62980e 100644
--- a/src/com/android/phone/ImsProvisioningController.java
+++ b/src/com/android/phone/ImsProvisioningController.java
@@ -41,6 +41,7 @@
import android.annotation.Nullable;
import android.content.Context;
import android.os.AsyncResult;
+import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -55,6 +56,7 @@
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.aidl.IFeatureProvisioningCallback;
import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.ImsConfigImplBase;
@@ -89,6 +91,7 @@
private static final int EVENT_PROVISIONING_CAPABILITY_CHANGED = 2;
@VisibleForTesting
protected static final int EVENT_MULTI_SIM_CONFIGURATION_CHANGE = 3;
+ private static final int EVENT_PROVISIONING_VALUE_CHANGED = 4;
// Provisioning Keys that are handled via AOSP cache and not sent to the ImsService
private static final int[] LOCAL_IMS_CONFIG_KEYS = {
@@ -245,6 +248,11 @@
int activeModemCount = (int) ((AsyncResult) msg.obj).result;
onMultiSimConfigChanged(activeModemCount);
break;
+ case EVENT_PROVISIONING_VALUE_CHANGED:
+ log("subId " + msg.arg1 + " changed provisioning value item : " + msg.arg2
+ + " value : " + (int) msg.obj);
+ updateCapabilityTechFromKey(msg.arg1, msg.arg2, (int) msg.obj);
+ break;
default:
log("unknown message " + msg);
break;
@@ -366,12 +374,15 @@
private boolean mRequiredNotify = false;
private int mSubId;
private int mSlotId;
+ private ConfigCallback mConfigCallback;
MmTelFeatureListener(int slotId) {
log(LOG_PREFIX, slotId, "created");
mSlotId = slotId;
mSubId = getSubId(slotId);
+ mConfigCallback = new ConfigCallback(mSubId);
+
mConnector = mMmTelFeatureConnector.create(
mApp, slotId, TAG, this, new HandlerExecutor(mHandler));
mConnector.connect();
@@ -389,10 +400,22 @@
mSubId = subId;
mSlotId = getSlotId(subId);
+ mConfigCallback.setSubId(subId);
}
public void destroy() {
log("destroy");
+ if (mImsManager != null) {
+ try {
+ ImsConfig imsConfig = getImsConfig(mImsManager);
+ if (imsConfig != null) {
+ imsConfig.removeConfigCallback(mConfigCallback);
+ }
+ } catch (ImsException e) {
+ logw(LOG_PREFIX, mSlotId, "destroy : " + e.getMessage());
+ }
+ }
+ mConfigCallback = null;
mConnector.disconnect();
mConnector = null;
mReady = false;
@@ -409,6 +432,17 @@
mReady = true;
mImsManager = manager;
+ if (mImsManager != null) {
+ try {
+ ImsConfig imsConfig = getImsConfig(mImsManager);
+ if (imsConfig != null) {
+ imsConfig.addConfigCallback(mConfigCallback);
+ }
+ } catch (ImsException e) {
+ logw(LOG_PREFIX, mSlotId, "addConfigCallback : " + e.getMessage());
+ }
+ }
+
onMmTelAvailable();
}
@@ -572,12 +606,15 @@
private boolean mRequiredNotify = false;
private int mSubId;
private int mSlotId;
+ private ConfigCallback mConfigCallback;
RcsFeatureListener(int slotId) {
log(LOG_PREFIX, slotId, "created");
mSlotId = slotId;
mSubId = getSubId(slotId);
+ mConfigCallback = new ConfigCallback(mSubId);
+
mConnector = mRcsFeatureConnector.create(
mApp, slotId, this, new HandlerExecutor(mHandler), TAG);
mConnector.connect();
@@ -595,10 +632,22 @@
mSubId = subId;
mSlotId = getSlotId(subId);
+ mConfigCallback.setSubId(subId);
}
public void destroy() {
log(LOG_PREFIX, mSlotId, "destroy");
+ if (mRcsFeatureManager != null) {
+ try {
+ ImsConfig imsConfig = getImsConfig(mRcsFeatureManager.getConfig());
+ if (imsConfig != null) {
+ imsConfig.removeConfigCallback(mConfigCallback);
+ }
+ } catch (ImsException e) {
+ logw(LOG_PREFIX, mSlotId, "destroy :" + e.getMessage());
+ }
+ }
+ mConfigCallback = null;
mConnector.disconnect();
mConnector = null;
mReady = false;
@@ -611,6 +660,17 @@
mReady = true;
mRcsFeatureManager = manager;
+ if (mRcsFeatureManager != null) {
+ try {
+ ImsConfig imsConfig = getImsConfig(mRcsFeatureManager.getConfig());
+ if (imsConfig != null) {
+ imsConfig.addConfigCallback(mConfigCallback);
+ }
+ } catch (ImsException e) {
+ logw(LOG_PREFIX, mSlotId, "addConfigCallback :" + e.getMessage());
+ }
+ }
+
onRcsAvailable();
}
@@ -726,6 +786,42 @@
}
}
+ // When vendor ImsService changed provisioning data, which should be updated in AOSP.
+ // Catch the event using IImsConfigCallback.
+ private final class ConfigCallback extends IImsConfigCallback.Stub {
+ private int mSubId;
+
+ ConfigCallback(int subId) {
+ mSubId = subId;
+ }
+
+ public void setSubId(int subId) {
+ mSubId = subId;
+ }
+
+ @Override
+ public void onIntConfigChanged(int item, int value) throws RemoteException {
+ if (!Arrays.stream(LOCAL_IMS_CONFIG_KEYS).anyMatch(keyValue -> keyValue == item)) {
+ return;
+ }
+
+ final long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ if (mHandler != null) {
+ mHandler.sendMessage(mHandler.obtainMessage(
+ EVENT_PROVISIONING_VALUE_CHANGED, mSubId, item, (Object) value));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
+ @Override
+ public void onStringConfigChanged(int item, String value) throws RemoteException {
+ // Ignore this callback.
+ }
+ }
+
/**
* Do NOT use this directly, instead use {@link #getInstance()}.
*/
@@ -1468,13 +1564,7 @@
}
protected int getSubId(int slotId) {
- final int[] subIds = mSubscriptionManager.getSubscriptionIds(slotId);
- int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- if (subIds != null && subIds.length >= 1) {
- subId = subIds[0];
- }
-
- return subId;
+ return SubscriptionManager.getSubscriptionId(slotId);
}
protected int getSlotId(int subId) {
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index bf55764..3f35454 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -50,6 +50,7 @@
import com.android.ims.ImsManager;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.telephony.IIntegerConsumer;
+import com.android.internal.telephony.ISipDialogStateCallback;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.telephony.ims.ImsResolver;
@@ -252,7 +253,7 @@
} catch (ImsException e) {
Log.e(TAG, "isCapable: sudId=" + subId
+ ", capability=" + capability + ", " + e.getMessage());
- return false;
+ throw new ServiceSpecificException(e.getCode(), e.getMessage());
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -278,7 +279,7 @@
} catch (ImsException e) {
Log.e(TAG, "isAvailable: sudId=" + subId
+ ", capability=" + capability + ", " + e.getMessage());
- return false;
+ throw new ServiceSpecificException(e.getCode(), e.getMessage());
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -667,6 +668,60 @@
}
/**
+ * Register a state of Sip Dialog callback
+ */
+ @Override
+ public void registerSipDialogStateCallback(int subId, ISipDialogStateCallback cb) {
+ enforceReadPrivilegedPermission("registerSipDialogStateCallback");
+ if (cb == null) {
+ throw new IllegalArgumentException("SipDialogStateCallback is null");
+ }
+ final long identity = Binder.clearCallingIdentity();
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+ }
+ try {
+ SipTransportController transport = getRcsFeatureController(subId).getFeature(
+ SipTransportController.class);
+ if (transport == null) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
+ "This transport does not support the registerSipDialogStateCallback"
+ + " of SIP delegates");
+ }
+ transport.addCallbackForSipDialogState(subId, cb);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Unregister a state of Sip Dialog callback
+ */
+ @Override
+ public void unregisterSipDialogStateCallback(int subId, ISipDialogStateCallback cb) {
+ enforceReadPrivilegedPermission("unregisterSipDialogStateCallback");
+ if (cb == null) {
+ throw new IllegalArgumentException("SipDialogStateCallback is null");
+ }
+ final long identity = Binder.clearCallingIdentity();
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+ }
+ try {
+ SipTransportController transport = getRcsFeatureController(subId).getFeature(
+ SipTransportController.class);
+ if (transport == null) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
+ "This transport does not support the unregisterSipDialogStateCallback"
+ + " of SIP delegates");
+ }
+ transport.removeCallbackForSipDialogState(subId, cb);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
* Registers for updates to the RcsFeature connection through the IImsServiceFeatureCallback
* callback.
*/
@@ -786,16 +841,43 @@
int slotId = phone.getPhoneId();
if (!skipVerifyingConfig) {
verifyImsRcsConfiguredOrThrow(slotId);
+ verifyRcsSubIdActiveOrThrow(slotId, subId);
}
RcsFeatureController c = mRcsService.getFeatureController(slotId);
if (c == null) {
+ // If we hit this case, we have verified that TelephonyRcsService has processed any
+ // subId changes for the associated slot and applied configs. In this case, the configs
+ // do not have the RCS feature enabled.
throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
"The requested operation is not supported for subId " + subId);
}
+ if (!skipVerifyingConfig && c.getAssociatedSubId() != subId) {
+ // If we hit this case, the ImsFeature has not finished setting up the RCS feature yet
+ // or the RCS feature has crashed and is being set up again.
+ Log.w(TAG, "getRcsFeatureController: service unavailable on slot " + slotId
+ + " for subId " + subId);
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
+ "The ImsService is not currently available for subid " + subId
+ + ", please try again");
+ }
return c;
}
/**
+ * Ensure the TelephonyRcsService is tracking the supplied subId for the supplied slotId and has
+ * set up the stack.
+ */
+ private void verifyRcsSubIdActiveOrThrow(int slotId, int subId) {
+ if (mRcsService.verifyActiveSubId(slotId, subId)) return;
+
+ Log.w(TAG, "verifyRcsSubIdActiveOrThrow: verify failed, service not set up yet on "
+ + "slot " + slotId + " for subId " + subId);
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE,
+ "ImsService set up in progress for subId " + subId
+ + ", please try again");
+ }
+
+ /**
* Throw an ImsException if the IMS resolver does not have an ImsService configured for RCS
* for the given slot ID or no ImsResolver instance has been created.
* @param slotId The slot ID that the IMS service is created for.
diff --git a/src/com/android/phone/ImsStateCallbackController.java b/src/com/android/phone/ImsStateCallbackController.java
index 57c1787..edad754 100644
--- a/src/com/android/phone/ImsStateCallbackController.java
+++ b/src/com/android/phone/ImsStateCallbackController.java
@@ -68,6 +68,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
/**
@@ -143,6 +144,10 @@
private final SparseArray<MmTelFeatureListener> mMmTelFeatureListeners = new SparseArray<>();
private final SparseArray<RcsFeatureListener> mRcsFeatureListeners = new SparseArray<>();
+ // Container to store ImsManager instance by subId
+ private final ConcurrentHashMap<Integer, ImsManager> mSubIdToImsManagerCache =
+ new ConcurrentHashMap<>();
+
private final SubscriptionManager mSubscriptionManager;
private final TelephonyRegistryManager mTelephonyRegistryManager;
private MmTelFeatureConnectorFactory mMmTelFeatureFactory;
@@ -282,6 +287,13 @@
if (mSubId == subId) return;
logd(mLogPrefix + "setSubId changed subId=" + subId);
+ // subId changed from valid to invalid
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ if (VDBG) logv(mLogPrefix + "setSubId remove ImsManager " + mSubId);
+ // remove ImsManager reference associated with subId
+ mSubIdToImsManagerCache.remove(mSubId);
+ }
+
mSubId = subId;
}
@@ -298,6 +310,12 @@
mSubId = subId;
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return;
+ // store ImsManager reference associated with subId
+ if (manager != null) {
+ if (VDBG) logv(mLogPrefix + "connectionReady add ImsManager " + subId);
+ mSubIdToImsManagerCache.put(subId, manager);
+ }
+
mState = STATE_READY;
mReason = AVAILABLE;
mHasConfig = true;
@@ -311,6 +329,10 @@
reason = convertReasonType(reason);
if (mReason == reason) return;
+ // remove ImsManager reference associated with subId
+ if (VDBG) logv(mLogPrefix + "connectionUnavailable remove ImsManager " + mSubId);
+ mSubIdToImsManagerCache.remove(mSubId);
+
connectionUnavailableInternal(reason);
}
@@ -319,7 +341,7 @@
mReason = reason;
/* If having no IMS package for MMTEL,
- * dicard the reason except REASON_NO_IMS_SERVICE_CONFIGURED. */
+ * discard the reason except REASON_NO_IMS_SERVICE_CONFIGURED. */
if (!mHasConfig && reason != REASON_NO_IMS_SERVICE_CONFIGURED) return;
onFeatureStateChange(mSubId, FEATURE_MMTEL, mState, mReason);
@@ -973,6 +995,19 @@
mHandler.sendMessage(mHandler.obtainMessage(EVENT_UNREGISTER_CALLBACK, cb));
}
+ /**
+ * Get ImsManager reference associated with subId
+ *
+ * @param subId subscribe ID
+ * @return instance of ImsManager associated with subId, but if ImsService is not
+ * available return null
+ */
+ public ImsManager getImsManager(int subId) {
+ if (VDBG) logv("getImsManager subId = " + subId);
+
+ return mSubIdToImsManagerCache.get(subId);
+ }
+
private void removeInactiveCallbacks(
ArrayList<IBinder> inactiveCallbacks, String message) {
if (inactiveCallbacks == null || inactiveCallbacks.size() == 0) return;
diff --git a/src/com/android/phone/NotificationMgr.java b/src/com/android/phone/NotificationMgr.java
index 226664d..d2c0e6b 100644
--- a/src/com/android/phone/NotificationMgr.java
+++ b/src/com/android/phone/NotificationMgr.java
@@ -59,6 +59,7 @@
import android.util.SparseArray;
import android.widget.Toast;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.RILConstants;
@@ -166,7 +167,8 @@
* Private constructor (this is a singleton).
* @see #init(PhoneGlobals)
*/
- private NotificationMgr(PhoneGlobals app) {
+ @VisibleForTesting
+ /* package */ NotificationMgr(PhoneGlobals app) {
mApp = app;
mContext = app;
mStatusBarManager =
@@ -904,15 +906,16 @@
// can be overridden to hide the network selection to the end user. In this case, the
// notification is not shown to avoid confusion to the end user.
if (!shouldDisplayNetworkSelectOptions(subId)) {
- logi("Skipping network selection unavailable notification due to carrier policy.");
+ logi("Carrier configs refuse to show network selection not available notification");
return;
}
- // In unstable network condition, the phone may go in and out of service. Add logic here to
- // debounce the network selection notification. The notification only shows after phone is
- // out of service, AND fulfills one of the two conditions below:
- // - Out of service lasts {@link #NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIME_IN_MS}
- // - Or has checked {@link #NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIMES} times
+ // In case network selection notification shows up repeatedly under
+ // unstable network condition. The logic is to check whether or not
+ // the service state keeps in no service condition for at least
+ // {@link #NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIME_IN_MS}.
+ // And checking {@link #NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIMES} times.
+ // To avoid the notification showing up for the momentary state.
if (serviceState == ServiceState.STATE_OUT_OF_SERVICE) {
if (mPreviousServiceState.get(subId, STATE_UNKNOWN_SERVICE)
!= ServiceState.STATE_OUT_OF_SERVICE) {
@@ -939,36 +942,10 @@
}
}
- private void startPendingNetworkSelectionNotification(int subId) {
- if (!mHandler.hasMessages(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId)) {
- if (DBG) {
- log("startPendingNetworkSelectionNotification: subId = " + subId);
- }
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId),
- NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIME_IN_MS);
- mPendingEventCounter.put(subId, mPendingEventCounter.get(subId, 0) + 1);
- }
- }
-
- private void clearUpNetworkSelectionNotificationParam(int subId) {
- if (mHandler.hasMessages(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId)) {
- mHandler.removeMessages(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId);
- }
- mPreviousServiceState.remove(subId);
- mOOSTimestamp.remove(subId);
- mPendingEventCounter.remove(subId);
- mSelectedNetworkOperatorName.remove(subId);
- }
-
- private static long getTimeStamp() {
- return SystemClock.elapsedRealtime();
- }
-
// TODO(b/243010310): merge methods below with Settings#MobileNetworkUtils and optimize them.
// The methods below are copied from com.android.settings.network.telephony.MobileNetworkUtils
- // to make sure the network selection unavailable notification should not show when network
- // selection menu is not visible to the end user in Settings app.
+ // to make sure the network selection unavailable notification should not show when Network
+ // Selection menu is not present in Settings app.
private boolean shouldDisplayNetworkSelectOptions(int subId) {
final TelephonyManager telephonyManager = mTelephonyManager.createForSubscriptionId(subId);
final CarrierConfigManager carrierConfigManager = mContext.getSystemService(
@@ -1071,4 +1048,31 @@
return false;
}
// END of TODO:(b/243010310): merge methods above with Settings#MobileNetworkUtils and optimize.
+
+ private void startPendingNetworkSelectionNotification(int subId) {
+ if (!mHandler.hasMessages(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId)) {
+ if (DBG) {
+ log("startPendingNetworkSelectionNotification: subId = " + subId);
+ }
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId),
+ NETWORK_SELECTION_NOTIFICATION_MAX_PENDING_TIME_IN_MS);
+ mPendingEventCounter.put(subId, mPendingEventCounter.get(subId, 0) + 1);
+ }
+ }
+
+ private void clearUpNetworkSelectionNotificationParam(int subId) {
+ if (mHandler.hasMessages(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId)) {
+ mHandler.removeMessages(EVENT_PENDING_NETWORK_SELECTION_NOTIFICATION, subId);
+ }
+ mPreviousServiceState.remove(subId);
+ mOOSTimestamp.remove(subId);
+ mPendingEventCounter.remove(subId);
+ mSelectedNetworkOperatorName.remove(subId);
+ }
+
+ @VisibleForTesting
+ public long getTimeStamp() {
+ return SystemClock.elapsedRealtime();
+ }
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index abbd816..7a61dd1 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -17,6 +17,7 @@
package com.android.phone;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.app.Activity;
import android.app.KeyguardManager;
import android.app.ProgressDialog;
@@ -49,6 +50,7 @@
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyLocalConnection;
import android.telephony.TelephonyManager;
+import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Log;
import android.widget.Toast;
@@ -67,14 +69,18 @@
import com.android.internal.telephony.TelephonyComponentFactory;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.data.DataEvaluation.DataDisallowedReason;
+import com.android.internal.telephony.domainselection.DomainSelectionResolver;
+import com.android.internal.telephony.emergency.EmergencyStateTracker;
import com.android.internal.telephony.ims.ImsResolver;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.telephony.uicc.UiccPort;
import com.android.internal.telephony.uicc.UiccProfile;
import com.android.internal.util.IndentingPrintWriter;
import com.android.phone.settings.SettingsConstants;
import com.android.phone.vvm.CarrierVvmPackageInstalledReceiver;
+import com.android.services.telephony.domainselection.TelephonyDomainSelectionService;
import com.android.services.telephony.rcs.TelephonyRcsService;
import java.io.FileDescriptor;
@@ -157,6 +163,7 @@
public ImsStateCallbackController mImsStateCallbackController;
public ImsProvisioningController mImsProvisioningController;
CarrierConfigLoader configLoader;
+ TelephonyDomainSelectionService mDomainSelectionService;
private Phone phoneInEcm;
@@ -188,6 +195,9 @@
@RoamingNotification
private int mPrevRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
+ /** Operator numerics for which we've shown is-roaming notifications. **/
+ private ArraySet<String> mPrevRoamingOperatorNumerics = new ArraySet<>();
+
private WakeState mWakeState = WakeState.SLEEP;
private PowerManager mPowerManager;
@@ -375,7 +385,7 @@
.unregisterTelephonyCallback(callback);
callback = new PhoneAppCallback(subId);
tm.createForSubscriptionId(subId).registerTelephonyCallback(
- TelephonyManager.INCLUDE_LOCATION_DATA_NONE, mHandler::post,
+ TelephonyManager.INCLUDE_LOCATION_DATA_COARSE, mHandler::post,
callback);
mTelephonyCallbacks[phone.getPhoneId()] = callback;
}
@@ -437,9 +447,27 @@
// Inject telephony component factory if configured using other jars.
XmlResourceParser parser = getResources().getXml(R.xml.telephony_injection);
TelephonyComponentFactory.getInstance().injectTheComponentFactory(parser);
+
+ // Create DomainSelectionResolver always, but it MUST be initialized only when
+ // the device supports AOSP domain selection architecture and
+ // has new IRadio that supports its related HAL APIs.
+ DomainSelectionResolver.make(this,
+ getResources().getBoolean(R.bool.config_enable_aosp_domain_selection));
+
// Initialize the telephony framework
PhoneFactory.makeDefaultPhones(this);
+ // Initialize the DomainSelectionResolver after creating the Phone instance
+ // to check the Radio HAL version.
+ if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
+ mDomainSelectionService = new TelephonyDomainSelectionService(this);
+ DomainSelectionResolver.getInstance().initialize(mDomainSelectionService);
+ // Initialize EmergencyStateTracker if domain selection is supported
+ boolean isSuplDdsSwitchRequiredForEmergencyCall = getResources()
+ .getBoolean(R.bool.config_gnss_supl_requires_default_data_for_emergency);
+ EmergencyStateTracker.make(this, isSuplDdsSwitchRequiredForEmergencyCall);
+ }
+
// Only bring up ImsResolver if the device supports having an IMS stack.
if (getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_IMS)) {
@@ -483,6 +511,10 @@
// status bar icons and control other status bar behavior.
notificationMgr = NotificationMgr.init(this);
+ // Create the SatelliteController singleton, which acts as a backend service for
+ // {@link android.telephony.satellite.SatelliteManager}.
+ SatelliteController.make(this);
+
// Create an instance of CdmaPhoneCallState and initialize it to IDLE
cdmaPhoneCallState = new CdmaPhoneCallState();
cdmaPhoneCallState.CdmaPhoneCallStateInit();
@@ -500,6 +532,8 @@
imsRcsController = ImsRcsController.init(this);
+ configLoader = CarrierConfigLoader.init(this);
+
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
mImsStateCallbackController =
ImsStateCallbackController.make(this, PhoneFactory.getPhones().length);
@@ -511,8 +545,6 @@
ImsProvisioningController.make(this, PhoneFactory.getPhones().length);
}
- configLoader = CarrierConfigLoader.init(this);
-
// Create the CallNotifier singleton, which handles
// asynchronous events from the telephony layer (like
// launching the incoming-call UI when an incoming call comes
@@ -736,6 +768,13 @@
Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT, 0);
TelephonyProperties.airplane_mode_on(true); // true means int value 1
PhoneUtils.setRadioPower(false);
+ clearCacheOnRadioOff();
+ }
+
+ /** Clear fields on power off radio **/
+ private void clearCacheOnRadioOff() {
+ // Re-show is-roaming notifications after APM mode
+ mPrevRoamingOperatorNumerics.clear();
}
private void setRadioPowerOn() {
@@ -859,26 +898,27 @@
+ mDefaultDataSubId + ", ss roaming=" + serviceState.getDataRoaming());
}
if (subId == mDefaultDataSubId) {
- updateDataRoamingStatus();
+ updateDataRoamingStatus(serviceState.getOperatorNumeric());
}
}
/**
- * @return whether or not we should show a notification when connecting to data roaming if the
- * user has data roaming enabled
- */
- private boolean shouldShowDataConnectedRoaming(int subId) {
- PersistableBundle config = getCarrierConfigForSubId(subId);
- return config.getBoolean(CarrierConfigManager
- .KEY_SHOW_DATA_CONNECTED_ROAMING_NOTIFICATION_BOOL);
- }
-
- /**
* When roaming, if mobile data cannot be established due to data roaming not enabled, we need
* to notify the user so they can enable it through settings. Vise versa if the condition
* changes, we need to dismiss the notification.
*/
private void updateDataRoamingStatus() {
+ updateDataRoamingStatus(null /*roamingOperatorNumeric*/);
+ }
+
+ /**
+ * When roaming, if mobile data cannot be established due to data roaming not enabled, we need
+ * to notify the user so they can enable it through settings. Vise versa if the condition
+ * changes, we need to dismiss the notification.
+ * @param roamingOperatorNumeric The operator numeric for the current roaming. {@code null} if
+ * the current roaming operator numeric didn't change.
+ */
+ private void updateDataRoamingStatus(@Nullable String roamingOperatorNumeric) {
if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
Phone phone = getPhone(mDefaultDataSubId);
if (phone == null) {
@@ -893,10 +933,21 @@
dataAllowed = reasons.isEmpty();
notAllowedDueToRoamingOff = (reasons.size() == 1
&& reasons.contains(DataDisallowedReason.ROAMING_DISABLED));
- mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
- if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
+ mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons
+ + ", roamingOperatorNumeric=" + roamingOperatorNumeric);
+ if (VDBG) {
+ Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons
+ + ", roamingOperatorNumeric=" + roamingOperatorNumeric);
+ }
if (!dataAllowed && notAllowedDueToRoamingOff) {
+ // Don't show roaming notification if we've already shown for this MccMnc
+ if (roamingOperatorNumeric != null
+ && !mPrevRoamingOperatorNumerics.add(roamingOperatorNumeric)) {
+ Log.d(LOG_TAG, "Skip roaming disconnected notification since already shown in "
+ + "MccMnc " + roamingOperatorNumeric);
+ return;
+ }
// No need to show it again if we never cancelled it explicitly.
if (mPrevRoamingNotification == ROAMING_NOTIFICATION_DISCONNECTED) return;
// If the only reason of no data is data roaming disabled, then we notify the user
@@ -907,8 +958,18 @@
Message msg = mHandler.obtainMessage(EVENT_DATA_ROAMING_DISCONNECTED);
msg.arg1 = mDefaultDataSubId;
msg.sendToTarget();
- } else if (dataAllowed && dataIsNowRoaming(mDefaultDataSubId)
- && shouldShowDataConnectedRoaming(mDefaultDataSubId)) {
+ } else if (dataAllowed && dataIsNowRoaming(mDefaultDataSubId)) {
+ boolean isShowRoamingNotificationEnabled = getCarrierConfigForSubId(mDefaultDataSubId)
+ .getBoolean(CarrierConfigManager
+ .KEY_SHOW_DATA_CONNECTED_ROAMING_NOTIFICATION_BOOL);
+ if (!isShowRoamingNotificationEnabled) return;
+ // Don't show roaming notification if we've already shown for this MccMnc
+ if (roamingOperatorNumeric != null
+ && !mPrevRoamingOperatorNumerics.add(roamingOperatorNumeric)) {
+ Log.d(LOG_TAG, "Skip roaming connected notification since already shown in "
+ + "MccMnc " + roamingOperatorNumeric);
+ return;
+ }
// No need to show it again if we never cancelled it explicitly, or carrier config
// indicates this is not needed.
if (mPrevRoamingNotification == ROAMING_NOTIFICATION_CONNECTED) return;
@@ -1052,7 +1113,21 @@
} catch (Exception e) {
e.printStackTrace();
}
+ pw.println("DomainSelectionResolver:");
+ pw.increaseIndent();
+ try {
+ if (DomainSelectionResolver.getInstance() != null) {
+ DomainSelectionResolver.getInstance().dump(fd, pw, args);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
pw.decreaseIndent();
+ if (mDomainSelectionService != null) {
+ mDomainSelectionService.dump(fd, pw, args);
+ }
+ pw.decreaseIndent();
+ pw.println("mPrevRoamingOperatorNumerics:" + mPrevRoamingOperatorNumerics);
pw.println("------- End PhoneGlobals -------");
}
}
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 0dd316f..b541c17 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -17,6 +17,8 @@
package com.android.phone;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
+import static android.telephony.TelephonyManager.HAL_SERVICE_RADIO;
import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
@@ -29,6 +31,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.PropertyInvalidatedCache;
@@ -50,6 +53,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
+import android.os.ICancellationSignal;
import android.os.LocaleList;
import android.os.Looper;
import android.os.Message;
@@ -69,6 +73,7 @@
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Telephony;
+import android.service.carrier.CarrierIdentifier;
import android.sysprop.TelephonyProperties;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
@@ -78,9 +83,11 @@
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.DataActivityType;
import android.telephony.Annotation.ThermalMitigationResult;
+import android.telephony.AnomalyReporter;
import android.telephony.CallForwardingInfo;
import android.telephony.CarrierConfigManager;
import android.telephony.CarrierRestrictionRules;
+import android.telephony.CellBroadcastIdRange;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityCdma;
import android.telephony.CellIdentityGsm;
@@ -109,6 +116,7 @@
import android.telephony.TelephonyFrameworkInitializer;
import android.telephony.TelephonyHistogram;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyManager.SimState;
import android.telephony.TelephonyScanManager;
import android.telephony.ThermalMitigationRequest;
import android.telephony.UiccCardInfo;
@@ -136,6 +144,15 @@
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsConfigImplBase;
import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.satellite.ISatelliteDatagramCallback;
+import android.telephony.satellite.ISatellitePositionUpdateCallback;
+import android.telephony.satellite.ISatelliteProvisionStateCallback;
+import android.telephony.satellite.ISatelliteStateCallback;
+import android.telephony.satellite.SatelliteCapabilities;
+import android.telephony.satellite.SatelliteDatagram;
+import android.telephony.satellite.SatelliteDatagramCallback;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteProvisionStateCallback;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.EventLog;
@@ -162,9 +179,11 @@
import com.android.internal.telephony.ICallForwardingInfoCallback;
import com.android.internal.telephony.IImsStateCallback;
import com.android.internal.telephony.IIntegerConsumer;
+import com.android.internal.telephony.ILongConsumer;
import com.android.internal.telephony.INumberVerificationCallback;
import com.android.internal.telephony.ITelephony;
import com.android.internal.telephony.IccCard;
+import com.android.internal.telephony.IccCardConstants;
import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.LocaleTracker;
import com.android.internal.telephony.NetworkScanRequestTracker;
@@ -179,12 +198,14 @@
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.RadioInterfaceCapabilityController;
import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.SmsApplication;
import com.android.internal.telephony.SmsController;
import com.android.internal.telephony.SmsPermissions;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.telephony.data.DataUtils;
+import com.android.internal.telephony.domainselection.DomainSelectionResolver;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.euicc.EuiccConnector;
import com.android.internal.telephony.ims.ImsResolver;
@@ -192,6 +213,9 @@
import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
import com.android.internal.telephony.metrics.RcsStats;
import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.internal.telephony.satellite.SatelliteController;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
import com.android.internal.telephony.uicc.IccIoResult;
import com.android.internal.telephony.uicc.IccUtils;
@@ -203,6 +227,7 @@
import com.android.internal.telephony.uicc.UiccProfile;
import com.android.internal.telephony.uicc.UiccSlot;
import com.android.internal.telephony.util.LocaleUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.telephony.util.VoicemailNotificationSettingsUtil;
import com.android.internal.util.FunctionalUtils;
import com.android.internal.util.HexDump;
@@ -210,6 +235,8 @@
import com.android.phone.callcomposer.CallComposerPictureTransfer;
import com.android.phone.callcomposer.ImageData;
import com.android.phone.settings.PickSmsSubscriptionActivity;
+import com.android.phone.slice.SlicePurchaseController;
+import com.android.phone.utils.CarrierAllowListInfo;
import com.android.phone.vvm.PhoneAccountHandleConverter;
import com.android.phone.vvm.RemoteVvmTaskManager;
import com.android.phone.vvm.VisualVoicemailSettingsUtil;
@@ -235,6 +262,7 @@
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
+import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
@@ -358,6 +386,8 @@
private static final int EVENT_ENABLE_VONR_DONE = 114;
private static final int CMD_IS_VONR_ENABLED = 115;
private static final int EVENT_IS_VONR_ENABLED_DONE = 116;
+ private static final int CMD_PURCHASE_PREMIUM_CAPABILITY = 117;
+ private static final int EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE = 118;
// Parameters of select command.
private static final int SELECT_COMMAND = 0xA4;
@@ -365,28 +395,31 @@
private static final int SELECT_P2 = 0;
private static final int SELECT_P3 = 0x10;
+ // Toggling null cipher and integrity support was added in IRadioNetwork 2.1
+ private static final int MIN_NULL_CIPHER_AND_INTEGRITY_VERSION = 201;
+
/** The singleton instance. */
private static PhoneInterfaceManager sInstance;
private static List<String> sThermalMitigationAllowlistedPackages = new ArrayList<>();
- private PhoneGlobals mApp;
- private CallManager mCM;
- private ImsResolver mImsResolver;
- private UserManager mUserManager;
- private AppOpsManager mAppOps;
- private PackageManager mPm;
- private MainThreadHandler mMainThreadHandler;
- private SubscriptionController mSubscriptionController;
- private SharedPreferences mTelephonySharedPreferences;
- private PhoneConfigurationManager mPhoneConfigurationManager;
+ private final PhoneGlobals mApp;
+ private final CallManager mCM;
+ private final ImsResolver mImsResolver;
+
+ private final SatelliteController mSatelliteController;
+ private final UserManager mUserManager;
+ private final AppOpsManager mAppOps;
+ private final MainThreadHandler mMainThreadHandler;
+ private final SubscriptionController mSubscriptionController;
+ private final SharedPreferences mTelephonySharedPreferences;
+ private final PhoneConfigurationManager mPhoneConfigurationManager;
private final RadioInterfaceCapabilityController mRadioInterfaceCapabilities;
- private final Telephony2gUpdater mTelephony2gUpdater;
/** User Activity */
- private AtomicBoolean mNotifyUserActivity;
+ private final AtomicBoolean mNotifyUserActivity;
private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
- private Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
+ private final Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
private static final String PREF_CARRIERS_NUMBER_PREFIX = "carrier_number_";
@@ -407,6 +440,9 @@
private static final int SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS = -1;
private static final int MODEM_DOES_NOT_SUPPORT_DATA_THROTTLING_ERROR_CODE = -2;
+ private static final String PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID =
+ "24bf97a6-e8a6-44d8-a6a4-255d7548733c";
+
/**
* Experiment flag to enable erase modem config on reset network, default value is false
*/
@@ -415,6 +451,8 @@
private static final int SET_NETWORK_SELECTION_MODE_AUTOMATIC_TIMEOUT_MS = 2000; // 2 seconds
+ private static final int MODEM_ACTIVITY_TIME_OFFSET_CORRECTION_MS = 50;
+
/**
* With support for MEP(multiple enabled profile) in Android T, a SIM card can have more than
* one ICCID active at the same time.
@@ -466,6 +504,17 @@
}
}
+ private static final class PurchasePremiumCapabilityArgument {
+ public @TelephonyManager.PremiumCapability int capability;
+ public @NonNull IIntegerConsumer callback;
+
+ PurchasePremiumCapabilityArgument(@TelephonyManager.PremiumCapability int capability,
+ @NonNull IIntegerConsumer callback) {
+ this.capability = capability;
+ this.callback = callback;
+ }
+ }
+
/**
* A request object for use with {@link MainThreadHandler}. Requesters should wait() on the
* request after sending. The main thread will notify the request when it is complete.
@@ -791,7 +840,7 @@
if (uiccPort == null) {
loge("iccCloseLogicalChannel: No UICC");
request.result = new IllegalArgumentException(
- "iccCloseLogicalChannel: No UICC");
+ "iccCloseLogicalChannel: No UICC");
notifyRequester(request);
} else {
onCompleted = obtainMessage(EVENT_CLOSE_CHANNEL_DONE, request);
@@ -1359,7 +1408,7 @@
int errorCode = CellNetworkScanResult.STATUS_UNKNOWN_ERROR;
if (ar.exception instanceof CommandException) {
CommandException.Error error =
- ((CommandException) (ar.exception)).getCommandError();
+ ((CommandException) (ar.exception)).getCommandError();
if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
errorCode = CellNetworkScanResult.STATUS_RADIO_NOT_AVAILABLE;
} else if (error == CommandException.Error.GENERIC_FAILURE) {
@@ -1433,6 +1482,8 @@
ModemActivityInfo info = (ModemActivityInfo) ar.result;
if (isModemActivityInfoValid(info)) {
mergeModemActivityInfo(info);
+ } else {
+ loge("queryModemActivityInfo: invalid response");
}
// This is needed to decouple ret from mLastModemActivityInfo
// We don't want to return mLastModemActivityInfo which is updated
@@ -1471,13 +1522,14 @@
break;
}
- case CMD_SET_ALLOWED_CARRIERS:
+ case CMD_SET_ALLOWED_CARRIERS: {
request = (MainThreadRequest) msg.obj;
CarrierRestrictionRules argument =
(CarrierRestrictionRules) request.argument;
onCompleted = obtainMessage(EVENT_SET_ALLOWED_CARRIERS_DONE, request);
defaultPhone.setAllowedCarriers(argument, onCompleted, request.workSource);
break;
+ }
case EVENT_SET_ALLOWED_CARRIERS_DONE:
ar = (AsyncResult) msg.obj;
@@ -1514,7 +1566,7 @@
request.result = ar.result;
} else {
request.result = new IllegalStateException(
- "Failed to get carrier restrictions");
+ "Failed to get carrier restrictions");
if (ar.result == null) {
loge("getAllowedCarriers: Empty response");
} else if (ar.exception instanceof CommandException) {
@@ -1524,7 +1576,39 @@
loge("getAllowedCarriers: Unknown exception");
}
}
- notifyRequester(request);
+ if (request.argument != null) {
+ // This is for the implementation of carrierRestrictionStatus.
+ CallerCallbackInfo callbackInfo = (CallerCallbackInfo) request.argument;
+ Consumer<Integer> callback = callbackInfo.getConsumer();
+ int callerCarrierId = callbackInfo.getCarrierId();
+ int lockStatus = TelephonyManager.CARRIER_RESTRICTION_STATUS_UNKNOWN;
+ if (ar.exception == null && ar.result instanceof CarrierRestrictionRules) {
+ CarrierRestrictionRules carrierRestrictionRules =
+ (CarrierRestrictionRules) ar.result;
+ int carrierId = -1;
+ try {
+ CarrierIdentifier carrierIdentifier =
+ carrierRestrictionRules.getAllowedCarriers().get(0);
+ carrierId = CarrierResolver.getCarrierIdFromIdentifier(mApp,
+ carrierIdentifier);
+ } catch (NullPointerException | IndexOutOfBoundsException ex) {
+ Rlog.e(LOG_TAG, "CarrierIdentifier exception = " + ex);
+ }
+ lockStatus = carrierRestrictionRules.getCarrierRestrictionStatus();
+ if (carrierId != -1 && callerCarrierId == carrierId && lockStatus
+ == TelephonyManager.CARRIER_RESTRICTION_STATUS_RESTRICTED) {
+ lockStatus = TelephonyManager
+ .CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER;
+ }
+ } else {
+ Rlog.e(LOG_TAG,
+ "getCarrierRestrictionStatus: exception ex = " + ar.exception);
+ }
+ callback.accept(lockStatus);
+ } else {
+ // This is for the implementation of getAllowedCarriers.
+ notifyRequester(request);
+ }
break;
case EVENT_GET_FORBIDDEN_PLMNS_DONE:
@@ -1568,7 +1652,7 @@
}
onCompleted = obtainMessage(EVENT_GET_FORBIDDEN_PLMNS_DONE, request);
((SIMRecords) uiccApp.getIccRecords()).getForbiddenPlmns(
- onCompleted);
+ onCompleted);
break;
case CMD_SWITCH_SLOTS:
@@ -1733,7 +1817,7 @@
case EVENT_CMD_MODEM_REBOOT_DONE:
handleNullReturnEvent(msg, "rebootModem");
break;
- case CMD_REQUEST_ENABLE_MODEM:
+ case CMD_REQUEST_ENABLE_MODEM: {
request = (MainThreadRequest) msg.obj;
boolean enable = (boolean) request.argument;
onCompleted = obtainMessage(EVENT_ENABLE_MODEM_DONE, request);
@@ -1741,6 +1825,7 @@
PhoneConfigurationManager.getInstance()
.enablePhone(request.phone, enable, onCompleted);
break;
+ }
case EVENT_ENABLE_MODEM_DONE: {
ar = (AsyncResult) msg.obj;
request = (MainThreadRequest) ar.userObj;
@@ -1982,7 +2067,7 @@
if (error == CommandException.Error.RADIO_NOT_AVAILABLE) {
request.result = TelephonyManager
- .THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ .THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
} else if (error == CommandException.Error.INVALID_ARGUMENTS) {
request.result = SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS;
} else if (error == CommandException.Error.REQUEST_NOT_SUPPORTED) {
@@ -2061,8 +2146,8 @@
onCompleted = obtainMessage(EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE,
request);
phone.getSignalStrengthController().setSignalStrengthUpdateRequest(
- request.subId, pair.first /*callingUid*/,
- pair.second /*request*/, onCompleted);
+ request.subId, pair.first /*callingUid*/,
+ pair.second /*request*/, onCompleted);
break;
}
case EVENT_SET_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE: {
@@ -2089,8 +2174,8 @@
onCompleted = obtainMessage(EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE,
request);
phone.getSignalStrengthController().clearSignalStrengthUpdateRequest(
- request.subId, pair.first /*callingUid*/,
- pair.second /*request*/, onCompleted);
+ request.subId, pair.first /*callingUid*/,
+ pair.second /*request*/, onCompleted);
break;
}
case EVENT_CLEAR_SIGNAL_STRENGTH_UPDATE_REQUEST_DONE: {
@@ -2137,11 +2222,44 @@
break;
}
+ case CMD_PURCHASE_PREMIUM_CAPABILITY: {
+ request = (MainThreadRequest) msg.obj;
+ onCompleted = obtainMessage(EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE, request);
+ PurchasePremiumCapabilityArgument arg =
+ (PurchasePremiumCapabilityArgument) request.argument;
+ SlicePurchaseController.getInstance(request.phone).purchasePremiumCapability(
+ arg.capability, onCompleted);
+ break;
+ }
+
+ case EVENT_PURCHASE_PREMIUM_CAPABILITY_DONE: {
+ ar = (AsyncResult) msg.obj;
+ request = (MainThreadRequest) ar.userObj;
+ PurchasePremiumCapabilityArgument arg =
+ (PurchasePremiumCapabilityArgument) request.argument;
+ try {
+ int result = (int) ar.result;
+ arg.callback.accept(result);
+ log("purchasePremiumCapability: capability="
+ + TelephonyManager.convertPremiumCapabilityToString(arg.capability)
+ + ", result= "
+ + TelephonyManager.convertPurchaseResultToString(result));
+ } catch (RemoteException e) {
+ String logStr = "Purchase premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(arg.capability)
+ + " failed: " + e;
+ if (DBG) log(logStr);
+ AnomalyReporter.reportAnomaly(
+ UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
+ }
+ break;
+ }
+
case CMD_PREPARE_UNATTENDED_REBOOT:
request = (MainThreadRequest) msg.obj;
request.result =
UiccController.getInstance().getPinStorage()
- .prepareUnattendedReboot(request.workSource);
+ .prepareUnattendedReboot(request.workSource);
notifyRequester(request);
break;
@@ -2339,24 +2457,35 @@
mApp = app;
mCM = PhoneGlobals.getInstance().mCM;
mImsResolver = ImsResolver.getInstance();
+ mSatelliteController = SatelliteController.getInstance();
mUserManager = (UserManager) app.getSystemService(Context.USER_SERVICE);
mAppOps = (AppOpsManager)app.getSystemService(Context.APP_OPS_SERVICE);
- mPm = app.getSystemService(PackageManager.class);
mMainThreadHandler = new MainThreadHandler();
- mSubscriptionController = SubscriptionController.getInstance();
- mTelephonySharedPreferences =
- PreferenceManager.getDefaultSharedPreferences(mApp);
+ if (!PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ mSubscriptionController = SubscriptionController.getInstance();
+ } else {
+ mSubscriptionController = null;
+ }
+ mTelephonySharedPreferences = PreferenceManager.getDefaultSharedPreferences(mApp);
mNetworkScanRequestTracker = new NetworkScanRequestTracker();
mPhoneConfigurationManager = PhoneConfigurationManager.getInstance();
mRadioInterfaceCapabilities = RadioInterfaceCapabilityController.getInstance();
mNotifyUserActivity = new AtomicBoolean(false);
PropertyInvalidatedCache.invalidateCache(TelephonyManager.CACHE_KEY_PHONE_ACCOUNT_TO_SUBID);
- mTelephony2gUpdater = new Telephony2gUpdater(mApp);
- mTelephony2gUpdater.init();
publish();
+ CarrierAllowListInfo.loadInstance(mApp);
}
- private Phone getDefaultPhone() {
+ @VisibleForTesting
+ public SharedPreferences getSharedPreferences() {
+ return mTelephonySharedPreferences;
+ }
+
+ /**
+ * Get the default phone for this device.
+ */
+ @VisibleForTesting
+ public Phone getDefaultPhone() {
Phone thePhone = getPhone(getDefaultSubscription());
return (thePhone != null) ? thePhone : PhoneFactory.getDefaultPhone();
}
@@ -2383,6 +2512,20 @@
? getDefaultPhone() : getPhone(subId);
}
+ /**
+ * Get phone object associated with a subscription.
+ * Return default phone if phone object associated with subscription is null
+ * @param subId - subscriptionId
+ * @return phone object associated with a subscription or default phone if null.
+ */
+ private Phone getPhoneFromSubIdOrDefault(int subId) {
+ Phone phone = getPhoneFromSubId(subId);
+ if (phone == null) {
+ phone = getDefaultPhone();
+ }
+ return phone;
+ }
+
@Nullable
private UiccPort getUiccPortFromRequest(@NonNull MainThreadRequest request) {
Phone phone = getPhoneFromRequest(request);
@@ -2392,7 +2535,7 @@
// returns phone associated with the subId.
private Phone getPhone(int subId) {
- return PhoneFactory.getPhone(mSubscriptionController.getPhoneId(subId));
+ return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
}
private void sendEraseModemConfig(@NonNull Phone phone) {
@@ -2567,14 +2710,16 @@
synchronized (UnlockSim.this) {
mRetryCount = msg.arg1;
if (ar.exception != null) {
- if (ar.exception instanceof CommandException &&
- ((CommandException)(ar.exception)).getCommandError()
- == CommandException.Error.PASSWORD_INCORRECT) {
+ CommandException.Error error = null;
+ if (ar.exception instanceof CommandException) {
+ error = ((CommandException) (ar.exception))
+ .getCommandError();
+ }
+ if (error == CommandException.Error.PASSWORD_INCORRECT) {
mResult = PhoneConstants.PIN_PASSWORD_INCORRECT;
- } //When UiccCardApp dispose,handle message and return exception
- else if (ar.exception instanceof CommandException &&
- ((CommandException) (ar.exception)).getCommandError()
- == CommandException.Error.ABORTED) {
+ } else if (error == CommandException.Error.ABORTED) {
+ /* When UiccCardApp dispose, handle message and return
+ exception */
mResult = PhoneConstants.PIN_OPERATION_ABORTED;
} else {
mResult = PhoneConstants.PIN_GENERAL_FAILURE;
@@ -2825,6 +2970,10 @@
public boolean setRadioPower(boolean turnOn) {
enforceModifyPermission();
+ if (!turnOn) {
+ log("setRadioPower off: callingPackage=" + getCurrentPackageName());
+ }
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone defaultPhone = PhoneFactory.getDefaultPhone();
@@ -2843,6 +2992,10 @@
public boolean setRadioPowerForSubscriber(int subId, boolean turnOn) {
enforceModifyPermission();
+ if (!turnOn) {
+ log("setRadioPowerForSubscriber off: subId=" + subId
+ + ",callingPackage=" + getCurrentPackageName());
+ }
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -2857,6 +3010,97 @@
}
}
+ /**
+ * Vote on powering off the radio for a reason. The radio will be turned on only when there is
+ * no reason to power it off. When any of the voters want to power it off, it will be turned
+ * off. In case of emergency, the radio will be turned on even if there are some reasons for
+ * powering it off, and these radio off votes will be cleared.
+ * Multiple apps can vote for the same reason and the last vote will take effect. Each app is
+ * responsible for its vote. A powering-off vote of a reason will be maintained until it is
+ * cleared by calling {@link clearRadioPowerOffForReason} for that reason, or an emergency call
+ * is made, or the device is rebooted. When an app comes backup from a crash, it needs to make
+ * sure if its vote is as expected. An app can use the API {@link getRadioPowerOffReasons} to
+ * check its vote.
+ *
+ * @param subId The subscription ID.
+ * @param reason The reason for powering off radio.
+ * @return true on success and false on failure.
+ */
+ public boolean requestRadioPowerOffForReason(int subId,
+ @TelephonyManager.RadioPowerReason int reason) {
+ enforceModifyPermission();
+
+ log("requestRadioPowerOffForReason: subId=" + subId
+ + ",reason=" + reason + ",callingPackage=" + getCurrentPackageName());
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final Phone phone = getPhone(subId);
+ if (phone != null) {
+ phone.setRadioPowerForReason(false, reason);
+ return true;
+ } else {
+ return false;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Remove the vote on powering off the radio for a reason, as requested by
+ * {@link requestRadioPowerOffForReason}.
+ *
+ * @param subId The subscription ID.
+ * @param reason The reason for powering off radio.
+ * @return true on success and false on failure.
+ */
+ public boolean clearRadioPowerOffForReason(int subId,
+ @TelephonyManager.RadioPowerReason int reason) {
+ enforceModifyPermission();
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final Phone phone = getPhone(subId);
+ if (phone != null) {
+ phone.setRadioPowerForReason(true, reason);
+ return true;
+ } else {
+ return false;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Get reasons for powering off radio, as requested by {@link requestRadioPowerOffForReason}.
+ *
+ * @param subId The subscription ID.
+ * @param callingPackage The package making the call.
+ * @param callingFeatureId The feature in the package.
+ * @return List of reasons for powering off radio.
+ */
+ public List getRadioPowerOffReasons(int subId, String callingPackage, String callingFeatureId) {
+ enforceReadPrivilegedPermission("getRadioPowerOffReasons");
+
+ final long identity = Binder.clearCallingIdentity();
+ List result = new ArrayList();
+ try {
+ if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mApp, subId,
+ callingPackage, callingFeatureId, "getRadioPowerOffReasons")) {
+ return result;
+ }
+
+ final Phone phone = getPhone(subId);
+ if (phone != null) {
+ result.addAll(phone.getRadioPowerOffReasons());
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return result;
+ }
+
// FIXME: subId version needed
@Override
public boolean enableDataConnectivity(String callingPackage) {
@@ -2864,7 +3108,7 @@
final long identity = Binder.clearCallingIdentity();
try {
- int subId = mSubscriptionController.getDefaultDataSubId();
+ int subId = SubscriptionManager.getDefaultDataSubscriptionId();
final Phone phone = getPhone(subId);
if (phone != null) {
phone.getDataSettingsManager().setDataEnabled(
@@ -2885,7 +3129,7 @@
final long identity = Binder.clearCallingIdentity();
try {
- int subId = mSubscriptionController.getDefaultDataSubId();
+ int subId = SubscriptionManager.getDefaultDataSubscriptionId();
final Phone phone = getPhone(subId);
if (phone != null) {
phone.getDataSettingsManager().setDataEnabled(
@@ -2996,7 +3240,7 @@
@Override
public int getDataState() {
- return getDataStateForSubId(mSubscriptionController.getDefaultDataSubId());
+ return getDataStateForSubId(SubscriptionManager.getDefaultDataSubscriptionId());
}
@Override
@@ -3017,7 +3261,7 @@
@Override
public @DataActivityType int getDataActivity() {
- return getDataActivityForSubId(mSubscriptionController.getDefaultDataSubId());
+ return getDataActivityForSubId(SubscriptionManager.getDefaultDataSubscriptionId());
}
@Override
@@ -3063,7 +3307,7 @@
final long identity = Binder.clearCallingIdentity();
try {
if (DBG_LOC) log("getCellLocation: is active user");
- int subId = mSubscriptionController.getDefaultDataSubId();
+ int subId = SubscriptionManager.getDefaultDataSubscriptionId();
return (CellIdentity) sendRequest(CMD_GET_CELL_LOCATION, workSource, subId);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -3080,7 +3324,7 @@
// Get default phone in this case.
phoneId = SubscriptionManager.DEFAULT_PHONE_INDEX;
}
- final int subId = mSubscriptionController.getSubId(phoneId);
+ final int subId = SubscriptionManager.getSubscriptionId(phoneId);
Phone phone = PhoneFactory.getPhone(phoneId);
if (phone == null) return "";
ServiceStateTracker sst = phone.getServiceStateTracker();
@@ -3271,13 +3515,18 @@
}
@Override
- public void setCellInfoListRate(int rateInMillis) {
+ public void setCellInfoListRate(int rateInMillis, int subId) {
enforceModifyPermission();
WorkSource workSource = getWorkSource(Binder.getCallingUid());
final long identity = Binder.clearCallingIdentity();
try {
- getDefaultPhone().setCellInfoListRate(rateInMillis, workSource);
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ getDefaultPhone().setCellInfoListRate(rateInMillis, workSource);
+ } else {
+ phone.setCellInfoListRate(rateInMillis, workSource);
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -3305,6 +3554,26 @@
}
@Override
+ public String getPrimaryImei(String callingPackage, String callingFeatureId) {
+ enforceCallingPackage(callingPackage, Binder.getCallingUid(), "getPrimaryImei");
+ if (!checkCallingOrSelfReadDeviceIdentifiersForAnySub(mApp, callingPackage,
+ callingFeatureId, "getPrimaryImei")) {
+ throw new SecurityException("Caller does not have permission");
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone.getImeiType() == Phone.IMEI_TYPE_PRIMARY) {
+ return phone.getImei();
+ }
+ }
+ throw new UnsupportedOperationException("Operation not supported");
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
public String getTypeAllocationCodeForSlot(int slotIndex) {
Phone phone = PhoneFactory.getPhone(slotIndex);
String tac = null;
@@ -3478,10 +3747,31 @@
*
* @throws SecurityException if the caller does not have the required permission
*/
- private void enforceModifyPermission() {
+ @VisibleForTesting
+ public void enforceModifyPermission() {
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE, null);
}
+ /**
+ * Make sure the caller has the READ_PHONE_STATE permission.
+ *
+ * @throws SecurityException if the caller does not have the required permission
+ */
+ @VisibleForTesting
+ public void enforceReadPermission() {
+ enforceReadPermission(null);
+ }
+
+ /**
+ * Make sure the caller has the READ_PHONE_STATE permissions.
+ *
+ * @throws SecurityException if the caller does not have the READ_PHONE_STATE permission.
+ */
+ @VisibleForTesting
+ public void enforceReadPermission(String msg) {
+ mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE, msg);
+ }
+
private void enforceActiveEmergencySessionPermission() {
mApp.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
@@ -3504,6 +3794,15 @@
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
}
+ /**
+ * Make sure the caller has SATELLITE_COMMUNICATION permission.
+ * @param message - log message to print.
+ * @throws SecurityException if the caller does not have the required permission
+ */
+ private void enforceSatelliteCommunicationPermission(String message) {
+ mApp.enforceCallingOrSelfPermission(permission.SATELLITE_COMMUNICATION, message);
+ }
+
private String createTelUrl(String number) {
if (TextUtils.isEmpty(number)) {
return null;
@@ -3513,15 +3812,15 @@
}
private static void log(String msg) {
- Log.d(LOG_TAG, "[PhoneIntfMgr] " + msg);
+ Log.d(LOG_TAG, msg);
}
private static void logv(String msg) {
- Log.v(LOG_TAG, "[PhoneIntfMgr] " + msg);
+ Log.v(LOG_TAG, msg);
}
private static void loge(String msg) {
- Log.e(LOG_TAG, "[PhoneIntfMgr] " + msg);
+ Log.e(LOG_TAG, msg);
}
@Override
@@ -3950,8 +4249,8 @@
}
/**
- * returns true, if the device is in a state where both voice and data
- * are supported simultaneously. This can change based on location or network condition.
+ * returns true, if the device is in a state where both voice and data
+ * are supported simultaneously. This can change based on location or network condition.
*/
@Override
public boolean isConcurrentVoiceAndDataAllowed(int subId) {
@@ -3991,8 +4290,8 @@
@Override
public int getNetworkSelectionMode(int subId) {
TelephonyPermissions
- .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
- mApp, subId, "getNetworkSelectionMode");
+ .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "getNetworkSelectionMode");
final long identity = Binder.clearCallingIdentity();
try {
if (!isActiveSubscription(subId)) {
@@ -4039,7 +4338,18 @@
try {
int slotId = getSlotIndexOrException(subId);
verifyImsMmTelConfiguredOrThrow(slotId);
- ImsManager.getInstance(mApp, slotId).addRegistrationCallbackForSubscription(c, subId);
+
+ ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+ if (controller != null) {
+ ImsManager imsManager = controller.getImsManager(subId);
+ if (imsManager != null) {
+ imsManager.addRegistrationCallbackForSubscription(c, subId);
+ } else {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ } else {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
+ }
} catch (ImsException e) {
throw new ServiceSpecificException(e.getCode());
} finally {
@@ -4060,14 +4370,20 @@
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
final long token = Binder.clearCallingIdentity();
+
try {
- ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
- .removeRegistrationCallbackForSubscription(c, subId);
- } catch (ImsException e) {
- Log.i(LOG_TAG, "unregisterImsRegistrationCallback: " + subId
- + "is inactive, ignoring unregister.");
- // If the subscription is no longer active, just return, since the callback
- // will already have been removed internally.
+ ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+ if (controller != null) {
+ ImsManager imsManager = controller.getImsManager(subId);
+ if (imsManager != null) {
+ imsManager.removeRegistrationCallbackForSubscription(c, subId);
+ } else {
+ Log.i(LOG_TAG, "unregisterImsRegistrationCallback: " + subId
+ + "is inactive, ignoring unregister.");
+ // If the ImsManager is not valid, just return, since the callback
+ // will already have been removed internally.
+ }
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -4160,7 +4476,18 @@
try {
int slotId = getSlotIndexOrException(subId);
verifyImsMmTelConfiguredOrThrow(slotId);
- ImsManager.getInstance(mApp, slotId).addCapabilitiesCallbackForSubscription(c, subId);
+
+ ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+ if (controller != null) {
+ ImsManager imsManager = controller.getImsManager(subId);
+ if (imsManager != null) {
+ imsManager.addCapabilitiesCallbackForSubscription(c, subId);
+ } else {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ } else {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
+ }
} catch (ImsException e) {
throw new ServiceSpecificException(e.getCode());
} finally {
@@ -4183,13 +4510,18 @@
final long token = Binder.clearCallingIdentity();
try {
- ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
- .removeCapabilitiesCallbackForSubscription(c, subId);
- } catch (ImsException e) {
- Log.i(LOG_TAG, "unregisterMmTelCapabilityCallback: " + subId
- + "is inactive, ignoring unregister.");
- // If the subscription is no longer active, just return, since the callback
- // will already have been removed internally.
+ ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+ if (controller != null) {
+ ImsManager imsManager = controller.getImsManager(subId);
+ if (imsManager != null) {
+ imsManager.removeCapabilitiesCallbackForSubscription(c, subId);
+ } else {
+ Log.i(LOG_TAG, "unregisterMmTelCapabilityCallback: " + subId
+ + " is inactive, ignoring unregister.");
+ // If the ImsManager is not valid, just return, since the callback
+ // will already have been removed internally.
+ }
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -4600,8 +4932,18 @@
}
int slotId = getSlotIndexOrException(subId);
verifyImsMmTelConfiguredOrThrow(slotId);
- ImsManager.getInstance(mApp, slotId)
- .addProvisioningCallbackForSubscription(callback, subId);
+
+ ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+ if (controller != null) {
+ ImsManager imsManager = controller.getImsManager(subId);
+ if (imsManager != null) {
+ imsManager.addProvisioningCallbackForSubscription(callback, subId);
+ } else {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ } else {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION);
+ }
} catch (ImsException e) {
throw new ServiceSpecificException(e.getCode());
} finally {
@@ -4618,13 +4960,18 @@
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
try {
- ImsManager.getInstance(mApp, getSlotIndexOrException(subId))
- .removeProvisioningCallbackForSubscription(callback, subId);
- } catch (ImsException e) {
- Log.i(LOG_TAG, "unregisterImsProvisioningChangedCallback: " + subId
- + "is inactive, ignoring unregister.");
- // If the subscription is no longer active, just return, since the callback will already
- // have been removed internally.
+ ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+ if (controller != null) {
+ ImsManager imsManager = controller.getImsManager(subId);
+ if (imsManager != null) {
+ imsManager.removeProvisioningCallbackForSubscription(callback, subId);
+ } else {
+ Log.i(LOG_TAG, "unregisterImsProvisioningChangedCallback: " + subId
+ + " is inactive, ignoring unregister.");
+ // If the ImsManager is not valid, just return, since the callback will already
+ // have been removed internally.
+ }
+ }
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -4982,7 +5329,7 @@
return getDataNetworkTypeForSubscriber(subId, callingPackage, callingFeatureId);
} else if (targetSdk == android.os.Build.VERSION_CODES.Q
&& !TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow(
- mApp, subId, callingPackage, callingFeatureId,
+ mApp, subId, callingPackage, callingFeatureId,
"getNetworkTypeForSubscriber")) {
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
@@ -5005,7 +5352,7 @@
*/
@Override
public int getDataNetworkType(String callingPackage, String callingFeatureId) {
- return getDataNetworkTypeForSubscriber(mSubscriptionController.getDefaultDataSubId(),
+ return getDataNetworkTypeForSubscriber(SubscriptionManager.getDefaultDataSubscriptionId(),
callingPackage, callingFeatureId);
}
@@ -5070,7 +5417,7 @@
*/
public boolean hasIccCard() {
// FIXME Make changes to pass defaultSimId of type int
- return hasIccCardUsingSlotIndex(mSubscriptionController.getSlotIndex(
+ return hasIccCardUsingSlotIndex(SubscriptionManager.getSlotIndex(
getDefaultSubscription()));
}
@@ -5135,18 +5482,22 @@
* Returns Default subId, 0 in the case of single standby.
*/
private int getDefaultSubscription() {
- return mSubscriptionController.getDefaultSubId();
+ return SubscriptionManager.getDefaultSubscriptionId();
}
private int getSlotForDefaultSubscription() {
- return mSubscriptionController.getPhoneId(getDefaultSubscription());
+ return SubscriptionManager.getPhoneId(getDefaultSubscription());
}
private int getPreferredVoiceSubscription() {
- return mSubscriptionController.getDefaultVoiceSubId();
+ return SubscriptionManager.getDefaultVoiceSubscriptionId();
}
private boolean isActiveSubscription(int subId) {
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ return getSubscriptionManagerService().isActiveSubId(subId,
+ mApp.getOpPackageName(), mApp.getFeatureId());
+ }
return mSubscriptionController.isActiveSubId(subId);
}
@@ -5188,7 +5539,7 @@
portIndex);
if (phoneId == -1) {
throw new IllegalArgumentException("Given slot index: " + slotIndex + " port index: "
- + portIndex + " does not correspond to an active phone");
+ + portIndex + " does not correspond to an active phone");
}
return PhoneFactory.getPhone(phoneId);
}
@@ -5307,12 +5658,12 @@
@Override
public String iccTransmitApduLogicalChannelByPort(int slotIndex, int portIndex, int channel,
- int cla, int command, int p1, int p2, int p3, String data) {
+ int cla, int command, int p1, int p2, int p3, String data) {
enforceModifyPermission();
if (DBG) {
log("iccTransmitApduLogicalChannelByPort: slotIndex=" + slotIndex + " portIndex="
- + portIndex + " chnl=" + channel + " cla=" + cla + " cmd=" + command + " p1="
- + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
+ + portIndex + " chnl=" + channel + " cla=" + cla + " cmd=" + command + " p1="
+ + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
}
return iccTransmitApduLogicalChannelWithPermission(
getPhoneFromSlotPortIndexOrThrowException(slotIndex, portIndex), channel, cla,
@@ -5360,13 +5711,13 @@
@Override
public String iccTransmitApduBasicChannelByPort(int slotIndex, int portIndex,
- String callingPackage, int cla, int command, int p1, int p2, int p3, String data) {
+ String callingPackage, int cla, int command, int p1, int p2, int p3, String data) {
enforceModifyPermission();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
if (DBG) {
log("iccTransmitApduBasicChannelByPort: slotIndex=" + slotIndex + " portIndex="
- + portIndex + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2="
- + p2 + " p3=" + p3 + " data=" + data);
+ + portIndex + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2="
+ + p2 + " p3=" + p3 + " data=" + data);
}
return iccTransmitApduBasicChannelWithPermission(
@@ -5682,8 +6033,7 @@
// may happen if the does not support IMS.
return;
}
- mImsResolver.disableIms(slotIndex);
- mImsResolver.enableIms(slotIndex);
+ mImsResolver.resetIms(slotIndex);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -5986,11 +6336,11 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setNetworkSelectionModeManual");
+ final long identity = Binder.clearCallingIdentity();
if (!isActiveSubscription(subId)) {
return false;
}
- final long identity = Binder.clearCallingIdentity();
try {
ManualNetworkSelectionArgument arg = new ManualNetworkSelectionArgument(operatorInfo,
persistSelection);
@@ -6003,7 +6353,7 @@
Binder.restoreCallingIdentity(identity);
}
}
- /**
+ /**
* Get the manual network selection
*
* @param subId the id of the subscription.
@@ -6013,8 +6363,8 @@
@Override
public String getManualNetworkSelectionPlmn(int subId) {
TelephonyPermissions
- .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
- mApp, subId, "getManualNetworkSelectionPlmn");
+ .enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "getManualNetworkSelectionPlmn");
final long identity = Binder.clearCallingIdentity();
try {
@@ -6028,7 +6378,7 @@
}
OperatorInfo networkSelection = phone.getSavedNetworkSelection();
return TextUtils.isEmpty(networkSelection.getOperatorNumeric())
- ? phone.getManualNetworkSelectionPlmn() : networkSelection.getOperatorNumeric();
+ ? phone.getManualNetworkSelectionPlmn() : networkSelection.getOperatorNumeric();
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -6186,7 +6536,7 @@
String newUssdCommand = "";
try {
newUssdCommand = carrierXmlParser.getFeature(
- CarrierXmlParser.FEATURE_CALL_WAITING)
+ CarrierXmlParser.FEATURE_CALL_WAITING)
.makeCommand(CarrierXmlParser.SsEntry.SSAction.QUERY, null);
} catch (NullPointerException e) {
loge("Failed to generate USSD number" + e);
@@ -6243,7 +6593,7 @@
String newUssdCommand = "";
try {
newUssdCommand = carrierXmlParser.getFeature(
- CarrierXmlParser.FEATURE_CALL_WAITING)
+ CarrierXmlParser.FEATURE_CALL_WAITING)
.makeCommand(ssAction, null);
} catch (NullPointerException e) {
loge("Failed to generate USSD number" + e);
@@ -6287,16 +6637,16 @@
LocationAccessPolicy.LocationPermissionResult.DENIED_HARD;
if (!renounceFineLocationAccess) {
locationResult = LocationAccessPolicy.checkLocationPermission(mApp,
- new LocationAccessPolicy.LocationPermissionQuery.Builder()
- .setCallingPackage(callingPackage)
- .setCallingFeatureId(callingFeatureId)
- .setCallingPid(Binder.getCallingPid())
- .setCallingUid(Binder.getCallingUid())
- .setMethod("requestNetworkScan")
- .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
- .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
- .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
- .build());
+ new LocationAccessPolicy.LocationPermissionQuery.Builder()
+ .setCallingPackage(callingPackage)
+ .setCallingFeatureId(callingFeatureId)
+ .setCallingPid(Binder.getCallingPid())
+ .setCallingUid(Binder.getCallingUid())
+ .setMethod("requestNetworkScan")
+ .setMinSdkVersionForFine(Build.VERSION_CODES.Q)
+ .setMinSdkVersionForCoarse(Build.VERSION_CODES.Q)
+ .setMinSdkVersionForEnforcement(Build.VERSION_CODES.Q)
+ .build());
}
if (locationResult != LocationAccessPolicy.LocationPermissionResult.ALLOWED) {
SecurityException e = checkNetworkRequestForSanitizedLocationAccess(
@@ -6334,7 +6684,7 @@
}
boolean hasNetworkScanPermission =
mApp.checkCallingOrSelfPermission(android.Manifest.permission.NETWORK_SCAN)
- == PERMISSION_GRANTED;
+ == PERMISSION_GRANTED;
if (!hasCarrierPriv && !hasNetworkScanPermission) {
return new SecurityException("permission.NETWORK_SCAN or carrier privileges is needed"
@@ -6410,7 +6760,7 @@
mApp, subId, "getAllowedNetworkTypesForReason");
final long identity = Binder.clearCallingIdentity();
try {
- return getPhoneFromSubId(subId).getAllowedNetworkTypes(reason);
+ return getPhoneFromSubIdOrDefault(subId).getAllowedNetworkTypes(reason);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -6496,12 +6846,10 @@
// any network types which were set for security reasons.
if (mApp.checkCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE)
!= PERMISSION_GRANTED
- && (reason == TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G
- || reason == TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS)) {
+ && reason == TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G) {
throw new SecurityException(
"setAllowedNetworkTypesForReason cannot be called with carrier privileges for"
- + " reason "
- + reason);
+ + " reason " + reason);
}
if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
loge("setAllowedNetworkTypesForReason: Invalid allowed network type reason: " + reason);
@@ -6512,11 +6860,15 @@
return false;
}
- log("setAllowedNetworkTypesForReason: " + reason + " value: "
+ log("setAllowedNetworkTypesForReason: subId=" + subId + ", reason=" + reason + " value: "
+ TelephonyManager.convertNetworkTypeBitmaskToString(allowedNetworkTypes));
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ return false;
+ }
- if (allowedNetworkTypes == getPhoneFromSubId(subId).getAllowedNetworkTypes(reason)) {
+ if (allowedNetworkTypes == phone.getAllowedNetworkTypes(reason)) {
log("setAllowedNetworkTypesForReason: " + reason + "does not change value");
return true;
}
@@ -6590,10 +6942,10 @@
try {
mApp.enforceCallingOrSelfPermission(permission.READ_BASIC_PHONE_STATE,
functionName);
- } catch (Exception e) {
+ } catch (SecurityException e) {
mApp.enforceCallingOrSelfPermission(permission.ACCESS_NETWORK_STATE, functionName);
}
- } catch (Exception e) {
+ } catch (SecurityException e) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, functionName);
@@ -6601,7 +6953,7 @@
final long identity = Binder.clearCallingIdentity();
try {
- int phoneId = mSubscriptionController.getPhoneId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
if (DBG) log("isUserDataEnabled: subId=" + subId + " phoneId=" + phoneId);
Phone phone = PhoneFactory.getPhone(phoneId);
if (phone != null) {
@@ -6632,27 +6984,26 @@
mApp.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE,
functionName);
- } catch (Exception e) {
+ } catch (SecurityException e) {
try {
mApp.enforceCallingOrSelfPermission(
android.Manifest.permission.READ_PHONE_STATE,
functionName);
- } catch (Exception e2) {
+ } catch (SecurityException e2) {
mApp.enforceCallingOrSelfPermission(
permission.READ_BASIC_PHONE_STATE, functionName);
}
}
- } catch (Exception e) {
+ } catch (SecurityException e) {
enforceReadPrivilegedPermission(functionName);
}
final long identity = Binder.clearCallingIdentity();
try {
- int phoneId = mSubscriptionController.getPhoneId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
Phone phone = PhoneFactory.getPhone(phoneId);
if (phone != null) {
- boolean retVal;
- retVal = phone.getDataSettingsManager().isDataEnabled();
+ boolean retVal = phone.getDataSettingsManager().isDataEnabled();
if (DBG) log("isDataEnabled: " + retVal + ", subId=" + subId);
return retVal;
} else {
@@ -6679,15 +7030,15 @@
mApp.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE,
functionName);
- } catch (Exception e) {
+ } catch (SecurityException e) {
mApp.enforceCallingOrSelfPermission(permission.READ_BASIC_PHONE_STATE,
functionName);
}
- } catch (Exception e) {
+ } catch (SecurityException e) {
try {
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PHONE_STATE,
functionName);
- } catch (Exception e2) {
+ } catch (SecurityException e2) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, functionName);
}
@@ -6696,7 +7047,7 @@
final long identity = Binder.clearCallingIdentity();
try {
- int phoneId = mSubscriptionController.getPhoneId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
if (DBG) {
log("isDataEnabledForReason: subId=" + subId + " phoneId=" + phoneId
+ " reason=" + reason);
@@ -7108,9 +7459,16 @@
return null;
}
- final SubscriptionInfo info = SubscriptionController.getInstance()
- .getSubscriptionInfo(subId);
- final ParcelUuid groupUuid = info.getGroupUuid();
+ ParcelUuid groupUuid;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ final SubscriptionInfo info = getSubscriptionManagerService()
+ .getSubscriptionInfo(subId);
+ groupUuid = info.getGroupUuid();
+ } else {
+ final SubscriptionInfo info = mSubscriptionController
+ .getSubscriptionInfo(subId);
+ groupUuid = info.getGroupUuid();
+ }
// If it doesn't belong to any group, return just subscriberId of itself.
if (groupUuid == null) {
return new String[]{subscriberId};
@@ -7118,9 +7476,16 @@
// Get all subscriberIds from the group.
final List<String> mergedSubscriberIds = new ArrayList<>();
- final List<SubscriptionInfo> groupInfos = SubscriptionController.getInstance()
- .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
- mApp.getAttributionTag());
+ List<SubscriptionInfo> groupInfos;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ groupInfos = getSubscriptionManagerService()
+ .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
+ mApp.getAttributionTag());
+ } else {
+ groupInfos = mSubscriptionController
+ .getSubscriptionsInGroup(groupUuid, mApp.getOpPackageName(),
+ mApp.getAttributionTag());
+ }
for (SubscriptionInfo subInfo : groupInfos) {
subscriberId = telephonyManager.getSubscriberId(subInfo.getSubscriptionId());
if (subscriberId != null) {
@@ -7531,9 +7896,10 @@
public @Nullable PhoneAccountHandle getPhoneAccountHandleForSubscriptionId(int subscriptionId) {
TelephonyPermissions
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
- mApp,
- subscriptionId,
- "getPhoneAccountHandleForSubscriptionId, " + "subscriptionId: " + subscriptionId);
+ mApp,
+ subscriptionId,
+ "getPhoneAccountHandleForSubscriptionId, " + "subscriptionId: "
+ + subscriptionId);
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subscriptionId);
@@ -7680,11 +8046,23 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- final SubscriptionInfo info = mSubscriptionController.getActiveSubscriptionInfo(subId,
- phone.getContext().getOpPackageName(), phone.getContext().getAttributionTag());
- if (info == null) {
- log("getSimLocaleForSubscriber, inactive subId: " + subId);
- return null;
+ SubscriptionInfo info;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ info = getSubscriptionManagerService().getActiveSubscriptionInfo(subId,
+ phone.getContext().getOpPackageName(),
+ phone.getContext().getAttributionTag());
+ if (info == null) {
+ log("getSimLocaleForSubscriber, inactive subId: " + subId);
+ return null;
+ }
+ } else {
+ info = mSubscriptionController.getActiveSubscriptionInfo(subId,
+ phone.getContext().getOpPackageName(),
+ phone.getContext().getAttributionTag());
+ if (info == null) {
+ log("getSimLocaleForSubscriber, inactive subId: " + subId);
+ return null;
+ }
}
// Try and fetch the locale from the carrier properties or from the SIM language
// preferences (EF-PL and EF-LI)...
@@ -7695,7 +8073,7 @@
if (!localeFromDefaultSim.getCountry().isEmpty()) {
if (DBG) log("Using locale from subId: " + subId + " locale: "
+ localeFromDefaultSim);
- return matchLocaleFromSupportedLocaleList(localeFromDefaultSim);
+ return matchLocaleFromSupportedLocaleList(phone, localeFromDefaultSim);
} else {
simLanguage = localeFromDefaultSim.getLanguage();
}
@@ -7708,7 +8086,7 @@
final Locale mccLocale = LocaleUtils.getLocaleFromMcc(mApp, mcc, simLanguage);
if (mccLocale != null) {
if (DBG) log("No locale from SIM, using mcc locale:" + mccLocale);
- return matchLocaleFromSupportedLocaleList(mccLocale);
+ return matchLocaleFromSupportedLocaleList(phone, mccLocale);
}
if (DBG) log("No locale found - returning null");
@@ -7719,13 +8097,12 @@
}
@VisibleForTesting
- String matchLocaleFromSupportedLocaleList(@NonNull Locale inputLocale) {
+ String matchLocaleFromSupportedLocaleList(Phone phone, @NonNull Locale inputLocale) {
String[] supportedLocale = com.android.internal.app.LocalePicker.getSupportedLocales(
- getDefaultPhone().getContext());
+ phone.getContext());
for (String localeTag : supportedLocale) {
- if (LocaleList.matchesLanguageAndScript(
- inputLocale, Locale.forLanguageTag(localeTag))
- && inputLocale.getCountry().equals(
+ if (LocaleList.matchesLanguageAndScript(inputLocale, Locale.forLanguageTag(localeTag))
+ && TextUtils.equals(inputLocale.getCountry(),
Locale.forLanguageTag(localeTag).getCountry())) {
return localeTag;
}
@@ -7733,15 +8110,14 @@
return inputLocale.toLanguageTag();
}
- private List<SubscriptionInfo> getAllSubscriptionInfoList() {
- return mSubscriptionController.getAllSubInfoList(mApp.getOpPackageName(),
- mApp.getAttributionTag());
- }
-
/**
* NOTE: this method assumes permission checks are done and caller identity has been cleared.
*/
private List<SubscriptionInfo> getActiveSubscriptionInfoListPrivileged() {
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ return getSubscriptionManagerService().getActiveSubscriptionInfoList(
+ mApp.getOpPackageName(), mApp.getAttributionTag());
+ }
return mSubscriptionController.getActiveSubscriptionInfoList(mApp.getOpPackageName(),
mApp.getAttributionTag());
}
@@ -7770,7 +8146,7 @@
}
}
- // Checks that ModemActivityInfo is valid. Sleep time, Idle time, Rx time and Tx time should be
+ // Checks that ModemActivityInfo is valid. Sleep time and Idle time should be
// less than total activity duration.
private boolean isModemActivityInfoValid(ModemActivityInfo info) {
if (info == null) {
@@ -7778,13 +8154,13 @@
}
int activityDurationMs =
(int) (info.getTimestampMillis() - mLastModemActivityInfo.getTimestampMillis());
+ activityDurationMs += MODEM_ACTIVITY_TIME_OFFSET_CORRECTION_MS;
+
int totalTxTimeMs = Arrays.stream(info.getTransmitTimeMillis()).sum();
return (info.isValid()
- && (info.getSleepTimeMillis() <= activityDurationMs)
- && (info.getIdleTimeMillis() <= activityDurationMs)
- && (info.getReceiveTimeMillis() <= activityDurationMs)
- && (totalTxTimeMs <= activityDurationMs));
+ && (info.getSleepTimeMillis() <= activityDurationMs)
+ && (info.getIdleTimeMillis() <= activityDurationMs));
}
private void updateLastModemActivityInfo(ModemActivityInfo info, int rat, int freq) {
@@ -7818,10 +8194,10 @@
info.getReceiveTimeMillis(rat) + mLastModemActivityInfo.getReceiveTimeMillis(rat));
}
- /**
- * Merge this ModemActivityInfo with mLastModemActivitySpecificInfo
- * @param info recent ModemActivityInfo
- */
+ /**
+ * Merge this ModemActivityInfo with mLastModemActivitySpecificInfo
+ * @param info recent ModemActivityInfo
+ */
private void mergeModemActivityInfo(ModemActivityInfo info) {
List<ActivityStatsTechSpecificInfo> merged = new ArrayList<>();
ActivityStatsTechSpecificInfo deltaSpecificInfo;
@@ -7866,17 +8242,17 @@
mLastModemActivityInfo.setTimestamp(info.getTimestampMillis());
mLastModemActivityInfo.setSleepTimeMillis(
info.getSleepTimeMillis()
- + mLastModemActivityInfo.getSleepTimeMillis());
+ + mLastModemActivityInfo.getSleepTimeMillis());
mLastModemActivityInfo.setIdleTimeMillis(
info.getIdleTimeMillis()
- + mLastModemActivityInfo.getIdleTimeMillis());
+ + mLastModemActivityInfo.getIdleTimeMillis());
mLastModemActivityInfo =
- new ModemActivityInfo(
- mLastModemActivityInfo.getTimestampMillis(),
- mLastModemActivityInfo.getSleepTimeMillis(),
- mLastModemActivityInfo.getIdleTimeMillis(),
- mLastModemActivitySpecificInfo);
+ new ModemActivityInfo(
+ mLastModemActivityInfo.getTimestampMillis(),
+ mLastModemActivityInfo.getSleepTimeMillis(),
+ mLastModemActivityInfo.getIdleTimeMillis(),
+ mLastModemActivitySpecificInfo);
}
private ActivityStatsTechSpecificInfo[] deepCopyModemActivitySpecificInfo(
@@ -7953,10 +8329,21 @@
.contains(callingPackage);
try {
// isActiveSubId requires READ_PHONE_STATE, which we already check for above
- if (!mSubscriptionController.isActiveSubId(subId, callingPackage, callingFeatureId)) {
- Rlog.d(LOG_TAG,
- "getServiceStateForSubscriber returning null for inactive subId=" + subId);
- return null;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ SubscriptionInfoInternal subInfo = getSubscriptionManagerService()
+ .getSubscriptionInfoInternal(subId);
+ if (subInfo == null || !subInfo.isActive()) {
+ Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
+ + "subId=" + subId);
+ return null;
+ }
+ } else {
+ if (!mSubscriptionController.isActiveSubId(subId, callingPackage,
+ callingFeatureId)) {
+ Rlog.d(LOG_TAG, "getServiceStateForSubscriber returning null for inactive "
+ + "subId=" + subId);
+ return null;
+ }
}
ServiceState ss = phone.getServiceState();
@@ -8091,7 +8478,8 @@
*
* @throws SecurityException if the caller does not have the required permission
*/
- private void enforceReadPrivilegedPermission(String message) {
+ @VisibleForTesting
+ public void enforceReadPrivilegedPermission(String message) {
mApp.enforceCallingOrSelfPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
message);
}
@@ -8107,6 +8495,16 @@
}
/**
+ * Make sure either called from same process as self (phone) or IPC caller has interact across
+ * users permission.
+ *
+ * @throws SecurityException if the caller does not have the required permission
+ */
+ private void enforceInteractAcrossUsersPermission(String message) {
+ mApp.enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS, message);
+ }
+
+ /**
* Make sure called from the package in charge of visual voicemail.
*
* @throws SecurityException if the caller is not the visual voicemail package.
@@ -8291,6 +8689,38 @@
}
/**
+ * Fetches the carrier restriction status of the device and sends the status to the caller
+ * through the callback.
+ *
+ * @param callback The callback that will be used to send the result.
+ * @throws SecurityException if the caller does not have the required permission/privileges or
+ * the caller is not allowlisted.
+ */
+ @Override
+ public void getCarrierRestrictionStatus(IIntegerConsumer callback, String packageName) {
+ enforceReadPermission("getCarrierRestrictionStatus");
+ int carrierId = validateCallerAndGetCarrierId(packageName);
+ if (carrierId == CarrierAllowListInfo.INVALID_CARRIER_ID) {
+ Rlog.e(LOG_TAG, "getCarrierRestrictionStatus: caller is not registered");
+ throw new SecurityException("Not an authorized caller");
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Consumer<Integer> consumer = FunctionalUtils.ignoreRemoteException(callback::accept);
+ CallerCallbackInfo callbackInfo = new CallerCallbackInfo(consumer, carrierId);
+ sendRequestAsync(CMD_GET_ALLOWED_CARRIERS, callbackInfo);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @VisibleForTesting
+ public int validateCallerAndGetCarrierId(String packageName) {
+ CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mApp);
+ return allowListInfo.validateCallerAndGetCarrierId(packageName);
+ }
+
+ /**
* 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.
@@ -8444,7 +8874,7 @@
@NonNull String[] args) {
return new TelephonyShellCommand(this, getDefaultPhone().getContext()).exec(
this, in.getFileDescriptor(), out.getFileDescriptor(),
- err.getFileDescriptor(), args);
+ err.getFileDescriptor(), args);
}
/**
@@ -8689,11 +9119,11 @@
mApp.enforceCallingOrSelfPermission(
android.Manifest.permission.ACCESS_NETWORK_STATE,
functionName);
- } catch (Exception e) {
+ } catch (SecurityException e) {
mApp.enforceCallingOrSelfPermission(
permission.READ_BASIC_PHONE_STATE, functionName);
}
- } catch (Exception e) {
+ } catch (SecurityException e) {
TelephonyPermissions.enforceCallingOrSelfReadPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, functionName);
}
@@ -8740,7 +9170,7 @@
public boolean isManualNetworkSelectionAllowed(int subId) {
TelephonyPermissions
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
- mApp, subId, "isManualNetworkSelectionAllowed");
+ mApp, subId, "isManualNetworkSelectionAllowed");
boolean isAllowed = true;
final long identity = Binder.clearCallingIdentity();
@@ -8784,7 +9214,7 @@
// even without READ_PRIVILEGED_PHONE_STATE, we allow the call to continue if the caller
// has carrier privileges on an active UICC
if (checkCarrierPrivilegesForPackageAnyPhoneWithPermission(callingPackage)
- != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+ != TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
throw new SecurityException("Caller does not have permission.");
}
}
@@ -9095,7 +9525,7 @@
*/
private int getDefaultNetworkType(int subId) {
List<Integer> list = TelephonyProperties.default_network();
- int phoneId = mSubscriptionController.getPhoneId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
if (phoneId >= 0 && phoneId < list.size() && list.get(phoneId) != null) {
return list.get(phoneId);
}
@@ -9169,7 +9599,7 @@
public int getCdmaRoamingMode(int subId) {
TelephonyPermissions
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
- mApp, subId, "getCdmaRoamingMode");
+ mApp, subId, "getCdmaRoamingMode");
final long identity = Binder.clearCallingIdentity();
try {
@@ -9255,9 +9685,11 @@
final long identity = Binder.clearCallingIdentity();
try {
for (Phone phone: PhoneFactory.getPhones()) {
+ //Note: we ignore passed in param exactMatch. We can remove it once
+ // TelephonyManager#isPotentialEmergencyNumber is removed completely
if (phone.getEmergencyNumberTracker() != null
&& phone.getEmergencyNumberTracker()
- .isEmergencyNumber(number, exactMatch)) {
+ .isEmergencyNumber(number)) {
return true;
}
}
@@ -9642,12 +10074,22 @@
/**
* Get the IRadio HAL Version
+ * @deprecated use getHalVersion instead
*/
+ @Deprecated
@Override
public int getRadioHalVersion() {
+ return getHalVersion(HAL_SERVICE_RADIO);
+ }
+
+ /**
+ * Get the HAL Version of a specific service
+ */
+ @Override
+ public int getHalVersion(int service) {
Phone phone = getDefaultPhone();
if (phone == null) return -1;
- HalVersion hv = phone.getHalVersion();
+ HalVersion hv = phone.getHalVersion(service);
if (hv.equals(HalVersion.UNKNOWN)) return -1;
return hv.major * 100 + hv.minor;
}
@@ -9797,6 +10239,16 @@
}
@Override
+ public void showSwitchToManagedProfileDialog() {
+ enforceModifyPermission();
+
+ Intent intent = new Intent();
+ intent.setClass(mApp, ErrorDialogActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ mApp.startActivity(intent);
+ }
+
+ @Override
public String getMmsUAProfUrl(int subId) {
//TODO investigate if this API should require proper permission check in R b/133791609
final long identity = Binder.clearCallingIdentity();
@@ -9905,8 +10357,9 @@
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
if (!isImsAvailableOnDevice()) {
- throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
- "IMS not available on device.");
+ // ProvisioningManager can not handle ServiceSpecificException.
+ // Throw the IllegalStateException and annotate ProvisioningManager.
+ throw new IllegalStateException("IMS not available on device.");
}
final long identity = Binder.clearCallingIdentity();
@@ -10110,7 +10563,7 @@
try {
getGbaManager(subId).bootstrapAuthenticationRequest(
new GbaAuthRequest(subId, appType, nafUrl, securityProtocol.toByteArray(),
- forceBootStrapping, callback));
+ forceBootStrapping, callback));
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -10131,7 +10584,7 @@
for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) {
Phone phone = PhoneFactory.getPhone(i);
if (phone != null) {
- phone.setRadioPowerForReason(enable, Phone.RADIO_POWER_REASON_THERMAL);
+ phone.setRadioPowerForReason(enable, TelephonyManager.RADIO_POWER_REASON_THERMAL);
isPhoneAvailable = true;
}
}
@@ -10161,7 +10614,7 @@
if (isDataThrottlingSupported) {
int thermalMitigationResult =
- (int) sendRequest(CMD_SET_DATA_THROTTLING, dataThrottlingRequest, subId);
+ (int) sendRequest(CMD_SET_DATA_THROTTLING, dataThrottlingRequest, subId);
if (thermalMitigationResult == SET_DATA_THROTTLING_MODEM_THREW_INVALID_PARAMS) {
throw new IllegalArgumentException("modem returned INVALID_ARGUMENTS");
} else if (thermalMitigationResult
@@ -10196,8 +10649,8 @@
for (Phone phone : PhoneFactory.getPhones()) {
if (phone.isInEmergencySmsMode() || phone.isInEcm()) {
Log.e(LOG_TAG, "Phone state is not valid. isInEmergencySmsMode = "
- + phone.isInEmergencySmsMode() + " isInEmergencyCallbackMode = "
- + phone.isInEcm());
+ + phone.isInEmergencySmsMode() + " isInEmergencyCallbackMode = "
+ + phone.isInEcm());
return true;
}
}
@@ -10258,9 +10711,9 @@
switch (thermalMitigationAction) {
case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_DATA_THROTTLING:
thermalMitigationResult =
- handleDataThrottlingRequest(subId,
- thermalMitigationRequest.getDataThrottlingRequest(),
- callingPackage);
+ handleDataThrottlingRequest(subId,
+ thermalMitigationRequest.getDataThrottlingRequest(),
+ callingPackage);
break;
case ThermalMitigationRequest.THERMAL_MITIGATION_ACTION_VOICE_ONLY:
if (thermalMitigationRequest.getDataThrottlingRequest() != null) {
@@ -10291,7 +10744,7 @@
Phone phone = getPhone(subId);
if (phone == null) {
thermalMitigationResult =
- TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
+ TelephonyManager.THERMAL_MITIGATION_RESULT_MODEM_NOT_AVAILABLE;
break;
}
@@ -10304,7 +10757,7 @@
break;
} else if (isAnyPhoneInEmergencyState()) {
thermalMitigationResult =
- TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE;
+ TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE;
break;
}
} else {
@@ -10321,7 +10774,7 @@
break;
}
thermalMitigationResult =
- TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
+ TelephonyManager.THERMAL_MITIGATION_RESULT_SUCCESS;
break;
default:
throw new IllegalArgumentException("the requested thermalMitigationAction does "
@@ -10505,8 +10958,9 @@
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
if (!isImsAvailableOnDevice()) {
- throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
- "IMS not available on device.");
+ // operation failed silently
+ Rlog.w(LOG_TAG, "IMS not available on device.");
+ return;
}
final long identity = Binder.clearCallingIdentity();
@@ -10530,8 +10984,9 @@
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
if (!isImsAvailableOnDevice()) {
- throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
- "IMS not available on device.");
+ // ProvisioningManager can not handle ServiceSpecificException.
+ // Throw the IllegalStateException and annotate ProvisioningManager.
+ throw new IllegalStateException("IMS not available on device.");
}
final long identity = Binder.clearCallingIdentity();
@@ -11029,9 +11484,8 @@
}
for (SignalThresholdInfo info : request.getSignalThresholdInfos()) {
- // Only system caller can set mHysteresisMs/mHysteresisDb/mIsEnabled.
+ // Only system caller can set mHysteresisMs/mIsEnabled.
if (info.getHysteresisMs() != SignalThresholdInfo.HYSTERESIS_MS_DISABLED
- || info.getHysteresisDb() != SignalThresholdInfo.HYSTERESIS_DB_DISABLED
|| info.isEnabled()) {
throw new IllegalArgumentException(
"Only system can set hide fields in SignalThresholdInfo");
@@ -11110,6 +11564,129 @@
}
/**
+ * Check whether the given premium capability is available for purchase from the carrier.
+ *
+ * @param capability The premium capability to check.
+ * @param subId The subId to check the premium capability for.
+ *
+ * @return Whether the given premium capability is available to purchase.
+ */
+ @Override
+ public boolean isPremiumCapabilityAvailableForPurchase(int capability, int subId) {
+ if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
+ mApp, "isPremiumCapabilityAvailableForPurchase")) {
+ log("Premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " is not available for purchase due to missing permissions.");
+ throw new SecurityException("isPremiumCapabilityAvailableForPurchase requires "
+ + "permission READ_BASIC_PHONE_STATE.");
+ }
+
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ loge("isPremiumCapabilityAvailableForPurchase: phone is null, subId=" + subId);
+ return false;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return SlicePurchaseController.getInstance(phone)
+ .isPremiumCapabilityAvailableForPurchase(capability);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Purchase the given premium capability from the carrier.
+ *
+ * @param capability The premium capability to purchase.
+ * @param callback The result of the purchase request.
+ * @param subId The subId to purchase the premium capability for.
+ */
+ @Override
+ public void purchasePremiumCapability(int capability, IIntegerConsumer callback, int subId) {
+ log("purchasePremiumCapability: capability="
+ + TelephonyManager.convertPremiumCapabilityToString(capability) + ", caller="
+ + getCurrentPackageName());
+
+ if (!TelephonyPermissions.checkCallingOrSelfReadNonDangerousPhoneStateNoThrow(
+ mApp, "purchasePremiumCapability")) {
+ log("purchasePremiumCapability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " failed due to missing permissions.");
+ throw new SecurityException("purchasePremiumCapability requires permission "
+ + "READ_BASIC_PHONE_STATE.");
+ } else if (!TelephonyPermissions.checkInternetPermissionNoThrow(
+ mApp, "purchasePremiumCapability")) {
+ log("purchasePremiumCapability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " failed due to missing permissions.");
+ throw new SecurityException("purchasePremiumCapability requires permission INTERNET.");
+ }
+
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ try {
+ int result = TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_REQUEST_FAILED;
+ callback.accept(result);
+ loge("purchasePremiumCapability: phone is null, subId=" + subId);
+ } catch (RemoteException e) {
+ String logStr = "Purchase premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " failed due to RemoteException handling null phone: " + e;
+ if (DBG) log(logStr);
+ AnomalyReporter.reportAnomaly(
+ UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
+ }
+ return;
+ }
+
+ String callingProcess;
+ try {
+ callingProcess = mApp.getPackageManager().getApplicationInfo(
+ getCurrentPackageName(), 0).processName;
+ } catch (PackageManager.NameNotFoundException e) {
+ callingProcess = getCurrentPackageName();
+ }
+
+ boolean isVisible = false;
+ ActivityManager am = mApp.getSystemService(ActivityManager.class);
+ if (am != null) {
+ List<ActivityManager.RunningAppProcessInfo> processes = am.getRunningAppProcesses();
+ if (processes != null) {
+ for (ActivityManager.RunningAppProcessInfo process : processes) {
+ log("purchasePremiumCapability: process " + process.processName
+ + "has importance " + process.importance);
+ if (process.processName.equals(callingProcess) && process.importance
+ <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE) {
+ isVisible = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!isVisible) {
+ try {
+ int result = TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND;
+ callback.accept(result);
+ loge("purchasePremiumCapability: " + callingProcess + " is not in the foreground.");
+ } catch (RemoteException e) {
+ String logStr = "Purchase premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " failed due to RemoteException handling background application: " + e;
+ if (DBG) log(logStr);
+ AnomalyReporter.reportAnomaly(
+ UUID.fromString(PURCHASE_PREMIUM_CAPABILITY_ERROR_UUID), logStr);
+ }
+ return;
+ }
+
+ sendRequestAsync(CMD_PURCHASE_PREMIUM_CAPABILITY,
+ new PurchasePremiumCapabilityArgument(capability, callback), phone, null);
+ }
+
+ /**
* Register an IMS connection state callback
*/
@Override
@@ -11238,8 +11815,8 @@
Log.d(LOG_TAG, "setModemService - " + serviceName);
TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setModemService");
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID,
- "setModemService");
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ "setModemService");
return mPhoneConfigurationManager.setModemService(serviceName);
}
@@ -11253,7 +11830,7 @@
Log.d(LOG_TAG, "getModemService");
TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "getModemService");
TelephonyPermissions
- .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
+ .enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID,
"getModemService");
result = mPhoneConfigurationManager.getModemService();
@@ -11272,6 +11849,8 @@
try {
Phone phone = getPhone(subId);
if (phone == null) return;
+ Log.i(LOG_TAG, "setVoiceServiceStateOverride: subId=" + subId + ", phone=" + phone
+ + ", hasService=" + hasService + ", callingPackage=" + callingPackage);
phone.setVoiceServiceStateOverride(hasService);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -11314,5 +11893,634 @@
}
}
+ /**
+ * Get the component name of the default app to direct respond-via-message intent for the
+ * user associated with this subscription, update the cache if there is no respond-via-message
+ * application currently configured for this user.
+ * @return component name of the app and class to direct Respond Via Message intent to, or
+ * {@code null} if the functionality is not supported.
+ * @hide
+ */
+ @Override
+ public @Nullable ComponentName getDefaultRespondViaMessageApplication(int subId,
+ boolean updateIfNeeded) {
+ enforceInteractAcrossUsersPermission("getDefaultRespondViaMessageApplication");
+ Context context = getPhoneFromSubIdOrDefault(subId).getContext();
+
+ UserHandle userHandle = null;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ userHandle = TelephonyUtils.getSubscriptionUserHandle(context, subId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return SmsApplication.getDefaultRespondViaMessageApplicationAsUser(context,
+ updateIfNeeded, userHandle);
+ }
+
+ /**
+ * Set whether the device is able to connect with null ciphering or integrity
+ * algorithms. This is a global setting and will apply to all active subscriptions
+ * and all new subscriptions after this.
+ *
+ * @param enabled when true, null cipher and integrity algorithms are allowed.
+ * @hide
+ */
+ @Override
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public void setNullCipherAndIntegrityEnabled(boolean enabled) {
+ enforceModifyPermission();
+ checkForNullCipherAndIntegritySupport();
+
+ // Persist the state of our preference. Each GsmCdmaPhone instance is responsible
+ // for listening to these preference changes and applying them immediately.
+ SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
+ editor.putBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, enabled);
+ editor.apply();
+
+ for (Phone phone: PhoneFactory.getPhones()) {
+ phone.handleNullCipherEnabledChange();
+ }
+ }
+
+
+ /**
+ * Get whether the device is able to connect with null ciphering or integrity
+ * algorithms. Note that this retrieves the phone-global preference and not
+ * the state of the radio.
+ *
+ * @throws SecurityException if {@link permission#MODIFY_PHONE_STATE} is not satisfied
+ * @throws UnsupportedOperationException if the device does not support the minimum HAL
+ * version for this feature.
+ * @hide
+ */
+ @Override
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public boolean isNullCipherAndIntegrityPreferenceEnabled() {
+ enforceReadPermission();
+ checkForNullCipherAndIntegritySupport();
+ return getDefaultPhone().getNullCipherAndIntegrityEnabledPreference();
+ }
+
+ private void checkForNullCipherAndIntegritySupport() {
+ if (getHalVersion(HAL_SERVICE_NETWORK) < MIN_NULL_CIPHER_AND_INTEGRITY_VERSION) {
+ throw new UnsupportedOperationException(
+ "Null cipher and integrity operations require HAL 2.1 or above");
+ }
+ if (!getDefaultPhone().isNullCipherAndIntegritySupported()) {
+ throw new UnsupportedOperationException(
+ "Null cipher and integrity operations unsupported by modem");
+ }
+ }
+
+ /**
+ * Get the SIM state for the slot index.
+ * For Remote-SIMs, this method returns {@link IccCardConstants.State#UNKNOWN}
+ *
+ * @return SIM state as the ordinal of {@link IccCardConstants.State}
+ */
+ @Override
+ @SimState
+ public int getSimStateForSlotIndex(int slotIndex) {
+ IccCardConstants.State simState;
+ if (slotIndex < 0) {
+ simState = IccCardConstants.State.UNKNOWN;
+ } else {
+ Phone phone = null;
+ try {
+ phone = PhoneFactory.getPhone(slotIndex);
+ } catch (IllegalStateException e) {
+ // ignore
+ }
+ if (phone == null) {
+ simState = IccCardConstants.State.UNKNOWN;
+ } else {
+ IccCard icc = phone.getIccCard();
+ if (icc == null) {
+ simState = IccCardConstants.State.UNKNOWN;
+ } else {
+ simState = icc.getState();
+ }
+ }
+ }
+ return simState.ordinal();
+ }
+
+ /**
+ * Get current cell broadcast ranges.
+ */
+ @Override
+ @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
+ public List<CellBroadcastIdRange> getCellBroadcastIdRanges(int subId) {
+ mApp.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
+ "getCellBroadcastIdRanges");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return getPhone(subId).getCellBroadcastIdRanges();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Set reception of cell broadcast messages with the list of the given ranges
+ *
+ * @param ranges the list of {@link CellBroadcastIdRange} to be enabled
+ */
+ @Override
+ @RequiresPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS)
+ public void setCellBroadcastIdRanges(int subId, @NonNull List<CellBroadcastIdRange> ranges,
+ @Nullable IIntegerConsumer callback) {
+ mApp.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
+ "setCellBroadcastIdRanges");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Phone phone = getPhoneFromSubId(subId);
+ if (DBG) {
+ log("setCellBroadcastIdRanges for subId :" + subId + ", phone:" + phone);
+ }
+ phone.setCellBroadcastIdRanges(ranges, result -> {
+ if (callback != null) {
+ try {
+ callback.accept(result);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "setCellBroadcastIdRanges: callback not available.");
+ }
+ }
+ });
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Returns whether the device supports the domain selection service.
+ *
+ * @return {@code true} if the device supports the domain selection service.
+ */
+ @Override
+ public boolean isDomainSelectionSupported() {
+ mApp.enforceCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+ "isDomainSelectionSupported");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return DomainSelectionResolver.getInstance().isDomainSelectionSupported();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
+ * Request to enable or disable the satellite modem. If the satellite modem is enabled, this
+ * will also disable the cellular modem, and if the satellite modem is disabled, this will also
+ * re-enable the cellular modem.
+ *
+ * @param subId The subId of the subscription to set satellite enabled for.
+ * @param enable {@code true} to enable the satellite modem and {@code false} to disable.
+ * @param callback The callback to get the error code of the request.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestSatelliteEnabled(
+ int subId, boolean enable, @NonNull IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("requestSatelliteEnabled");
+ mSatelliteController.requestSatelliteEnabled(subId, enable, callback);
+ }
+
+ /**
+ * Request to get whether the satellite modem is enabled.
+ *
+ * @param subId The subId of the subscription to check whether satellite is enabled for.
+ * @param result The result receiver that returns whether the satellite modem is enabled
+ * if the request is successful or an error code if the request failed.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestIsSatelliteEnabled(int subId, @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission("requestIsSatelliteEnabled");
+ mSatelliteController.requestIsSatelliteEnabled(subId, result);
+ }
+
+ /**
+ * Request to enable or disable the satellite service demo mode.
+ *
+ * @param subId The subId of the subscription to set the satellite demo mode enabled for.
+ * @param enable {@code true} to enable the satellite demo mode and {@code false} to disable.
+ * @param callback The callback to get the error code of the request.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestSatelliteDemoModeEnabled(
+ int subId, boolean enable, @NonNull IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("requestSatelliteDemoModeEnabled");
+ mSatelliteController.requestSatelliteDemoModeEnabled(subId, enable, callback);
+ }
+
+ /**
+ * Request to get whether the satellite service demo mode is enabled.
+ *
+ * @param subId The subId of the subscription to check whether the satellite demo mode
+ * is enabled for.
+ * @param result The result receiver that returns whether the satellite demo mode is enabled
+ * if the request is successful or an error code if the request failed.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestIsSatelliteDemoModeEnabled(int subId, @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission("requestIsSatelliteDemoModeEnabled");
+ mSatelliteController.requestIsSatelliteDemoModeEnabled(subId, result);
+ }
+
+ /**
+ * Request to get whether the satellite service is supported on the device.
+ *
+ * @param subId The subId of the subscription to check satellite service support for.
+ * @param result The result receiver that returns whether the satellite service is supported on
+ * the device if the request is successful or an error code if the request failed.
+ */
+ @Override
+ public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) {
+ mSatelliteController.requestIsSatelliteSupported(subId, result);
+ }
+
+ /**
+ * Request to get the {@link SatelliteCapabilities} of the satellite service.
+ *
+ * @param subId The subId of the subscription to get the satellite capabilities for.
+ * @param result The result receiver that returns the {@link SatelliteCapabilities}
+ * if the request is successful or an error code if the request failed.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ @Override
+ public void requestSatelliteCapabilities(int subId, @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission("requestSatelliteCapabilities");
+ mSatelliteController.requestSatelliteCapabilities(subId, result);
+ }
+
+ /**
+ * Start receiving satellite position updates.
+ * This can be called by the pointing UI when the user starts pointing to the satellite.
+ * Modem should continue to report the pointing input as the device or satellite moves.
+ *
+ * @param subId The subId of the subscription to start satellite position updates for.
+ * @param errorCallback The callback to get the error code of the request.
+ * @param callback The callback to notify of changes in satellite position.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void startSatellitePositionUpdates(int subId, @NonNull IIntegerConsumer errorCallback,
+ @NonNull ISatellitePositionUpdateCallback callback) {
+ enforceSatelliteCommunicationPermission("startSatellitePositionUpdates");
+ mSatelliteController.startSatellitePositionUpdates(subId, errorCallback, callback);
+ }
+
+ /**
+ * Stop receiving satellite position updates.
+ * This can be called by the pointing UI when the user stops pointing to the satellite.
+ *
+ * @param subId The subId of the subscription to stop satellite position updates for.
+ * @param errorCallback The callback to get the error code of the request.
+ * @param callback The callback that was passed to {@link
+ * #startSatellitePositionUpdates(int, IIntegerConsumer, ISatellitePositionUpdateCallback)}
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void stopSatellitePositionUpdates(int subId, @NonNull IIntegerConsumer errorCallback,
+ @NonNull ISatellitePositionUpdateCallback callback) {
+ enforceSatelliteCommunicationPermission("stopSatellitePositionUpdates");
+ mSatelliteController.stopSatellitePositionUpdates(subId, errorCallback, callback);
+ }
+
+ /**
+ * Request to get the maximum number of bytes per datagram that can be sent to satellite.
+ *
+ * @param subId The subId of the subscription to get the maximum number of characters for.
+ * @param result The result receiver that returns the maximum number of bytes per datagram
+ * message on satellite if the request is successful or an error code
+ * if the request failed.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestMaxSizePerSendingDatagram(int subId,
+ @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission("requestMaxSizePerSendingDatagram");
+ mSatelliteController.requestMaxSizePerSendingDatagram(subId, result);
+ }
+
+ /**
+ * Register the subscription with a satellite provider.
+ * This is needed to register the subscription if the provider allows dynamic registration.
+ *
+ * @param subId The subId of the subscription to be provisioned.
+ * @param token The token to be used as a unique identifier for provisioning with satellite
+ * gateway.
+ * @param callback The callback to get the error code of the request.
+ *
+ * @return The signal transport used by the caller to cancel the provision request,
+ * or {@code null} if the request failed.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ @Nullable public ICancellationSignal provisionSatelliteService(int subId,
+ @NonNull String token, @NonNull IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("provisionSatelliteService");
+ return mSatelliteController.provisionSatelliteService(subId, token, callback);
+ }
+
+ /**
+ * Unregister the device/subscription with the satellite provider.
+ * This is needed if the provider allows dynamic registration. Once deprovisioned,
+ * {@link SatelliteProvisionStateCallback#onSatelliteProvisionStateChanged(boolean)}
+ * should report as deprovisioned.
+ *
+ * @param subId The subId of the subscription to be deprovisioned.
+ * @param token The token of the device/subscription to be deprovisioned.
+ * @param callback The callback to get the error code of the request.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void deprovisionSatelliteService(int subId,
+ @NonNull String token, @NonNull IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("deprovisionSatelliteService");
+ mSatelliteController.deprovisionSatelliteService(subId, token, callback);
+ }
+
+ /**
+ * Registers for the satellite provision state changed.
+ *
+ * @param subId The subId of the subscription to register for provision state changed.
+ * @param callback The callback to handle the satellite provision state changed event.
+ *
+ * @return The {@link SatelliteManager.SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ @SatelliteManager.SatelliteError public int registerForSatelliteProvisionStateChanged(int subId,
+ @NonNull ISatelliteProvisionStateCallback callback) {
+ enforceSatelliteCommunicationPermission("registerForSatelliteProvisionStateChanged");
+ return mSatelliteController.registerForSatelliteProvisionStateChanged(subId, callback);
+ }
+
+ /**
+ * Unregisters for the satellite provision state changed.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for provision state changed.
+ * @param callback The callback that was passed to
+ * {@link #registerForSatelliteProvisionStateChanged(int, ISatelliteProvisionStateCallback)}.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void unregisterForSatelliteProvisionStateChanged(
+ int subId, @NonNull ISatelliteProvisionStateCallback callback) {
+ enforceSatelliteCommunicationPermission("unregisterForSatelliteProvisionStateChanged");
+ mSatelliteController.unregisterForSatelliteProvisionStateChanged(subId, callback);
+ }
+
+ /**
+ * Request to get whether the device is provisioned with a satellite provider.
+ *
+ * @param subId The subId of the subscription to get whether the device is provisioned for.
+ * @param result The result receiver that returns whether the device is provisioned with a
+ * satellite provider if the request is successful or an error code if the
+ * request failed.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestIsSatelliteProvisioned(int subId, @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission("requestIsSatelliteProvisioned");
+ mSatelliteController.requestIsSatelliteProvisioned(subId, result);
+ }
+
+ /**
+ * Registers for modem state changed from satellite modem.
+ *
+ * @param subId The subId of the subscription to register for satellite modem state changed.
+ * @param callback The callback to handle the satellite modem state changed event.
+ *
+ * @return The {@link SatelliteManager.SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ @SatelliteManager.SatelliteError public int registerForSatelliteModemStateChanged(int subId,
+ @NonNull ISatelliteStateCallback callback) {
+ enforceSatelliteCommunicationPermission("registerForSatelliteModemStateChanged");
+ return mSatelliteController.registerForSatelliteModemStateChanged(subId, callback);
+ }
+
+ /**
+ * Unregisters for modem state changed from satellite modem.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for satellite modem state changed.
+ * @param callback The callback that was passed to
+ * {@link #registerForSatelliteModemStateChanged(int, ISatelliteStateCallback)}.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void unregisterForSatelliteModemStateChanged(int subId,
+ @NonNull ISatelliteStateCallback callback) {
+ enforceSatelliteCommunicationPermission("unregisterForSatelliteModemStateChanged");
+ mSatelliteController.unregisterForSatelliteModemStateChanged(subId, callback);
+ }
+
+ /**
+ * Register to receive incoming datagrams over satellite.
+ *
+ * @param subId The subId of the subscription to register for incoming satellite datagrams.
+ * @param datagramType datagram type indicating whether the datagram is of type
+ * SOS_SMS or LOCATION_SHARING.
+ * @param callback The callback to handle incoming datagrams over satellite.
+ *
+ * @return The {@link SatelliteManager.SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ @SatelliteManager.SatelliteError public int registerForSatelliteDatagram(int subId,
+ @SatelliteManager.DatagramType int datagramType,
+ @NonNull ISatelliteDatagramCallback callback) {
+ enforceSatelliteCommunicationPermission("registerForSatelliteDatagram");
+ return mSatelliteController.registerForSatelliteDatagram(subId, datagramType, callback);
+ }
+
+ /**
+ * Unregister to stop receiving incoming datagrams over satellite.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for incoming satellite datagrams.
+ * @param callback The callback that was passed to
+ * {@link #registerForSatelliteDatagram(int, int, ISatelliteDatagramCallback)}.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void unregisterForSatelliteDatagram(int subId,
+ @NonNull ISatelliteDatagramCallback callback) {
+ enforceSatelliteCommunicationPermission("unregisterForSatelliteDatagram");
+ mSatelliteController.unregisterForSatelliteDatagram(subId, callback);
+ }
+
+ /**
+ * Poll pending satellite datagrams over satellite.
+ *
+ * This method requests modem to check if there are any pending datagrams to be received over
+ * satellite. If there are any incoming datagrams, they will be received via
+ * {@link SatelliteDatagramCallback#onSatelliteDatagramReceived(long, SatelliteDatagram, int,
+ * ILongConsumer)})}
+ *
+ * @param subId The subId of the subscription used for receiving datagrams.
+ * @param callback The callback to get {@link SatelliteManager.SatelliteError} of the request.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ @Override
+ public void pollPendingSatelliteDatagrams(int subId, IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("pollPendingSatelliteDatagrams");
+ mSatelliteController.pollPendingSatelliteDatagrams(subId, callback);
+ }
+
+ /**
+ * Send datagram over satellite.
+ *
+ * Gateway encodes SOS message or location sharing message into a datagram and passes it as
+ * input to this method. Datagram received here will be passed down to modem without any
+ * encoding or encryption.
+ *
+ * @param subId The subId of the subscription to send satellite datagrams for.
+ * @param datagramType datagram type indicating whether the datagram is of type
+ * SOS_SMS or LOCATION_SHARING.
+ * @param datagram encoded gateway datagram which is encrypted by the caller.
+ * Datagram will be passed down to modem without any encoding or encryption.
+ * @param needFullScreenPointingUI this is used to indicate pointingUI app to open in
+ * full screen mode.
+ * @param callback The callback to get {@link SatelliteManager.SatelliteError} of the request.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ @Override
+ public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
+ @NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
+ @NonNull IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("sendSatelliteDatagram");
+ mSatelliteController.sendSatelliteDatagram(subId, datagramType, datagram,
+ needFullScreenPointingUI, callback);
+ }
+
+ /**
+ * Request to get whether satellite communication is allowed for the current location.
+ *
+ * @param subId The subId of the subscription to check whether satellite communication is
+ * allowed for the current location for.
+ * @param result The result receiver that returns whether satellite communication is allowed
+ * for the current location if the request is successful or an error code
+ * if the request failed.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestIsSatelliteCommunicationAllowedForCurrentLocation(int subId,
+ @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission(
+ "requestIsSatelliteCommunicationAllowedForCurrentLocation");
+ mSatelliteController.requestIsSatelliteCommunicationAllowedForCurrentLocation(subId,
+ result);
+ }
+
+ /**
+ * Request to get the time after which the satellite will be visible
+ *
+ * @param subId The subId to get the time after which the satellite will be visible for.
+ * @param result The result receiver that returns the time after which the satellite will
+ * be visible if the request is successful or an error code if the request failed.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestTimeForNextSatelliteVisibility(int subId, @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission("requestTimeForNextSatelliteVisibility");
+ mSatelliteController.requestTimeForNextSatelliteVisibility(subId, result);
+ }
+
+ private Phone getPhoneOrDefault(int subId, String caller) {
+ Phone phone = getPhone(subId);
+ if (phone == null) {
+ loge(caller + " called with invalid subId: " + subId
+ + ". Retrying with default phone.");
+ phone = getDefaultPhone();
+ if (phone == null) {
+ loge(caller + " failed with no phone object.");
+ }
+ }
+ return phone;
+ }
+
+ /**
+ * Check whether the caller (or self, if not processing an IPC) can read device identifiers.
+ *
+ * <p>This method behaves in one of the following ways:
+ * <ul>
+ * <li>return true : if the calling package has the appop permission {@link
+ * Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER} in the manifest </>
+ * <li>return true : if any one subscription has the READ_PRIVILEGED_PHONE_STATE
+ * permission, the calling package passes a DevicePolicyManager Device Owner / Profile
+ * Owner device identifier access check, or the calling package has carrier privileges</>
+ * <li>throw SecurityException: if the caller does not meet any of the requirements.
+ * </ul>
+ */
+ private static boolean checkCallingOrSelfReadDeviceIdentifiersForAnySub(Context context,
+ String callingPackage, @Nullable String callingFeatureId, String message) {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(context,
+ phone.getSubId(), callingPackage, callingFeatureId, message)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return The subscription manager service instance.
+ */
+ public SubscriptionManagerService getSubscriptionManagerService() {
+ return SubscriptionManagerService.getInstance();
+ }
+
+ /**
+ * Class binds the consumer[callback] and carrierId.
+ */
+ private static class CallerCallbackInfo {
+ private final Consumer<Integer> mConsumer;
+ private final int mCarrierId;
+
+ public CallerCallbackInfo(Consumer<Integer> consumer, int carrierId) {
+ mConsumer = consumer;
+ mCarrierId = carrierId;
+ }
+
+ public Consumer<Integer> getConsumer() {
+ return mConsumer;
+ }
+
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+ }
}
diff --git a/src/com/android/phone/PhoneUtils.java b/src/com/android/phone/PhoneUtils.java
index d0aad4a..4826d2b 100644
--- a/src/com/android/phone/PhoneUtils.java
+++ b/src/com/android/phone/PhoneUtils.java
@@ -31,6 +31,7 @@
import android.os.Handler;
import android.os.Message;
import android.os.PersistableBundle;
+import android.os.UserHandle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.telecom.PhoneAccount;
@@ -701,31 +702,28 @@
Log.d(LOG_TAG, msg);
}
- public static PhoneAccountHandle makePstnPhoneAccountHandle(String id) {
- return makePstnPhoneAccountHandleWithPrefix(id, "", false);
- }
-
- public static PhoneAccountHandle makePstnPhoneAccountHandle(int phoneId) {
- return makePstnPhoneAccountHandle(PhoneFactory.getPhone(phoneId));
- }
-
public static PhoneAccountHandle makePstnPhoneAccountHandle(Phone phone) {
- return makePstnPhoneAccountHandleWithPrefix(phone, "", false);
+ return makePstnPhoneAccountHandleWithPrefix(phone, "",
+ false, phone.getUserHandle());
}
public static PhoneAccountHandle makePstnPhoneAccountHandleWithPrefix(
- Phone phone, String prefix, boolean isEmergency) {
+ Phone phone, String prefix, boolean isEmergency, UserHandle userHandle) {
// TODO: Should use some sort of special hidden flag to decorate this account as
// an emergency-only account
String id = isEmergency ? EMERGENCY_ACCOUNT_HANDLE_ID : prefix +
String.valueOf(phone.getSubId());
- return makePstnPhoneAccountHandleWithPrefix(id, prefix, isEmergency);
+ return makePstnPhoneAccountHandleWithId(id, userHandle);
}
- public static PhoneAccountHandle makePstnPhoneAccountHandleWithPrefix(
- String id, String prefix, boolean isEmergency) {
+ public static PhoneAccountHandle makePstnPhoneAccountHandleWithId(
+ String id, UserHandle userHandle) {
ComponentName pstnConnectionServiceName = getPstnConnectionServiceName();
- return new PhoneAccountHandle(pstnConnectionServiceName, id);
+ // If user handle is null, resort to default constructor to use phone process's
+ // user handle
+ return userHandle == null
+ ? new PhoneAccountHandle(pstnConnectionServiceName, id)
+ : new PhoneAccountHandle(pstnConnectionServiceName, id, userHandle);
}
public static int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
diff --git a/src/com/android/phone/SubscriptionInfoHelper.java b/src/com/android/phone/SubscriptionInfoHelper.java
index 14faebc..f964f82 100644
--- a/src/com/android/phone/SubscriptionInfoHelper.java
+++ b/src/com/android/phone/SubscriptionInfoHelper.java
@@ -55,8 +55,8 @@
*/
public SubscriptionInfoHelper(Context context, Intent intent) {
mContext = context;
- PhoneAccountHandle phoneAccountHandle =
- intent.getParcelableExtra(TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE);
+ PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra(
+ TelephonyManager.EXTRA_PHONE_ACCOUNT_HANDLE, PhoneAccountHandle.class);
if (phoneAccountHandle != null) {
mSubId = PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccountHandle);
}
diff --git a/src/com/android/phone/Telephony2gUpdater.java b/src/com/android/phone/Telephony2gUpdater.java
deleted file mode 100644
index baaa684..0000000
--- a/src/com/android/phone/Telephony2gUpdater.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.phone;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.UserManager;
-import android.telephony.RadioAccessFamily;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.RILConstants;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-
-/**
- * A {@link BroadcastReceiver} that ensures that user restrictions are correctly applied to
- * telephony.
- * This includes handling broadcasts from user restriction state changes, as well as ensuring that
- * SIM-specific settings are correctly applied when new subscriptions become active.
- *
- * <p>
- * Callers are expected to call {@code init()} and keep an instance of this class alive.
- * </p>
- */
-public class Telephony2gUpdater extends BroadcastReceiver {
- private static final String TAG = "Telephony2gUpdater";
-
- // We can't interact with the HAL on the main thread of the phone process (where
- // receivers are run by default), so we execute our logic from a separate thread.
- // The correctness of this implementation relies heavily on this executor ensuring
- // tasks are serially executed i.e. ExecutorService.newSingleThreadExecutor()
- private final Executor mExecutor;
- private final Context mContext;
- private final long mBaseAllowedNetworks;
-
- private UserManager mUserManager;
- private TelephonyManager mTelephonyManager;
- private SubscriptionManager mSubscriptionManager;
-
- // The current subscription ids
- // Ensure this value is never accessed concurrently
- private Set<Integer> mCurrentSubscriptions;
- // We keep track of the last value to avoid updating when unrelated user restrictions change
- // Ensure this value is never accessed concurrently
- private boolean mDisallowCellular2gRestriction;
-
- public Telephony2gUpdater(Context context) {
- this(Executors.newSingleThreadExecutor(), context,
- RadioAccessFamily.getRafFromNetworkType(RILConstants.PREFERRED_NETWORK_MODE));
- }
-
- @VisibleForTesting
- public Telephony2gUpdater(Executor executor, Context context, long baseAllowedNetworks) {
- mExecutor = executor;
- mContext = context;
- mBaseAllowedNetworks = baseAllowedNetworks;
-
- mUserManager = mContext.getSystemService(UserManager.class);
- mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
- mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
-
- // All user restrictions are false by default
- mDisallowCellular2gRestriction = false;
- mCurrentSubscriptions = new HashSet<>();
- }
-
- /**
- * Register the given instance as a {@link BroadcastReceiver} and a {@link
- * SubscriptionManager.OnSubscriptionsChangedListener}.
- */
- public void init() {
- mContext.getSystemService(SubscriptionManager.class).addOnSubscriptionsChangedListener(
- mExecutor, new SubscriptionListener());
- IntentFilter filter = new IntentFilter();
- filter.addAction(UserManager.ACTION_USER_RESTRICTIONS_CHANGED);
- mContext.registerReceiver(this, filter);
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (context == null || intent == null) return;
- Log.i(TAG, "Received callback for action " + intent.getAction());
- final PendingResult result = goAsync();
- mExecutor.execute(() -> {
- boolean disallow2g = mUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G);
- if (mDisallowCellular2gRestriction == disallow2g) {
- Log.i(TAG, "No update to DISALLOW_CELLULAR_2G restriction.");
- return;
- }
-
- mDisallowCellular2gRestriction = disallow2g;
-
- Log.i(TAG, "Running handler for all subscriptions based on DISALLOW_CELLULAR_2G change."
- + " Restriction value: " + mDisallowCellular2gRestriction);
- handleUserRestrictionsChanged(mCurrentSubscriptions);
- if (result != null) {
- result.finish();
- }
- });
- }
-
- /**
- * Update subscriptions with allowed network types depending on the current state
- * of the {@link UserManager#DISALLOW_CELLULAR_2G}.
- *
- * @param subIds A list of subIds to update.
- */
- private void handleUserRestrictionsChanged(Collection<Integer> subIds) {
- final long twoGBitmask = TelephonyManager.NETWORK_CLASS_BITMASK_2G;
-
- long allowedNetworkTypes = mBaseAllowedNetworks;
-
- // 2G device admin controls are global
- for (Integer subId : subIds) {
- TelephonyManager telephonyManager = mTelephonyManager.createForSubscriptionId(subId);
- if (mDisallowCellular2gRestriction) {
- Log.i(TAG, "Disabling 2g based on user restriction for subId: " + subId);
- allowedNetworkTypes &= ~twoGBitmask;
- } else {
- Log.i(TAG, "Enabling 2g based on user restriction for subId: " + subId);
- allowedNetworkTypes |= twoGBitmask;
- }
- telephonyManager.setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS,
- allowedNetworkTypes);
- }
- }
-
- private class SubscriptionListener extends SubscriptionManager.OnSubscriptionsChangedListener {
- @Override
- public void onSubscriptionsChanged() {
- // Note that this entire callback gets invoked in the single threaded executor
- List<SubscriptionInfo> allSubscriptions =
- mSubscriptionManager.getCompleteActiveSubscriptionInfoList();
-
- HashSet<Integer> updatedSubIds = new HashSet<>(allSubscriptions.size());
- List<Integer> newSubIds = new ArrayList<>();
-
- for (SubscriptionInfo info : allSubscriptions) {
- updatedSubIds.add(info.getSubscriptionId());
- if (!mCurrentSubscriptions.contains(info.getSubscriptionId())) {
- newSubIds.add(info.getSubscriptionId());
- }
- }
-
- mCurrentSubscriptions = updatedSubIds;
-
- if (newSubIds.isEmpty()) {
- Log.d(TAG, "No new subIds. Skipping update.");
- return;
- }
-
- Log.i(TAG, "New subscriptions found. Running handler to update 2g restrictions with "
- + "subIds " + newSubIds.toString());
- handleUserRestrictionsChanged(newSubIds);
- }
- }
-
-}
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 9f86c24..1858fe2 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -57,6 +57,8 @@
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.modules.utils.BasicShellCommandHandler;
import com.android.phone.callcomposer.CallComposerPictureManager;
+import com.android.phone.euicc.EuiccUiDispatcherActivity;
+import com.android.phone.utils.CarrierAllowListInfo;
import java.io.IOException;
import java.io.PrintWriter;
@@ -64,6 +66,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
@@ -96,6 +99,8 @@
private static final String ENABLE = "enable";
private static final String DISABLE = "disable";
private static final String QUERY = "query";
+ private static final String CARRIER_RESTRICTION_STATUS_TEST = "carrier_restriction_status_test";
+ private final String QUOTES = "\"";
private static final String CALL_COMPOSER_TEST_MODE = "test-mode";
private static final String CALL_COMPOSER_SIMULATE_CALL = "simulate-outgoing-call";
@@ -117,6 +122,9 @@
private static final String CC_SET_VALUES_FROM_XML = "set-values-from-xml";
private static final String CC_CLEAR_VALUES = "clear-values";
+ private static final String EUICC_SUBCOMMAND = "euicc";
+ private static final String EUICC_SET_UI_COMPONENT = "set-euicc-uicomponent";
+
private static final String GBA_SUBCOMMAND = "gba";
private static final String GBA_SET_SERVICE = "set-service";
private static final String GBA_GET_SERVICE = "get-service";
@@ -168,6 +176,13 @@
private static final String ALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "allow-package";
private static final String DISALLOW_THERMAL_MITIGATION_PACKAGE_SUBCOMMAND = "disallow-package";
+ private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
+ + "'*', '#' or '+') needs to be specified after -a in the command ";
+
+ private static final int[] ROUTING_TYPES = {EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL};
+
private static final String GET_ALLOWED_NETWORK_TYPES_FOR_USER =
"get-allowed-network-types-for-users";
private static final String SET_ALLOWED_NETWORK_TYPES_FOR_USER =
@@ -302,6 +317,8 @@
return handleDataTestModeCommand();
case END_BLOCK_SUPPRESSION:
return handleEndBlockSuppressionCommand();
+ case EUICC_SUBCOMMAND:
+ return handleEuiccCommand();
case GBA_SUBCOMMAND:
return handleGbaCommand();
case D2D_SUBCOMMAND:
@@ -333,6 +350,8 @@
return handleGetSimSlotsMapping();
case RADIO_SUBCOMMAND:
return handleRadioCommand();
+ case CARRIER_RESTRICTION_STATUS_TEST:
+ return handleCarrierRestrictionStatusCommand();
default: {
return handleDefaultCommands(cmd);
}
@@ -595,6 +614,15 @@
pw.println(" is specified, it will choose the default voice SIM slot.");
}
+ private void onHelpEuicc() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("Euicc Commands:");
+ pw.println(" euicc set-euicc-uicomponent COMPONENT_NAME PACKAGE_NAME");
+ pw.println(" Sets the Euicc Ui-Component which handles EuiccService Actions.");
+ pw.println(" COMPONENT_NAME: The component name which handles UI Actions.");
+ pw.println(" PACKAGE_NAME: THe package name in which ui component belongs.");
+ }
+
private void onHelpGba() {
PrintWriter pw = getOutPrintWriter();
pw.println("Gba Commands:");
@@ -785,6 +813,24 @@
return 0;
}
+ private void removeEmergencyNumberTestMode(String emergencyNumber) {
+ PrintWriter errPw = getErrPrintWriter();
+ for (int routingType : ROUTING_TYPES) {
+ try {
+ mInterface.updateEmergencyNumberListTestMode(
+ EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
+ new EmergencyNumber(emergencyNumber, "", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
+ routingType));
+ } catch (RemoteException ex) {
+ Log.w(LOG_TAG, "emergency-number-test-mode " + "error " + ex.getMessage());
+ errPw.println("Exception: " + ex.getMessage());
+ }
+ }
+ }
+
private int handleEmergencyNumberTestModeCommand() {
PrintWriter errPw = getErrPrintWriter();
String opt = getNextOption();
@@ -792,26 +838,52 @@
onHelpEmergencyNumber();
return 0;
}
-
switch (opt) {
case "-a": {
String emergencyNumberCmd = getNextArgRequired();
- if (emergencyNumberCmd == null
- || !EmergencyNumber.validateEmergencyNumberAddress(emergencyNumberCmd)) {
- errPw.println("An emergency number (only allow '0'-'9', '*', '#' or '+') needs"
- + " to be specified after -a in the command ");
+ if (emergencyNumberCmd == null){
+ errPw.println(INVALID_ENTRY_ERROR);
return -1;
}
+ String[] params = emergencyNumberCmd.split(":");
+ String emergencyNumber;
+ if (params[0] == null ||
+ !EmergencyNumber.validateEmergencyNumberAddress(params[0])){
+ errPw.println(INVALID_ENTRY_ERROR);
+ return -1;
+ } else {
+ emergencyNumber = params[0];
+ }
+ removeEmergencyNumberTestMode(emergencyNumber);
+ int emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN;
+ if (params.length > 1) {
+ switch (params[1].toLowerCase(Locale.ROOT)) {
+ case "emergency":
+ emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY;
+ break;
+ case "normal":
+ emergencyCallRouting = EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
+ break;
+ case "unknown":
+ break;
+ default:
+ errPw.println("\"" + params[1] + "\" is not a valid specification for "
+ + "emergency call routing. Please enter either \"normal\", "
+ + "\"unknown\", or \"emergency\" for call routing. "
+ + "(-a 1234:normal)");
+ return -1;
+ }
+ }
try {
mInterface.updateEmergencyNumberListTestMode(
EmergencyNumberTracker.ADD_EMERGENCY_NUMBER_TEST_MODE,
- new EmergencyNumber(emergencyNumberCmd, "", "",
+ new EmergencyNumber(emergencyNumber, "", "",
EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
new ArrayList<String>(),
EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
- EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+ emergencyCallRouting));
} catch (RemoteException ex) {
- Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumberCmd
+ Log.w(LOG_TAG, "emergency-number-test-mode -a " + emergencyNumber
+ ", error " + ex.getMessage());
errPw.println("Exception: " + ex.getMessage());
return -1;
@@ -837,20 +909,7 @@
+ " to be specified after -r in the command ");
return -1;
}
- try {
- mInterface.updateEmergencyNumberListTestMode(
- EmergencyNumberTracker.REMOVE_EMERGENCY_NUMBER_TEST_MODE,
- new EmergencyNumber(emergencyNumberCmd, "", "",
- EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
- new ArrayList<String>(),
- EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
- EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
- } catch (RemoteException ex) {
- Log.w(LOG_TAG, "emergency-number-test-mode -r " + emergencyNumberCmd
- + ", error " + ex.getMessage());
- errPw.println("Exception: " + ex.getMessage());
- return -1;
- }
+ removeEmergencyNumberTestMode(emergencyNumberCmd);
break;
}
case "-p": {
@@ -1139,7 +1198,7 @@
return 0;
}
- boolean isEnabled = "true".equals(arg.toLowerCase());
+ boolean isEnabled = "true".equals(arg.toLowerCase(Locale.ROOT));
try {
mInterface.setDeviceToDeviceForceEnabled(isEnabled);
} catch (RemoteException e) {
@@ -2014,6 +2073,35 @@
return 0;
}
+ private int handleEuiccCommand() {
+ String arg = getNextArg();
+ if (arg == null) {
+ onHelpEuicc();
+ return 0;
+ }
+
+ switch (arg) {
+ case EUICC_SET_UI_COMPONENT: {
+ return handleEuiccServiceCommand();
+ }
+ }
+ return -1;
+ }
+
+ private int handleEuiccServiceCommand() {
+ String uiComponent = getNextArg();
+ String packageName = getNextArg();
+ if (packageName == null || uiComponent == null) {
+ return -1;
+ }
+ EuiccUiDispatcherActivity.setTestEuiccUiComponent(packageName, uiComponent);
+ if (VDBG) {
+ Log.v(LOG_TAG, "euicc set-euicc-uicomponent " + uiComponent +" "
+ + packageName);
+ }
+ return 0;
+ }
+
private int handleRestartModemCommand() {
// Verify that the user is allowed to run the command. Only allowed in rooted device in a
// non user build.
@@ -2972,4 +3060,74 @@
return -1;
}
+
+ private int handleCarrierRestrictionStatusCommand() {
+ try {
+ String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
+ if (!(checkShellUid() && MOCK_MODEM_SERVICE_NAME.equalsIgnoreCase(
+ mInterface.getModemService()))) {
+ Log.v(LOG_TAG,
+ "handleCarrierRestrictionStatusCommand, MockModem service check fails or "
+ + " checkShellUid fails");
+ return -1;
+ }
+ } catch (RemoteException ex) {
+ ex.printStackTrace();
+ }
+ String callerInfo = getNextOption();
+ CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mContext);
+ if (TextUtils.isEmpty(callerInfo)) {
+ // reset the Json content after testing
+ allowListInfo.updateJsonForTest(null);
+ return 0;
+ }
+ if (callerInfo.startsWith("--")) {
+ callerInfo = callerInfo.replace("--", "");
+ }
+ String params[] = callerInfo.split(",");
+ StringBuffer jsonStrBuffer = new StringBuffer();
+ String tokens;
+ for (int index = 0; index < params.length; index++) {
+ tokens = convertToJsonString(index, params[index]);
+ if (TextUtils.isEmpty(tokens)) {
+ // received wrong format from CTS
+ if (VDBG) {
+ Log.v(LOG_TAG,
+ "handleCarrierRestrictionStatusCommand, Shell command parsing error");
+ }
+ return -1;
+ }
+ jsonStrBuffer.append(tokens);
+ }
+ int result = allowListInfo.updateJsonForTest(jsonStrBuffer.toString());
+ return result;
+ }
+
+
+ /**
+ * Building the string that can be used to build the JsonObject which supports to stub the data
+ * in CarrierAllowListInfo for CTS testing. sample format is like
+ * {"com.android.example":{"carrierId":"10000","callerSHA1Id":["XXXXXXXXXXXXXX"]}}
+ */
+ private String convertToJsonString(int index, String param) {
+
+ String token[] = param.split(":");
+ String jSonString;
+ switch (index) {
+ case 0:
+ jSonString = "{" + QUOTES + token[1] + QUOTES + ":";
+ break;
+ case 1:
+ jSonString =
+ "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
+ break;
+ case 2:
+ jSonString =
+ QUOTES + token[0] + QUOTES + ":" + "[" + QUOTES + token[1] + QUOTES + "]}}";
+ break;
+ default:
+ jSonString = null;
+ }
+ return jSonString;
+ }
}
diff --git a/src/com/android/phone/callcomposer/DigestAuthUtils.java b/src/com/android/phone/callcomposer/DigestAuthUtils.java
index 2f081f7..770aadf 100644
--- a/src/com/android/phone/callcomposer/DigestAuthUtils.java
+++ b/src/com/android/phone/callcomposer/DigestAuthUtils.java
@@ -30,6 +30,7 @@
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.ParseException;
+import java.util.Locale;
public class DigestAuthUtils {
private static final String TAG = DigestAuthUtils.class.getSimpleName();
@@ -54,12 +55,12 @@
public static String generateAuthorizationHeader(WWWAuthenticate parsedHeader,
GbaCredentials credentials, String method, String uri) {
if (!TextUtils.isEmpty(parsedHeader.getAlgorithm())
- && !MD5_ALGORITHM.equals(parsedHeader.getAlgorithm().toLowerCase())) {
+ && !MD5_ALGORITHM.equals(parsedHeader.getAlgorithm().toLowerCase(Locale.ROOT))) {
Log.e(TAG, "This client only supports MD5 auth");
return "";
}
if (!TextUtils.isEmpty(parsedHeader.getQop())
- && !AUTH_QOP.equals(parsedHeader.getQop().toLowerCase())) {
+ && !AUTH_QOP.equals(parsedHeader.getQop().toLowerCase(Locale.ROOT))) {
Log.e(TAG, "This client only supports the auth qop");
return "";
}
@@ -137,7 +138,7 @@
}
private static String base16(byte[] input) {
- return BaseEncoding.base16().encode(input).toLowerCase();
+ return BaseEncoding.base16().encode(input).toLowerCase(Locale.ROOT);
}
private static MessageDigest getMd5Digest() {
diff --git a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
index 804611f..5da52d6 100644
--- a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
+++ b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
@@ -29,6 +29,7 @@
import android.permission.LegacyPermissionManager;
import android.service.euicc.EuiccService;
import android.telephony.euicc.EuiccManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -58,6 +59,8 @@
private LegacyPermissionManager mPermissionManager;
private boolean mGrantPermissionDone = false;
private ThreadPoolExecutor mExecutor;
+ // Used for CTS EuiccManager action verification
+ private static ComponentName mTestEuiccUiComponentName;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -94,6 +97,18 @@
}
}
+ /**
+ * This API used to set the Test EuiccUiComponent for CTS
+ * @param packageName package which handles the intent
+ * @param componentName ui component to be launched for testing
+ */
+ public static void setTestEuiccUiComponent(String packageName, String componentName) {
+ mTestEuiccUiComponentName = null;
+ if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(componentName)) {
+ mTestEuiccUiComponentName = new ComponentName(packageName, componentName);
+ }
+ }
+
@VisibleForTesting
@Nullable
Intent resolveEuiccUiIntent() {
@@ -109,6 +124,13 @@
return null;
}
+ if (mTestEuiccUiComponentName != null) {
+ Log.i(TAG, "Test mode");
+ euiccUiIntent.setComponent(mTestEuiccUiComponentName);
+ mTestEuiccUiComponentName = null;
+ return euiccUiIntent;
+ }
+
revokePermissionFromLuiApps(euiccUiIntent);
ActivityInfo activityInfo = findBestActivity(euiccUiIntent);
@@ -148,6 +170,12 @@
case EuiccManager.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION:
intent.setAction(EuiccService.ACTION_PROVISION_EMBEDDED_SUBSCRIPTION);
break;
+ case EuiccManager.ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS:
+ intent.setAction(EuiccService.ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS);
+ break;
+ case EuiccManager.ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION:
+ intent.setAction(EuiccService.ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION);
+ break;
default:
Log.w(TAG, "Unsupported action: " + action);
return null;
diff --git a/src/com/android/phone/settings/AccessibilitySettingsFragment.java b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
index 475d878..4c29e65 100644
--- a/src/com/android/phone/settings/AccessibilitySettingsFragment.java
+++ b/src/com/android/phone/settings/AccessibilitySettingsFragment.java
@@ -40,6 +40,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.phone.PhoneGlobals;
import com.android.phone.R;
@@ -183,10 +184,16 @@
// Update RTT config with IMS Manager if the always-on carrier config isn't set to true.
CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService(
Context.CARRIER_CONFIG_SERVICE);
- for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
+ int[] activeSubIds;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ activeSubIds = SubscriptionManagerService.getInstance().getActiveSubIdList(true);
+ } else {
+ activeSubIds = SubscriptionController.getInstance().getActiveSubIdList(true);
+ }
+ for (int subId : activeSubIds) {
if (!configManager.getConfigForSubId(subId).getBoolean(
CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL, false)) {
- int phoneId = SubscriptionController.getInstance().getPhoneId(subId);
+ int phoneId = SubscriptionManager.getPhoneId(subId);
ImsManager imsManager = ImsManager.getInstance(getContext(), phoneId);
imsManager.setRttEnabled(mButtonRtt.isChecked());
}
@@ -264,6 +271,14 @@
private boolean shouldShowRttSetting() {
// Go through all the subs -- if we want to display the RTT setting for any of them, do
// display it.
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ for (int subId : SubscriptionManagerService.getInstance().getActiveSubIdList(true)) {
+ if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) {
+ return true;
+ }
+ }
+ return false;
+ }
for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) {
if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) {
return true;
diff --git a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
index 49e1379..7cc9235 100644
--- a/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
+++ b/src/com/android/phone/settings/PhoneAccountSettingsFragment.java
@@ -6,7 +6,9 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Icon;
+import android.os.Binder;
import android.os.Bundle;
+import android.os.UserHandle;
import android.os.UserManager;
import android.preference.Preference;
import android.preference.PreferenceCategory;
@@ -364,6 +366,7 @@
mTelecomManager.getCallCapablePhoneAccounts(includeDisabledAccounts);
for (Iterator<PhoneAccountHandle> i = accountHandles.iterator(); i.hasNext();) {
PhoneAccountHandle handle = i.next();
+ UserHandle userHandle = handle.getUserHandle();
if (handle.equals(emergencyAccountHandle)) {
// never include emergency call accounts in this piece of code.
i.remove();
@@ -376,6 +379,11 @@
} else if (!includeSims &&
account.hasCapabilities(PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)) {
i.remove();
+ } else if (!userHandle.equals(Binder.getCallingUserHandle())
+ && !account.hasCapabilities(PhoneAccount.CAPABILITY_MULTI_USER)) {
+ // Only show accounts for the current user (unless account has
+ // CAPABILITY_MULTI_USER).
+ i.remove();
}
}
return accountHandles;
@@ -387,7 +395,7 @@
private PhoneAccountHandle getEmergencyPhoneAccount() {
return PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
- (Phone) null, "" /* prefix */, true /* isEmergency */);
+ (Phone) null, "" /* prefix */, true /* isEmergency */, null /* userHandle */);
}
public static Intent buildPhoneAccountConfigureIntent(
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index 3cf0c93..574440a 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -29,6 +29,7 @@
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Typeface;
+import android.hardware.radio.modem.ImeiInfo;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -102,6 +103,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.euicc.EuiccConnector;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.phone.R;
import java.io.IOException;
@@ -256,6 +258,7 @@
private TextView mNetworkSlicingConfig;
private EditText mSmsc;
private Switch mRadioPowerOnSwitch;
+ private Switch mSimulateOutOfServiceSwitch;
private Button mCellInfoRefreshRateButton;
private Button mDnsCheckToggleButton;
private Button mPingTestButton;
@@ -292,6 +295,7 @@
private boolean mCfiValue = false;
private List<CellInfo> mCellInfoResult = null;
+ private final boolean[] mSimulateOos = new boolean[2];
private int mPreferredNetworkTypeResult;
private int mCellInfoRefreshRateIndex;
@@ -410,7 +414,7 @@
private void updatePhoneIndex(int phoneIndex, int subId) {
// unregister listeners on the old subId
unregisterPhoneStateListener();
- mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled);
+ mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mPhone.getSubId());
if (phoneIndex == SubscriptionManager.INVALID_PHONE_INDEX) {
log("Invalid phone index " + phoneIndex + ", subscription ID " + subId);
@@ -598,6 +602,11 @@
mRadioPowerOnSwitch = (Switch) findViewById(R.id.radio_power);
+ mSimulateOutOfServiceSwitch = (Switch) findViewById(R.id.simulate_out_of_service);
+ if (!TelephonyUtils.IS_DEBUGGABLE) {
+ mSimulateOutOfServiceSwitch.setVisibility(View.GONE);
+ }
+
mDownlinkKbps = (TextView) findViewById(R.id.dl_kbps);
mUplinkKbps = (TextView) findViewById(R.id.ul_kbps);
updateBandwidths(0, 0);
@@ -690,7 +699,8 @@
//set selection after registering listener to force update
mCellInfoRefreshRateSpinner.setSelection(mCellInfoRefreshRateIndex);
// Request cell information update from RIL.
- mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[mCellInfoRefreshRateIndex]);
+ mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[mCellInfoRefreshRateIndex],
+ mPhone.getSubId());
//set selection before registering to prevent update
mPreferredNetworkType.setSelection(mPreferredNetworkTypeResult, true);
@@ -707,6 +717,8 @@
mSelectPhoneIndex.setOnItemSelectedListener(mSelectPhoneIndexHandler);
mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
+ mSimulateOutOfServiceSwitch.setOnCheckedChangeListener(mSimulateOosOnChangeListener);
+ mSimulateOutOfServiceSwitch.setChecked(mSimulateOos[mPhone.getPhoneId()]);
mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
@@ -735,7 +747,7 @@
log("onPause: unregister phone & data intents");
mTelephonyManager.unregisterTelephonyCallback(mTelephonyCallback);
- mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled);
+ mTelephonyManager.setCellInfoListRate(sCellInfoListRateDisabled, mPhone.getSubId());
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
}
@@ -1234,11 +1246,16 @@
Resources r = getResources();
s = mPhone.getDeviceId();
- if (s == null) s = r.getString(R.string.radioInfo_unknown);
+ if (s == null) {
+ s = r.getString(R.string.radioInfo_unknown);
+ } else if (mPhone.getImeiType() == ImeiInfo.ImeiType.PRIMARY) {
+ s = s + " (" + r.getString(R.string.radioInfo_imei_primary) + ")";
+ }
mDeviceId.setText(s);
s = mPhone.getSubscriberId();
if (s == null) s = r.getString(R.string.radioInfo_unknown);
+
mSubscriberId.setText(s);
SubscriptionManager subMgr = getSystemService(SubscriptionManager.class);
@@ -1635,6 +1652,22 @@
}
};
+ private final OnCheckedChangeListener mSimulateOosOnChangeListener =
+ (buttonView, isChecked) -> {
+ Intent intent = new Intent("com.android.internal.telephony.TestServiceState");
+ if (isChecked) {
+ log("Send OOS override broadcast intent.");
+ intent.putExtra("data_reg_state", 1);
+ mSimulateOos[mPhone.getPhoneId()] = true;
+ } else {
+ log("Remove OOS override.");
+ intent.putExtra("action", "reset");
+ mSimulateOos[mPhone.getPhoneId()] = false;
+ }
+
+ mPhone.getTelephonyTester().setServiceStateTestIntent(intent);
+ };
+
private boolean isImsVolteProvisioned() {
return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
@@ -1889,7 +1922,7 @@
public void onItemSelected(AdapterView parent, View v, int pos, long id) {
mCellInfoRefreshRateIndex = pos;
- mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[pos]);
+ mTelephonyManager.setCellInfoListRate(CELL_INFO_REFRESH_RATES[pos], mPhone.getSubId());
updateAllCellInfo();
}
diff --git a/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java b/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java
new file mode 100644
index 0000000..8288c43
--- /dev/null
+++ b/src/com/android/phone/slice/PremiumNetworkEntitlementApi.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.slice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.PersistableBundle;
+import android.provider.DeviceConfig;
+import android.telephony.AnomalyReporter;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+import com.android.libraries.entitlement.CarrierConfig;
+import com.android.libraries.entitlement.ServiceEntitlement;
+import com.android.libraries.entitlement.ServiceEntitlementException;
+import com.android.libraries.entitlement.ServiceEntitlementRequest;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.UUID;
+
+/**
+ * Premium network entitlement API class to check the premium network slice entitlement result
+ * from carrier API over the network.
+ */
+public class PremiumNetworkEntitlementApi {
+ private static final String TAG = "PremiumNwEntitlementApi";
+ private static final String ENTITLEMENT_STATUS_KEY = "EntitlementStatus";
+ private static final String PROVISION_STATUS_KEY = "ProvStatus";
+ private static final String SERVICE_FLOW_URL_KEY = "ServiceFlow_URL";
+ private static final String SERVICE_FLOW_USERDATA_KEY = "ServiceFlow_UserData";
+ private static final String DEFAULT_EAP_AKA_RESPONSE = "Default EAP AKA response";
+ /**
+ * UUID to report an anomaly if an unexpected error is received during entitlement check.
+ */
+ private static final String UUID_ENTITLEMENT_CHECK_UNEXPECTED_ERROR =
+ "f2b0661a-9114-4b1b-9add-a8d338f9c054";
+
+ /**
+ * Experiment flag to enable bypassing EAP-AKA authentication for Slice Purchase activities.
+ * The device will accept any challenge from the entitlement server and return a predefined
+ * string as a response.
+ *
+ * This flag should be enabled for testing only.
+ */
+ public static final String BYPASS_EAP_AKA_AUTH_FOR_SLICE_PURCHASE_ENABLED =
+ "bypass_eap_aka_auth_for_slice_purchase_enabled";
+
+ @NonNull private final Phone mPhone;
+ @NonNull private final ServiceEntitlement mServiceEntitlement;
+
+ public PremiumNetworkEntitlementApi(@NonNull Phone phone,
+ @NonNull PersistableBundle carrierConfig) {
+ mPhone = phone;
+ if (isBypassEapAkaAuthForSlicePurchaseEnabled()) {
+ mServiceEntitlement =
+ new ServiceEntitlement(
+ mPhone.getContext(),
+ getEntitlementServerCarrierConfig(carrierConfig),
+ mPhone.getSubId(),
+ true,
+ DEFAULT_EAP_AKA_RESPONSE);
+ } else {
+ mServiceEntitlement =
+ new ServiceEntitlement(
+ mPhone.getContext(),
+ getEntitlementServerCarrierConfig(carrierConfig),
+ mPhone.getSubId());
+ }
+ }
+
+ /**
+ * Returns premium network slice entitlement check result from carrier API (over network),
+ * or {@code null} on unrecoverable network issue or malformed server response.
+ * This is blocking call sending HTTP request and should not be called on main thread.
+ */
+ @Nullable public PremiumNetworkEntitlementResponse checkEntitlementStatus(
+ @TelephonyManager.PremiumCapability int capability) {
+ Log.d(TAG, "checkEntitlementStatus subId=" + mPhone.getSubId());
+ ServiceEntitlementRequest.Builder requestBuilder = ServiceEntitlementRequest.builder();
+ // Set fake device info to avoid leaking
+ requestBuilder.setTerminalVendor("vendorX");
+ requestBuilder.setTerminalModel("modelY");
+ requestBuilder.setTerminalSoftwareVersion("versionZ");
+ requestBuilder.setAcceptContentType(ServiceEntitlementRequest.ACCEPT_CONTENT_TYPE_JSON);
+ requestBuilder.setBoostType(getBoostTypeFromPremiumCapability(capability));
+ ServiceEntitlementRequest request = requestBuilder.build();
+ PremiumNetworkEntitlementResponse premiumNetworkEntitlementResponse =
+ new PremiumNetworkEntitlementResponse();
+
+ String response = null;
+ try {
+ response = mServiceEntitlement.queryEntitlementStatus(
+ ServiceEntitlement.APP_DATA_PLAN_BOOST,
+ request);
+ } catch (ServiceEntitlementException e) {
+ Log.e(TAG, "queryEntitlementStatus failed", e);
+ reportAnomaly(UUID_ENTITLEMENT_CHECK_UNEXPECTED_ERROR,
+ "checkEntitlementStatus failed with ServiceEntitlementException");
+ }
+ if (response == null) {
+ return null;
+ }
+ try {
+ JSONObject jsonAuthResponse = new JSONObject(response);
+ String entitlementStatus = null;
+ String provisionStatus = null;
+ if (jsonAuthResponse.has(ServiceEntitlement.APP_DATA_PLAN_BOOST)) {
+ JSONObject jsonToken = jsonAuthResponse.getJSONObject(
+ ServiceEntitlement.APP_DATA_PLAN_BOOST);
+ if (jsonToken.has(ENTITLEMENT_STATUS_KEY)) {
+ entitlementStatus = jsonToken.getString(ENTITLEMENT_STATUS_KEY);
+ if (entitlementStatus == null) {
+ return null;
+ }
+ premiumNetworkEntitlementResponse.mEntitlementStatus =
+ Integer.parseInt(entitlementStatus);
+ }
+ if (jsonToken.has(PROVISION_STATUS_KEY)) {
+ provisionStatus = jsonToken.getString(PROVISION_STATUS_KEY);
+ if (provisionStatus != null) {
+ premiumNetworkEntitlementResponse.mProvisionStatus =
+ Integer.parseInt(provisionStatus);
+ }
+ }
+ if (jsonToken.has(SERVICE_FLOW_URL_KEY)) {
+ premiumNetworkEntitlementResponse.mServiceFlowURL =
+ jsonToken.getString(SERVICE_FLOW_URL_KEY);
+ }
+ if (jsonToken.has(SERVICE_FLOW_USERDATA_KEY)) {
+ premiumNetworkEntitlementResponse.mServiceFlowUserData =
+ jsonToken.getString(SERVICE_FLOW_USERDATA_KEY);
+ }
+ } else {
+ Log.e(TAG, "queryEntitlementStatus failed with no app");
+ }
+ } catch (JSONException e) {
+ Log.e(TAG, "queryEntitlementStatus failed", e);
+ reportAnomaly(UUID_ENTITLEMENT_CHECK_UNEXPECTED_ERROR,
+ "checkEntitlementStatus failed with JSONException");
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "queryEntitlementStatus failed", e);
+ reportAnomaly(UUID_ENTITLEMENT_CHECK_UNEXPECTED_ERROR,
+ "checkEntitlementStatus failed with NumberFormatException");
+ }
+
+ return premiumNetworkEntitlementResponse;
+ }
+
+ private void reportAnomaly(@NonNull String uuid, @NonNull String log) {
+ AnomalyReporter.reportAnomaly(UUID.fromString(uuid), log);
+ }
+
+ /**
+ * Returns entitlement server url from the given carrier configs or a default empty string
+ * if it is not available.
+ */
+ @NonNull public static String getEntitlementServerUrl(
+ @NonNull PersistableBundle carrierConfig) {
+ return carrierConfig.getString(
+ CarrierConfigManager.ImsServiceEntitlement.KEY_ENTITLEMENT_SERVER_URL_STRING,
+ "");
+ }
+
+ @NonNull private CarrierConfig getEntitlementServerCarrierConfig(
+ @NonNull PersistableBundle carrierConfig) {
+ String entitlementServiceUrl = getEntitlementServerUrl(carrierConfig);
+ return CarrierConfig.builder().setServerUrl(entitlementServiceUrl).build();
+ }
+
+ private boolean isBypassEapAkaAuthForSlicePurchaseEnabled() {
+ return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TELEPHONY,
+ BYPASS_EAP_AKA_AUTH_FOR_SLICE_PURCHASE_ENABLED, false);
+ }
+
+ @NonNull private String getBoostTypeFromPremiumCapability(
+ @TelephonyManager.PremiumCapability int capability) {
+ if (capability == TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY) {
+ return "0" /* REALTIME_INTERACTIVE_TRAFFIC */;
+ }
+ return "";
+ }
+}
diff --git a/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java b/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java
new file mode 100644
index 0000000..242ca69
--- /dev/null
+++ b/src/com/android/phone/slice/PremiumNetworkEntitlementResponse.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.slice;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+/**
+ * Response class containing the entitlement status, provisioning status, and service flow URL
+ * for premium network entitlement checks.
+ */
+public class PremiumNetworkEntitlementResponse {
+ public static final int PREMIUM_NETWORK_ENTITLEMENT_STATUS_DISABLED = 0;
+ public static final int PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED = 1;
+ public static final int PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCOMPATIBLE = 2;
+ public static final int PREMIUM_NETWORK_ENTITLEMENT_STATUS_PROVISIONING = 3;
+ public static final int PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED = 4;
+
+ @IntDef(prefix = {"PREMIUM_NETWORK_ENTITLEMENT_STATUS_"}, value = {
+ PREMIUM_NETWORK_ENTITLEMENT_STATUS_DISABLED,
+ PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED,
+ PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCOMPATIBLE,
+ PREMIUM_NETWORK_ENTITLEMENT_STATUS_PROVISIONING,
+ PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED
+ })
+ public @interface PremiumNetworkEntitlementStatus {}
+
+ public static final int PREMIUM_NETWORK_PROVISION_STATUS_NOT_PROVISIONED = 0;
+ public static final int PREMIUM_NETWORK_PROVISION_STATUS_PROVISIONED = 1;
+ public static final int PREMIUM_NETWORK_PROVISION_STATUS_NOT_AVAILABLE = 2;
+ public static final int PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS = 3;
+
+ @IntDef(prefix = {"PREMIUM_NETWORK_PROVISION_STATUS_"}, value = {
+ PREMIUM_NETWORK_PROVISION_STATUS_NOT_PROVISIONED,
+ PREMIUM_NETWORK_PROVISION_STATUS_PROVISIONED,
+ PREMIUM_NETWORK_PROVISION_STATUS_NOT_AVAILABLE,
+ PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS
+ })
+ public @interface PremiumNetworkProvisionStatus {}
+
+ @PremiumNetworkEntitlementStatus public int mEntitlementStatus;
+ @PremiumNetworkProvisionStatus public int mProvisionStatus;
+ @NonNull public String mServiceFlowURL;
+ @NonNull public String mServiceFlowUserData;
+
+ /**
+ * @return {@code true} if the premium network is provisioned and {@code false} otherwise.
+ */
+ public boolean isProvisioned() {
+ return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_PROVISIONED
+ || mEntitlementStatus == PREMIUM_NETWORK_ENTITLEMENT_STATUS_ENABLED
+ || mEntitlementStatus == PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCLUDED;
+ }
+
+ /**
+ * @return {@code true} if provisioning the premium network is in progress and
+ * {@code false} otherwise.
+ */
+ public boolean isProvisioningInProgress() {
+ return mProvisionStatus == PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS
+ || mEntitlementStatus == PREMIUM_NETWORK_ENTITLEMENT_STATUS_PROVISIONING;
+ }
+
+ /**
+ * @return {@code true} if the premium network capability is allowed and
+ * {@code false} otherwise.
+ */
+ public boolean isPremiumNetworkCapabilityAllowed() {
+ switch (mEntitlementStatus) {
+ case PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCOMPATIBLE:
+ return false;
+ }
+ switch (mProvisionStatus) {
+ case PREMIUM_NETWORK_PROVISION_STATUS_NOT_AVAILABLE:
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/phone/slice/SlicePurchaseController.java b/src/com/android/phone/slice/SlicePurchaseController.java
new file mode 100644
index 0000000..e36325e
--- /dev/null
+++ b/src/com/android/phone/slice/SlicePurchaseController.java
@@ -0,0 +1,1090 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.slice;
+
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.net.ConnectivityManager;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.provider.DeviceConfig;
+import android.sysprop.TelephonyProperties;
+import android.telephony.AnomalyReporter;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.data.NetworkSliceInfo;
+import android.telephony.data.NetworkSlicingConfig;
+import android.text.TextUtils;
+import android.util.Log;
+import android.webkit.URLUtil;
+import android.webkit.WebView;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.Phone;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.time.format.DateTimeParseException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * The SlicePurchaseController controls the purchase and availability of all cellular premium
+ * capabilities. Applications can check whether premium capabilities are available by calling
+ * {@link TelephonyManager#isPremiumCapabilityAvailableForPurchase(int)}. If this returns true,
+ * they can then call {@link TelephonyManager#purchasePremiumCapability(int, Executor, Consumer)}
+ * to purchase the premium capability. If all conditions are met, a notification will be displayed
+ * to the user prompting them to purchase the premium capability. If the user confirms on the
+ * notification, a {@link WebView} will open that allows the user to purchase the premium capability
+ * from the carrier. If the purchase is successful, the premium capability will be available for
+ * all applications to request through {@link ConnectivityManager#requestNetwork}.
+ */
+public class SlicePurchaseController extends Handler {
+ @NonNull private static final String TAG = "SlicePurchaseController";
+
+ /** Unknown failure code. */
+ public static final int FAILURE_CODE_UNKNOWN = 0;
+ /** Performance boost purchase failed because the carrier URL is unavailable. */
+ public static final int FAILURE_CODE_CARRIER_URL_UNAVAILABLE = 1;
+ /** Performance boost purchase failed because the server is unreachable. */
+ public static final int FAILURE_CODE_SERVER_UNREACHABLE = 2;
+ /** Performance boost purchase failed because user authentication failed. */
+ public static final int FAILURE_CODE_AUTHENTICATION_FAILED = 3;
+ /** Performance boost purchase failed because the payment failed. */
+ public static final int FAILURE_CODE_PAYMENT_FAILED = 4;
+
+ /**
+ * Failure codes that the carrier website can return when a premium capability purchase fails.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "FAILURE_CODE_" }, value = {
+ FAILURE_CODE_UNKNOWN,
+ FAILURE_CODE_CARRIER_URL_UNAVAILABLE,
+ FAILURE_CODE_SERVER_UNREACHABLE,
+ FAILURE_CODE_AUTHENTICATION_FAILED,
+ FAILURE_CODE_PAYMENT_FAILED})
+ public @interface FailureCode {}
+
+ /** Value for an invalid premium capability. */
+ public static final int PREMIUM_CAPABILITY_INVALID = -1;
+
+ /** Asset URL for the slice_purchase_test.html file. */
+ public static final String SLICE_PURCHASE_TEST_FILE =
+ "file:///android_asset/slice_purchase_test.html";
+
+ /** Purchasing the premium capability is no longer throttled. */
+ private static final int EVENT_PURCHASE_UNTHROTTLED = 1;
+ /** Slicing config changed. */
+ private static final int EVENT_SLICING_CONFIG_CHANGED = 2;
+ /** Start slice purchase application. */
+ private static final int EVENT_START_SLICE_PURCHASE_APP = 3;
+ /**
+ * Premium capability was not purchased within the timeout specified by
+ * {@link CarrierConfigManager#KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG}.
+ */
+ private static final int EVENT_PURCHASE_TIMEOUT = 4;
+ /**
+ * Network did not set up the slicing configuration within the timeout specified by
+ * {@link CarrierConfigManager#KEY_PREMIUM_CAPABILITY_NETWORK_SETUP_TIME_MILLIS_LONG}.
+ */
+ private static final int EVENT_SETUP_TIMEOUT = 5;
+ /** Device config changed. */
+ private static final int EVENT_DEVICE_CONFIG_CHANGED = 6;
+
+ /** UUID to report an anomaly when a premium capability is throttled twice in a row. */
+ private static final String UUID_CAPABILITY_THROTTLED_TWICE =
+ "15574927-e2e2-4593-99d4-2f340d22b383";
+ /** UUID to report an anomaly when receiving an invalid phone ID. */
+ private static final String UUID_INVALID_PHONE_ID = "ced79f1a-8ac0-4260-8cf3-08b54c0494f3";
+ /** UUID to report an anomaly when receiving an unknown action. */
+ private static final String UUID_UNKNOWN_ACTION = "0197efb0-dab1-4b0a-abaf-ac9336ec7923";
+ /** UUID to report an anomaly when receiving an unknown failure code with a non-empty reason. */
+ private static final String UUID_UNKNOWN_FAILURE_CODE = "76943b23-4415-400c-9855-b534fc4fc62c";
+ /**
+ * UUID to report an anomaly when the network fails to set up a slicing configuration after
+ * the user purchases a premium capability.
+ */
+ private static final String UUID_NETWORK_SETUP_FAILED = "12eeffbf-08f8-40ed-9a00-d344199552fc";
+
+ /**
+ * Action to start the slice purchase application and display the
+ * performance boost notification.
+ */
+ public static final String ACTION_START_SLICE_PURCHASE_APP =
+ "com.android.phone.slice.action.START_SLICE_PURCHASE_APP";
+ /** Action indicating the premium capability purchase was not completed in time. */
+ public static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_TIMEOUT =
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_TIMEOUT";
+ /** Action indicating the performance boost notification or WebView was canceled. */
+ private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_CANCELED =
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_CANCELED";
+ /** Action indicating a carrier error prevented premium capability purchase. */
+ private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_CARRIER_ERROR =
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_CARRIER_ERROR";
+ /**
+ * Action indicating a Telephony or slice purchase application error prevented premium
+ * capability purchase.
+ */
+ private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_REQUEST_FAILED =
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_REQUEST_FAILED";
+ /** Action indicating the purchase request was not made on the default data subscription. */
+ private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION =
+ "com.android.phone.slice.action."
+ + "SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION";
+ /** Action indicating the purchase request was successful. */
+ private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS =
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_SUCCESS";
+ /**
+ * Action indicating the slice purchase application showed the performance boost notification.
+ */
+ private static final String ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATION_SHOWN =
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_NOTIFICATION_SHOWN";
+
+ /** Extra for the phone index to send to the slice purchase application. */
+ public static final String EXTRA_PHONE_ID = "com.android.phone.slice.extra.PHONE_ID";
+ /** Extra for the subscription ID to send to the slice purchase application. */
+ public static final String EXTRA_SUB_ID = "com.android.phone.slice.extra.SUB_ID";
+ /**
+ * Extra for the requested premium capability to purchase from the slice purchase application.
+ */
+ public static final String EXTRA_PREMIUM_CAPABILITY =
+ "com.android.phone.slice.extra.PREMIUM_CAPABILITY";
+ /** Extra for the carrier URL to display to the user to allow premium capability purchase. */
+ public static final String EXTRA_PURCHASE_URL = "com.android.phone.slice.extra.PURCHASE_URL";
+ /** Extra for the duration of the purchased premium capability. */
+ public static final String EXTRA_PURCHASE_DURATION =
+ "com.android.phone.slice.extra.PURCHASE_DURATION";
+ /** Extra for the {@link FailureCode} why the premium capability purchase failed. */
+ public static final String EXTRA_FAILURE_CODE = "com.android.phone.slice.extra.FAILURE_CODE";
+ /** Extra for the human-readable reason why the premium capability purchase failed. */
+ public static final String EXTRA_FAILURE_REASON =
+ "com.android.phone.slice.extra.FAILURE_REASON";
+ /**
+ * Extra for the user's carrier.
+ */
+ public static final String EXTRA_CARRIER = "com.android.phone.slice.extra.CARRIER";
+ /**
+ * Extra for the canceled PendingIntent that the slice purchase application can send as a
+ * response if the performance boost notification or WebView was canceled by the user.
+ * Sends {@link #ACTION_SLICE_PURCHASE_APP_RESPONSE_CANCELED}.
+ */
+ public static final String EXTRA_INTENT_CANCELED =
+ "com.android.phone.slice.extra.INTENT_CANCELED";
+ /**
+ * Extra for the carrier error PendingIntent that the slice purchase application can send as a
+ * response if the premium capability purchase request failed due to a carrier error.
+ * Sends {@link #ACTION_SLICE_PURCHASE_APP_RESPONSE_CARRIER_ERROR}.
+ * Sender can modify the intent to specify the failure code and reason for failure with
+ * {@link #EXTRA_FAILURE_CODE} and {@link #EXTRA_FAILURE_REASON}.
+ */
+ public static final String EXTRA_INTENT_CARRIER_ERROR =
+ "com.android.phone.slice.extra.INTENT_CARRIER_ERROR";
+ /**
+ * Extra for the request failed PendingIntent that the slice purchase application can send as a
+ * response if the premium capability purchase request failed due to an error in Telephony or
+ * the slice purchase application.
+ * Sends {@link #ACTION_SLICE_PURCHASE_APP_RESPONSE_REQUEST_FAILED}.
+ */
+ public static final String EXTRA_INTENT_REQUEST_FAILED =
+ "com.android.phone.slice.extra.INTENT_REQUEST_FAILED";
+ /**
+ * Extra for the not-default data subscription ID PendingIntent that the slice purchase
+ * application can send as a response if the premium capability purchase request failed because
+ * it was not requested on the default data subscription.
+ * Sends {@link #ACTION_SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION}.
+ */
+ public static final String EXTRA_INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION =
+ "com.android.phone.slice.extra.INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION";
+ /**
+ * Extra for the success PendingIntent that the slice purchase application can send as a
+ * response if the premium capability purchase request was successful.
+ * Sends {@link #ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS}.
+ * Sender can modify the intent to specify a purchase duration with
+ * {@link #EXTRA_PURCHASE_DURATION}.
+ */
+ public static final String EXTRA_INTENT_SUCCESS =
+ "com.android.phone.slice.extra.INTENT_SUCCESS";
+ /**
+ * Extra for the PendingIntent that the slice purchase application can send to indicate
+ * that it displayed the performance boost notification to the user.
+ * Sends {@link #ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATION_SHOWN}.
+ */
+ public static final String EXTRA_INTENT_NOTIFICATION_SHOWN =
+ "com.android.phone.slice.extra.NOTIFICATION_SHOWN";
+
+ /** Component name for the SlicePurchaseBroadcastReceiver. */
+ private static final ComponentName SLICE_PURCHASE_APP_COMPONENT_NAME =
+ ComponentName.unflattenFromString(
+ "com.android.carrierdefaultapp/.SlicePurchaseBroadcastReceiver");
+
+ /** Shared preference name for performance boost notification preferences. */
+ private static final String PERFORMANCE_BOOST_NOTIFICATION_PREFERENCES =
+ "performance_boost_notification_preferences";
+ /** Shared preference key for daily count of performance boost notifications. */
+ private static final String KEY_DAILY_NOTIFICATION_COUNT = "daily_notification_count";
+ /** Shared preference key for monthly count of performance boost notifications. */
+ private static final String KEY_MONTHLY_NOTIFICATION_COUNT = "monthly_notification_count";
+ /** DeviceConfig key for whether the slicing upsell feature is enabled. */
+ private static final String KEY_ENABLE_SLICING_UPSELL = "enable_slicing_upsell";
+ /**
+ * Shared preference key for the date the daily or monthly counts of performance boost
+ * notifications were last reset.
+ * A String with ISO-8601 format {@code YYYY-MM-DD}, from {@link LocalDate#toString}.
+ * For example, if the count was last updated on December 25, 2020, this would be `2020-12-25`.
+ */
+ private static final String KEY_NOTIFICATION_COUNT_LAST_RESET_DATE =
+ "notification_count_last_reset_date";
+
+ /** Map of phone ID -> SlicePurchaseController instances. */
+ @NonNull private static final Map<Integer, SlicePurchaseController> sInstances =
+ new HashMap<>();
+
+ /** The Phone instance used to create the SlicePurchaseController. */
+ @NonNull private final Phone mPhone;
+ /** The set of capabilities that are pending network setup. */
+ @NonNull private final Set<Integer> mPendingSetupCapabilities = new HashSet<>();
+ /** The set of throttled capabilities. */
+ @NonNull private final Set<Integer> mThrottledCapabilities = new HashSet<>();
+ /** A map of pending capabilities to the onComplete message for the purchase request. */
+ @NonNull private final Map<Integer, Message> mPendingPurchaseCapabilities = new HashMap<>();
+ /**
+ * A map of capabilities to the SlicePurchaseControllerBroadcastReceiver to handle
+ * slice purchase application responses.
+ */
+ @NonNull private final Map<Integer, SlicePurchaseControllerBroadcastReceiver>
+ mSlicePurchaseControllerBroadcastReceivers = new HashMap<>();
+ /** The current network slicing configuration. */
+ @Nullable private NetworkSlicingConfig mSlicingConfig;
+ /** Premium network entitlement query API. */
+ @NonNull private final PremiumNetworkEntitlementApi mPremiumNetworkEntitlementApi;
+ /** LocalDate to use when resetting notification counts. {@code null} except when testing. */
+ @Nullable private LocalDate mLocalDate;
+ /** The number of times the performance boost notification has been shown today. */
+ private int mDailyCount;
+ /** The number of times the performance boost notification has been shown this month. */
+ private int mMonthlyCount;
+ /** {@code true} if the slicing upsell feature is enabled and {@code false} otherwise. */
+ private boolean mIsSlicingUpsellEnabled;
+
+ /**
+ * BroadcastReceiver to receive responses from the slice purchase application.
+ */
+ private class SlicePurchaseControllerBroadcastReceiver extends BroadcastReceiver {
+ @TelephonyManager.PremiumCapability private final int mCapability;
+
+ /**
+ * Create a SlicePurchaseControllerBroadcastReceiver for the given capability
+ *
+ * @param capability The requested capability to listen to response for.
+ */
+ SlicePurchaseControllerBroadcastReceiver(
+ @TelephonyManager.PremiumCapability int capability) {
+ mCapability = capability;
+ }
+
+ /**
+ * Process responses from the slice purchase application.
+ *
+ * @param context The Context in which the receiver is running.
+ * @param intent The Intent being received.
+ */
+ @Override
+ public void onReceive(@NonNull Context context, @NonNull Intent intent) {
+ String action = intent.getAction();
+ logd("SlicePurchaseControllerBroadcastReceiver("
+ + TelephonyManager.convertPremiumCapabilityToString(mCapability)
+ + ") received action: " + action);
+ int phoneId = intent.getIntExtra(EXTRA_PHONE_ID,
+ SubscriptionManager.INVALID_PHONE_INDEX);
+ int capability = intent.getIntExtra(EXTRA_PREMIUM_CAPABILITY,
+ PREMIUM_CAPABILITY_INVALID);
+ if (SlicePurchaseController.getInstance(phoneId) == null) {
+ reportAnomaly(UUID_INVALID_PHONE_ID, "SlicePurchaseControllerBroadcastReceiver( "
+ + TelephonyManager.convertPremiumCapabilityToString(mCapability)
+ + ") received invalid phoneId: " + phoneId);
+ return;
+ } else if (capability != mCapability) {
+ logd("SlicePurchaseControllerBroadcastReceiver("
+ + TelephonyManager.convertPremiumCapabilityToString(mCapability)
+ + ") ignoring intent for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ return;
+ }
+ switch (action) {
+ case ACTION_SLICE_PURCHASE_APP_RESPONSE_CANCELED: {
+ logd("Slice purchase application canceled for capability: "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ SlicePurchaseController.getInstance(phoneId)
+ .handlePurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED,
+ true);
+ break;
+ }
+ case ACTION_SLICE_PURCHASE_APP_RESPONSE_CARRIER_ERROR: {
+ int failureCode = intent.getIntExtra(EXTRA_FAILURE_CODE, FAILURE_CODE_UNKNOWN);
+ String failureReason = intent.getStringExtra(EXTRA_FAILURE_REASON);
+ SlicePurchaseController.getInstance(phoneId).onCarrierError(
+ capability, failureCode, failureReason);
+ break;
+ }
+ case ACTION_SLICE_PURCHASE_APP_RESPONSE_REQUEST_FAILED: {
+ logd("Purchase premium capability request failed for capability: "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ SlicePurchaseController.getInstance(phoneId)
+ .handlePurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_REQUEST_FAILED,
+ false);
+ break;
+ }
+ case ACTION_SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION: {
+ logd("Purchase premium capability request was not made on the default data "
+ + "subscription for capability: "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ SlicePurchaseController.getInstance(phoneId)
+ .handlePurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION,
+ false);
+ break;
+ }
+ case ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS: {
+ long duration = intent.getLongExtra(EXTRA_PURCHASE_DURATION, 0);
+ SlicePurchaseController.getInstance(phoneId).onCarrierSuccess(
+ capability, duration);
+ break;
+ }
+ case ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATION_SHOWN: {
+ SlicePurchaseController.getInstance(phoneId).onNotificationShown();
+ break;
+ }
+ default:
+ reportAnomaly(UUID_UNKNOWN_ACTION, "SlicePurchaseControllerBroadcastReceiver("
+ + TelephonyManager.convertPremiumCapabilityToString(mCapability)
+ + ") received unknown action: " + action);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Get the static SlicePurchaseController instance for the given phone or create one if it
+ * doesn't exist.
+ *
+ * @param phone The Phone to get the SlicePurchaseController for.
+ * @return The static SlicePurchaseController instance.
+ */
+ @NonNull public static synchronized SlicePurchaseController getInstance(@NonNull Phone phone) {
+ // TODO: Add listeners for multi sim setting changed (maybe carrier config changed too)
+ // that dismiss notifications and update SlicePurchaseController instance
+ int phoneId = phone.getPhoneId();
+ if (sInstances.get(phoneId) == null) {
+ HandlerThread handlerThread = new HandlerThread("SlicePurchaseController");
+ handlerThread.start();
+ sInstances.put(phoneId, new SlicePurchaseController(phone, handlerThread.getLooper()));
+ }
+ return sInstances.get(phoneId);
+ }
+
+ /**
+ * Get the static SlicePurchaseController instance for the given phone ID if it exists.
+ *
+ * @param phoneId The phone ID to get the SlicePurchaseController for.
+ * @return The static SlicePurchaseController instance or
+ * {@code null} if it hasn't been created yet.
+ */
+ @Nullable private static SlicePurchaseController getInstance(int phoneId) {
+ return sInstances.get(phoneId);
+ }
+
+ /**
+ * Create a SlicePurchaseController for the given phone on the given looper.
+ *
+ * @param phone The Phone to create the SlicePurchaseController for.
+ * @param looper The Looper to run the SlicePurchaseController on.
+ */
+ @VisibleForTesting
+ public SlicePurchaseController(@NonNull Phone phone, @NonNull Looper looper) {
+ super(looper);
+ mPhone = phone;
+ // TODO: Create a cached value for slicing config in DataIndication and initialize here
+ mPhone.mCi.registerForSlicingConfigChanged(this, EVENT_SLICING_CONFIG_CHANGED, null);
+ mPremiumNetworkEntitlementApi =
+ new PremiumNetworkEntitlementApi(mPhone, getCarrierConfigs());
+ mIsSlicingUpsellEnabled = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_TELEPHONY, KEY_ENABLE_SLICING_UPSELL, false);
+ DeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_TELEPHONY, this::post,
+ properties -> {
+ if (TextUtils.equals(DeviceConfig.NAMESPACE_TELEPHONY,
+ properties.getNamespace())) {
+ sendEmptyMessage(EVENT_DEVICE_CONFIG_CHANGED);
+ }
+ });
+ updateNotificationCounts();
+ }
+
+ /**
+ * Set the LocalDate to use for resetting daily and monthly notification counts.
+ *
+ * @param localDate The LocalDate instance to use.
+ */
+ @VisibleForTesting
+ public void setLocalDate(@NonNull LocalDate localDate) {
+ mLocalDate = localDate;
+ }
+
+ @Override
+ public void handleMessage(@NonNull Message msg) {
+ switch (msg.what) {
+ case EVENT_PURCHASE_UNTHROTTLED: {
+ int capability = (int) msg.obj;
+ logd("EVENT_PURCHASE_UNTHROTTLED: for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ mThrottledCapabilities.remove(capability);
+ break;
+ }
+ case EVENT_SLICING_CONFIG_CHANGED: {
+ AsyncResult ar = (AsyncResult) msg.obj;
+ NetworkSlicingConfig config = (NetworkSlicingConfig) ar.result;
+ logd("EVENT_SLICING_CONFIG_CHANGED: from " + mSlicingConfig + " to " + config);
+ mSlicingConfig = config;
+ onSlicingConfigChanged();
+ break;
+ }
+ case EVENT_START_SLICE_PURCHASE_APP: {
+ int capability = (int) msg.obj;
+ logd("EVENT_START_SLICE_PURCHASE_APP: "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ onStartSlicePurchaseApplication(capability);
+ break;
+ }
+ case EVENT_PURCHASE_TIMEOUT: {
+ int capability = (int) msg.obj;
+ logd("EVENT_PURCHASE_TIMEOUT: for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ onTimeout(capability);
+ break;
+ }
+ case EVENT_SETUP_TIMEOUT:
+ int capability = (int) msg.obj;
+ logd("EVENT_SETUP_TIMEOUT: for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ onSetupTimeout(capability);
+ break;
+ case EVENT_DEVICE_CONFIG_CHANGED:
+ boolean isSlicingUpsellEnabled = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_TELEPHONY, KEY_ENABLE_SLICING_UPSELL, false);
+ if (isSlicingUpsellEnabled != mIsSlicingUpsellEnabled) {
+ logd("EVENT_DEVICE_CONFIG_CHANGED: from " + mIsSlicingUpsellEnabled + " to "
+ + isSlicingUpsellEnabled);
+ mIsSlicingUpsellEnabled = isSlicingUpsellEnabled;
+ }
+ break;
+ default:
+ loge("Unknown event: " + msg.obj);
+ }
+ }
+
+ /**
+ * Check whether the given premium capability is available for purchase from the carrier.
+ *
+ * @param capability The premium capability to check.
+ * @return Whether the given premium capability is available to purchase.
+ */
+ public boolean isPremiumCapabilityAvailableForPurchase(
+ @TelephonyManager.PremiumCapability int capability) {
+ if (!arePremiumCapabilitiesSupportedByDevice()) {
+ logd("Premium capabilities unsupported by the device.");
+ return false;
+ }
+ if (!isPremiumCapabilitySupportedByCarrier(capability)) {
+ logd("Premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " unsupported by the carrier.");
+ return false;
+ }
+ if (!isDefaultDataSub()) {
+ logd("Premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " unavailable on the non-default data subscription.");
+ return false;
+ }
+ logd("Premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " is available for purchase.");
+ return true;
+ }
+
+ /**
+ * Purchase the given premium capability from the carrier.
+ *
+ * @param capability The premium capability to purchase.
+ * @param onComplete The callback message to send when the purchase request is complete.
+ */
+ public synchronized void purchasePremiumCapability(
+ @TelephonyManager.PremiumCapability int capability, @NonNull Message onComplete) {
+ logd("purchasePremiumCapability: "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ // Check whether the premium capability can be purchased.
+ if (!arePremiumCapabilitiesSupportedByDevice()) {
+ sendPurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_FEATURE_NOT_SUPPORTED,
+ onComplete);
+ return;
+ }
+ if (!isPremiumCapabilitySupportedByCarrier(capability)) {
+ sendPurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED,
+ onComplete);
+ return;
+ }
+ if (!isDefaultDataSub()) {
+ sendPurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION,
+ onComplete);
+ return;
+ }
+ if (isSlicingConfigActive(capability)) {
+ sendPurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED,
+ onComplete);
+ return;
+ }
+ if (mPendingSetupCapabilities.contains(capability)) {
+ sendPurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP,
+ onComplete);
+ return;
+ }
+ if (mThrottledCapabilities.contains(capability)) {
+ sendPurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED,
+ onComplete);
+ return;
+ }
+ if (!isNetworkAvailable()) {
+ sendPurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NETWORK_NOT_AVAILABLE,
+ onComplete);
+ return;
+ }
+
+ if (mPendingPurchaseCapabilities.containsKey(capability)) {
+ sendPurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS,
+ onComplete);
+ return;
+ }
+
+ // All state checks passed. Mark purchase pending and start the slice purchase application.
+ // Process through the handler since this method is synchronized.
+ mPendingPurchaseCapabilities.put(capability, onComplete);
+ sendMessage(obtainMessage(EVENT_START_SLICE_PURCHASE_APP, capability));
+ }
+
+ private void sendPurchaseResult(@TelephonyManager.PremiumCapability int capability,
+ @TelephonyManager.PurchasePremiumCapabilityResult int result,
+ @NonNull Message onComplete) {
+ // Send the onComplete message with the purchase result.
+ logd("Purchase result for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + ": " + TelephonyManager.convertPurchaseResultToString(result));
+ AsyncResult.forMessage(onComplete, result, null);
+ onComplete.sendToTarget();
+ }
+
+ private void handlePurchaseResult(
+ @TelephonyManager.PremiumCapability int capability,
+ @TelephonyManager.PurchasePremiumCapabilityResult int result, boolean throttle) {
+ SlicePurchaseControllerBroadcastReceiver receiver =
+ mSlicePurchaseControllerBroadcastReceivers.remove(capability);
+ if (receiver != null) {
+ mPhone.getContext().unregisterReceiver(receiver);
+ }
+ removeMessages(EVENT_PURCHASE_TIMEOUT, capability);
+ if (throttle) {
+ throttleCapability(capability, getThrottleDuration(result));
+ }
+ sendPurchaseResult(capability, result, mPendingPurchaseCapabilities.remove(capability));
+ }
+
+ private void throttleCapability(@TelephonyManager.PremiumCapability int capability,
+ long throttleDuration) {
+ // Throttle subsequent requests if necessary.
+ if (!mThrottledCapabilities.contains(capability)) {
+ if (throttleDuration > 0) {
+ logd("Throttle purchase requests for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability) + " for "
+ + TimeUnit.MILLISECONDS.toMinutes(throttleDuration) + " minutes.");
+ mThrottledCapabilities.add(capability);
+ sendMessageDelayed(obtainMessage(EVENT_PURCHASE_UNTHROTTLED, capability),
+ throttleDuration);
+ }
+ } else {
+ reportAnomaly(UUID_CAPABILITY_THROTTLED_TWICE,
+ TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " is already throttled.");
+ }
+ }
+
+ private void onSlicingConfigChanged() {
+ for (int capability : new int[] {TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY}) {
+ if (isSlicingConfigActive(capability) && hasMessages(EVENT_SETUP_TIMEOUT, capability)) {
+ logd("Successfully set up slicing configuration for "
+ + TelephonyManager.convertPremiumCapabilityToString(capability));
+ mPendingSetupCapabilities.remove(capability);
+ removeMessages(EVENT_SETUP_TIMEOUT, capability);
+ }
+ }
+ }
+
+ private void onStartSlicePurchaseApplication(
+ @TelephonyManager.PremiumCapability int capability) {
+ PremiumNetworkEntitlementResponse premiumNetworkEntitlementResponse =
+ mPremiumNetworkEntitlementApi.checkEntitlementStatus(capability);
+
+ // invalid response for entitlement check
+ if (premiumNetworkEntitlementResponse == null) {
+ logd("Invalid response for entitlement check.");
+ handlePurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED, true);
+ return;
+ }
+
+ if (premiumNetworkEntitlementResponse.isProvisioned()) {
+ logd("Entitlement Check: Already provisioned.");
+ handlePurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED, true);
+ return;
+ }
+
+ if (premiumNetworkEntitlementResponse.isProvisioningInProgress()) {
+ logd("Entitlement Check: In Progress");
+ handlePurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS, true);
+ return;
+ }
+
+ if (!premiumNetworkEntitlementResponse.isPremiumNetworkCapabilityAllowed()) {
+ handlePurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED, true);
+ return;
+ }
+
+ String purchaseUrl = getPurchaseUrl(premiumNetworkEntitlementResponse);
+ String carrier = getSimOperator();
+ if (TextUtils.isEmpty(purchaseUrl) || TextUtils.isEmpty(carrier)) {
+ handlePurchaseResult(capability,
+ PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED, false);
+ return;
+ }
+
+ updateNotificationCounts();
+ if (mMonthlyCount >= getCarrierConfigs().getInt(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_MONTHLY_NOTIFICATION_COUNT_INT)
+ || mDailyCount >= getCarrierConfigs().getInt(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_DAILY_NOTIFICATION_COUNT_INT)) {
+ logd("Reached maximum number of performance boost notifications.");
+ handlePurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, false);
+ return;
+ }
+
+ // Start timeout for purchase completion.
+ long timeout = getCarrierConfigs().getLong(CarrierConfigManager
+ .KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG);
+ logd("Start purchase timeout for "
+ + TelephonyManager.convertPremiumCapabilityToString(capability) + " for "
+ + TimeUnit.MILLISECONDS.toMinutes(timeout) + " minutes.");
+ sendMessageDelayed(obtainMessage(EVENT_PURCHASE_TIMEOUT, capability), timeout);
+
+ // Broadcast start intent to start the slice purchase application
+ Intent intent = new Intent(ACTION_START_SLICE_PURCHASE_APP);
+ intent.setComponent(SLICE_PURCHASE_APP_COMPONENT_NAME);
+ intent.putExtra(EXTRA_PHONE_ID, mPhone.getPhoneId());
+ intent.putExtra(EXTRA_SUB_ID, mPhone.getSubId());
+ intent.putExtra(EXTRA_PREMIUM_CAPABILITY, capability);
+ intent.putExtra(EXTRA_PURCHASE_URL, purchaseUrl);
+ intent.putExtra(EXTRA_CARRIER, carrier);
+ intent.putExtra(EXTRA_INTENT_CANCELED, createPendingIntent(
+ ACTION_SLICE_PURCHASE_APP_RESPONSE_CANCELED, capability, false));
+ intent.putExtra(EXTRA_INTENT_CARRIER_ERROR, createPendingIntent(
+ ACTION_SLICE_PURCHASE_APP_RESPONSE_CARRIER_ERROR, capability, true));
+ intent.putExtra(EXTRA_INTENT_REQUEST_FAILED, createPendingIntent(
+ ACTION_SLICE_PURCHASE_APP_RESPONSE_REQUEST_FAILED, capability, false));
+ intent.putExtra(EXTRA_INTENT_NOT_DEFAULT_DATA_SUBSCRIPTION, createPendingIntent(
+ ACTION_SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION, capability,
+ false));
+ intent.putExtra(EXTRA_INTENT_SUCCESS, createPendingIntent(
+ ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS, capability, true));
+ intent.putExtra(EXTRA_INTENT_NOTIFICATION_SHOWN, createPendingIntent(
+ ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATION_SHOWN, capability, false));
+ logd("Broadcasting start intent to SlicePurchaseBroadcastReceiver.");
+ mPhone.getContext().sendBroadcast(intent);
+
+ // Listen for responses from the slice purchase application
+ mSlicePurchaseControllerBroadcastReceivers.put(capability,
+ new SlicePurchaseControllerBroadcastReceiver(capability));
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_CANCELED);
+ filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_CARRIER_ERROR);
+ filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_REQUEST_FAILED);
+ filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION);
+ filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_SUCCESS);
+ filter.addAction(ACTION_SLICE_PURCHASE_APP_RESPONSE_NOTIFICATION_SHOWN);
+ mPhone.getContext().registerReceiver(
+ mSlicePurchaseControllerBroadcastReceivers.get(capability), filter);
+ }
+
+ /**
+ * Get a valid purchase URL from either entitlement response or carrier configs, if one exists.
+ *
+ * @param entitlementResponse The entitlement response to get the purchase URL from.
+ * @return A valid purchase URL or an empty string if one doesn't exist.
+ */
+ @VisibleForTesting
+ @NonNull public String getPurchaseUrl(
+ @NonNull PremiumNetworkEntitlementResponse entitlementResponse) {
+ String purchaseUrl = entitlementResponse.mServiceFlowURL;
+ if (!isUrlValid(purchaseUrl)) {
+ purchaseUrl = getCarrierConfigs().getString(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING);
+ if (!isUrlValid(purchaseUrl)) {
+ purchaseUrl = "";
+ }
+ }
+ return purchaseUrl;
+ }
+
+ /**
+ * Get the SIM operator. This is the carrier name from the SIM rather than from the network,
+ * which will be the same regardless of whether the user is roaming or not.
+ *
+ * @return The operator name from the SIM.
+ */
+ @VisibleForTesting
+ @Nullable public String getSimOperator() {
+ if (mPhone.getPhoneId() < TelephonyProperties.icc_operator_alpha().size()) {
+ return TelephonyProperties.icc_operator_alpha().get(mPhone.getPhoneId());
+ }
+ return null;
+ }
+
+ /**
+ * Create the PendingIntent to allow the slice purchase application to send back responses.
+ *
+ * @param action The action that will be sent for this PendingIntent
+ * @param capability The premium capability that was requested.
+ * @param mutable {@code true} if the PendingIntent should be mutable and
+ * {@code false} if it should be immutable.
+ * @return The PendingIntent for the given action and capability.
+ */
+ @VisibleForTesting
+ @NonNull public PendingIntent createPendingIntent(@NonNull String action,
+ @TelephonyManager.PremiumCapability int capability, boolean mutable) {
+ Intent intent = new Intent(action);
+ intent.putExtra(EXTRA_PHONE_ID, mPhone.getPhoneId());
+ intent.putExtra(EXTRA_PREMIUM_CAPABILITY, capability);
+ intent.setPackage(mPhone.getContext().getPackageName());
+ return PendingIntent.getBroadcast(mPhone.getContext(), capability, intent,
+ PendingIntent.FLAG_CANCEL_CURRENT
+ | (mutable ? PendingIntent.FLAG_MUTABLE : PendingIntent.FLAG_IMMUTABLE));
+ }
+
+ private void onTimeout(@TelephonyManager.PremiumCapability int capability) {
+ logd("onTimeout: " + TelephonyManager.convertPremiumCapabilityToString(capability));
+ // Broadcast timeout intent to clean up the slice purchase notification and activity
+ Intent intent = new Intent(ACTION_SLICE_PURCHASE_APP_RESPONSE_TIMEOUT);
+ intent.setComponent(SLICE_PURCHASE_APP_COMPONENT_NAME);
+ intent.putExtra(EXTRA_PHONE_ID, mPhone.getPhoneId());
+ intent.putExtra(EXTRA_PREMIUM_CAPABILITY, capability);
+ logd("Broadcasting timeout intent to SlicePurchaseBroadcastReceiver.");
+ mPhone.getContext().sendBroadcast(intent);
+
+ handlePurchaseResult(
+ capability, TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT, true);
+ }
+
+ private void onCarrierError(@TelephonyManager.PremiumCapability int capability,
+ @FailureCode int failureCode, @Nullable String failureReason) {
+ logd("Carrier error for capability: "
+ + TelephonyManager.convertPremiumCapabilityToString(capability) + " with code: "
+ + convertFailureCodeToString(failureCode) + " and reason: " + failureReason);
+ if (failureCode == FAILURE_CODE_UNKNOWN && !TextUtils.isEmpty(failureReason)) {
+ reportAnomaly(UUID_UNKNOWN_FAILURE_CODE,
+ "Failure code needs to be added for: " + failureReason);
+ }
+ handlePurchaseResult(capability,
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR, true);
+ }
+
+ private void onCarrierSuccess(@TelephonyManager.PremiumCapability int capability,
+ long duration) {
+ logd("Successfully purchased premium capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability) + (duration > 0
+ ? " for " + TimeUnit.MILLISECONDS.toMinutes(duration) + " minutes." : "."));
+ mPendingSetupCapabilities.add(capability);
+ long setupDuration = getCarrierConfigs().getLong(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_NETWORK_SETUP_TIME_MILLIS_LONG);
+ logd("Waiting " + TimeUnit.MILLISECONDS.toMinutes(setupDuration) + " minutes for the "
+ + "network to set up the slicing configuration.");
+ sendMessageDelayed(obtainMessage(EVENT_SETUP_TIMEOUT, capability), setupDuration);
+ handlePurchaseResult(
+ capability, TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_SUCCESS, false);
+ }
+
+ private void onSetupTimeout(@TelephonyManager.PremiumCapability int capability) {
+ logd("onSetupTimeout: " + TelephonyManager.convertPremiumCapabilityToString(capability));
+ mPendingSetupCapabilities.remove(capability);
+ if (!isSlicingConfigActive(capability)) {
+ reportAnomaly(UUID_NETWORK_SETUP_FAILED,
+ "Failed to set up slicing configuration for capability "
+ + TelephonyManager.convertPremiumCapabilityToString(capability)
+ + " within the time specified.");
+ }
+ }
+
+ private void onNotificationShown() {
+ SharedPreferences sp = mPhone.getContext().getSharedPreferences(
+ PERFORMANCE_BOOST_NOTIFICATION_PREFERENCES, 0);
+ mDailyCount = sp.getInt((KEY_DAILY_NOTIFICATION_COUNT + mPhone.getPhoneId()), 0) + 1;
+ mMonthlyCount = sp.getInt((KEY_MONTHLY_NOTIFICATION_COUNT + mPhone.getPhoneId()), 0) + 1;
+ logd("Performance boost notification was shown " + mDailyCount + " times today and "
+ + mMonthlyCount + " times this month.");
+
+ SharedPreferences.Editor editor = sp.edit();
+ editor.putInt((KEY_DAILY_NOTIFICATION_COUNT + mPhone.getPhoneId()), mDailyCount);
+ editor.putInt((KEY_MONTHLY_NOTIFICATION_COUNT + mPhone.getPhoneId()), mMonthlyCount);
+ editor.apply();
+
+ // Don't call updateNotificationCounts here because it will be called whenever a new
+ // purchase request comes in or when SlicePurchaseController is initialized.
+ }
+
+ /**
+ * Update the current daily and monthly performance boost notification counts.
+ * If it has been at least a day since the last daily reset or at least a month since the last
+ * monthly reset, reset the current daily or monthly notification counts.
+ */
+ @VisibleForTesting
+ public void updateNotificationCounts() {
+ SharedPreferences sp = mPhone.getContext().getSharedPreferences(
+ PERFORMANCE_BOOST_NOTIFICATION_PREFERENCES, 0);
+ mDailyCount = sp.getInt((KEY_DAILY_NOTIFICATION_COUNT + mPhone.getPhoneId()), 0);
+ mMonthlyCount = sp.getInt((KEY_MONTHLY_NOTIFICATION_COUNT + mPhone.getPhoneId()), 0);
+
+ if (mLocalDate == null) {
+ // Standardize to UTC to prevent default time zone dependency
+ mLocalDate = LocalDate.now(ZoneId.of("UTC"));
+ }
+ LocalDate lastLocalDate = LocalDate.of(1, 1, 1);
+ String lastLocalDateString = sp.getString(
+ (KEY_NOTIFICATION_COUNT_LAST_RESET_DATE + mPhone.getPhoneId()), "");
+ if (!TextUtils.isEmpty(lastLocalDateString)) {
+ try {
+ lastLocalDate = LocalDate.parse(lastLocalDateString);
+ } catch (DateTimeParseException e) {
+ loge("Error parsing LocalDate from SharedPreferences: " + e);
+ }
+ }
+ logd("updateNotificationCounts: mDailyCount=" + mDailyCount + ", mMonthlyCount="
+ + mMonthlyCount + ", mLocalDate=" + mLocalDate + ", lastLocalDate="
+ + lastLocalDate);
+
+ boolean resetMonthly = lastLocalDate.getYear() != mLocalDate.getYear()
+ || lastLocalDate.getMonthValue() != mLocalDate.getMonthValue();
+ boolean resetDaily = resetMonthly
+ || lastLocalDate.getDayOfMonth() != mLocalDate.getDayOfMonth();
+ if (resetDaily) {
+ logd("Resetting daily" + (resetMonthly ? " and monthly" : "") + " notification count.");
+ SharedPreferences.Editor editor = sp.edit();
+ if (resetMonthly) {
+ mMonthlyCount = 0;
+ editor.putInt((KEY_MONTHLY_NOTIFICATION_COUNT + mPhone.getPhoneId()),
+ mMonthlyCount);
+ }
+ mDailyCount = 0;
+ editor.putInt((KEY_DAILY_NOTIFICATION_COUNT + mPhone.getPhoneId()), mDailyCount);
+ editor.putString((KEY_NOTIFICATION_COUNT_LAST_RESET_DATE + mPhone.getPhoneId()),
+ mLocalDate.toString());
+ editor.apply();
+ }
+ }
+
+ @Nullable private PersistableBundle getCarrierConfigs() {
+ return mPhone.getContext().getSystemService(CarrierConfigManager.class)
+ .getConfigForSubId(mPhone.getSubId());
+ }
+
+ private long getThrottleDuration(@TelephonyManager.PurchasePremiumCapabilityResult int result) {
+ if (result == TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED
+ || result == TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT) {
+ return getCarrierConfigs().getLong(CarrierConfigManager
+ .KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG);
+ }
+ if (result == TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED
+ || result == TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR) {
+ return getCarrierConfigs().getLong(CarrierConfigManager
+ .KEY_PREMIUM_CAPABILITY_PURCHASE_CONDITION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG);
+ }
+ return 0;
+ }
+
+ private boolean isPremiumCapabilitySupportedByCarrier(
+ @TelephonyManager.PremiumCapability int capability) {
+ int[] supportedCapabilities = getCarrierConfigs().getIntArray(
+ CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY);
+ if (supportedCapabilities == null) {
+ return false;
+ }
+ return Arrays.stream(supportedCapabilities)
+ .anyMatch(supportedCapability -> supportedCapability == capability);
+ }
+
+ private boolean isUrlValid(@Nullable String url) {
+ if (!URLUtil.isValidUrl(url)) {
+ loge("Invalid URL: " + url);
+ return false;
+ }
+ if (URLUtil.isAssetUrl(url) && !url.equals(SLICE_PURCHASE_TEST_FILE)) {
+ loge("Invalid asset: " + url);
+ return false;
+ }
+ try {
+ new URL(url).toURI();
+ } catch (MalformedURLException | URISyntaxException e) {
+ loge("Invalid URI: " + url);
+ return false;
+ }
+ logd("Valid URL: " + url);
+ return true;
+ }
+
+ private boolean arePremiumCapabilitiesSupportedByDevice() {
+ if ((mPhone.getCachedAllowedNetworkTypesBitmask()
+ & TelephonyManager.NETWORK_TYPE_BITMASK_NR) == 0) {
+ return false;
+ }
+ return mIsSlicingUpsellEnabled;
+ }
+
+ private boolean isDefaultDataSub() {
+ return mPhone.getSubId() == SubscriptionManager.getDefaultDataSubscriptionId();
+ }
+
+ private boolean isSlicingConfigActive(@TelephonyManager.PremiumCapability int capability) {
+ if (mSlicingConfig == null) {
+ return false;
+ }
+ int capabilityServiceType = getSliceServiceType(capability);
+ for (NetworkSliceInfo sliceInfo : mSlicingConfig.getSliceInfo()) {
+ if (sliceInfo.getSliceServiceType() == capabilityServiceType
+ && sliceInfo.getStatus() == NetworkSliceInfo.SLICE_STATUS_ALLOWED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @NetworkSliceInfo.SliceServiceType private int getSliceServiceType(
+ @TelephonyManager.PremiumCapability int capability) {
+ if (capability == TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY) {
+ return NetworkSliceInfo.SLICE_SERVICE_TYPE_URLLC;
+ }
+ return NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE;
+ }
+
+ private boolean isNetworkAvailable() {
+ if (mPhone.getServiceState().getDataRoaming()) {
+ logd("Network unavailable because it is roaming.");
+ return false;
+ }
+
+ // TODO (b/251558673): Create a listener for data network type changed to dismiss
+ // notification and activity when the network is no longer available.
+ switch (mPhone.getServiceState().getDataNetworkType()) {
+ case TelephonyManager.NETWORK_TYPE_NR:
+ return true;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ case TelephonyManager.NETWORK_TYPE_LTE_CA:
+ return getCarrierConfigs().getBoolean(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_SUPPORTED_ON_LTE_BOOL);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the failure code {@link FailureCode} as a String.
+ *
+ * @param failureCode The failure code.
+ * @return The failure code as a String.
+ */
+ @NonNull private static String convertFailureCodeToString(@FailureCode int failureCode) {
+ switch (failureCode) {
+ case FAILURE_CODE_UNKNOWN: return "UNKNOWN";
+ case FAILURE_CODE_CARRIER_URL_UNAVAILABLE: return "CARRIER_URL_UNAVAILABLE";
+ case FAILURE_CODE_SERVER_UNREACHABLE: return "SERVER_UNREACHABLE";
+ case FAILURE_CODE_AUTHENTICATION_FAILED: return "AUTHENTICATION_FAILED";
+ case FAILURE_CODE_PAYMENT_FAILED: return "PAYMENT_FAILED";
+ default:
+ return "UNKNOWN(" + failureCode + ")";
+ }
+ }
+
+ private void reportAnomaly(@NonNull String uuid, @NonNull String log) {
+ loge(log);
+ AnomalyReporter.reportAnomaly(UUID.fromString(uuid), log);
+ }
+
+ private void logd(String s) {
+ Log.d(TAG + "-" + mPhone.getPhoneId(), s);
+ }
+
+ private void loge(String s) {
+ Log.e(TAG + "-" + mPhone.getPhoneId(), s);
+ }
+}
diff --git a/src/com/android/phone/utils/CarrierAllowListInfo.java b/src/com/android/phone/utils/CarrierAllowListInfo.java
new file mode 100644
index 0000000..208eff3
--- /dev/null
+++ b/src/com/android/phone/utils/CarrierAllowListInfo.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2023 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.utils;
+
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.telephony.Rlog;
+import android.text.TextUtils;
+
+import com.android.internal.telephony.uicc.IccUtils;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class CarrierAllowListInfo {
+ private static final String LOG_TAG = "CarrierAllowListInfo";
+ private JSONObject mDataJSON;
+ private static final String JSON_CHARSET = "UTF-8";
+ private static final String MESSAGE_DIGEST_ALGORITHM = "SHA1";
+ private static final String CALLER_SHA_1_ID = "callerSHA1Id";
+ private static final String CALLER_CARRIER_ID = "carrierId";
+ public static final int INVALID_CARRIER_ID = -1;
+
+ private static final String CARRIER_RESTRICTION_OPERATOR_REGISTERED_FILE =
+ "CarrierRestrictionOperatorDetails.json";
+
+ private static CarrierAllowListInfo mInstance = null;
+ private Context mContext;
+
+ private CarrierAllowListInfo(Context context) {
+ mContext = context;
+ loadJsonFile(context);
+ }
+
+ public static CarrierAllowListInfo loadInstance(Context context) {
+ if (mInstance == null) {
+ mInstance = new CarrierAllowListInfo(context);
+ }
+ return mInstance;
+ }
+
+ public int validateCallerAndGetCarrierId(String packageName) {
+ CarrierInfo carrierInfo = parseJsonForCallerInfo(packageName);
+ boolean isValid = (carrierInfo != null) && validateCallerSignature(mContext, packageName,
+ carrierInfo.getSHAIdList());
+ return (isValid) ? carrierInfo.getCallerCarrierId() : INVALID_CARRIER_ID;
+ }
+
+ private void loadJsonFile(Context context) {
+ try {
+ String jsonString = getJsonFromAssets(context,
+ CARRIER_RESTRICTION_OPERATOR_REGISTERED_FILE, JSON_CHARSET);
+ if (!TextUtils.isEmpty(jsonString)) {
+ mDataJSON = new JSONObject(jsonString);
+ }
+ } catch (Exception ex) {
+ Rlog.e(LOG_TAG, "CarrierAllowListInfo: JSON file reading exception = " + ex);
+ }
+ }
+
+ /**
+ * Parse the JSON object to fetch the given caller's SHA-Ids and carrierId.
+ */
+ private CarrierInfo parseJsonForCallerInfo(String callerPackage) {
+ try {
+ if (mDataJSON != null && callerPackage != null) {
+ JSONObject callerJSON = mDataJSON.getJSONObject(callerPackage.trim());
+ JSONArray callerJSONArray = callerJSON.getJSONArray(CALLER_SHA_1_ID);
+ int carrierId = callerJSON.getInt(CALLER_CARRIER_ID);
+ List<String> appSignatures = new ArrayList<>();
+ for (int index = 0; index < callerJSONArray.length(); index++) {
+ appSignatures.add((String) callerJSONArray.get(index));
+ }
+ return new CarrierInfo(carrierId, appSignatures);
+ }
+ } catch (JSONException ex) {
+ Rlog.e(LOG_TAG, "getCallerSignatureInfo: JSONException = " + ex);
+ }
+ return null;
+ }
+
+ /**
+ * Read the Json file from the assert folder.
+ *
+ * @param context context
+ * @param fileName JSON file name in assets folder
+ * @param charset JSON file data format
+ * @return JSON file content in string format or null in case of IOException
+ */
+ private static String getJsonFromAssets(Context context, String fileName, String charset) {
+ String jsonStr;
+ try {
+ InputStream ipStream = context.getAssets().open(fileName);
+ int bufSize = ipStream.available();
+ byte[] fileBuffer = new byte[bufSize];
+ ipStream.read(fileBuffer);
+ ipStream.close();
+ jsonStr = new String(fileBuffer, charset);
+ } catch (IOException ex) {
+ Rlog.e(LOG_TAG, "getJsonFromAssets: Exception = " + ex);
+ return null;
+ }
+ return jsonStr;
+ }
+
+ /**
+ * API fetches all the related signatures of the given package from the packageManager
+ * and validate all the signatures.
+ *
+ * @param context context
+ * @param packageName package name of the caller to validate the signatures.
+ * @param allowListSignatures list of signatures to be validated.
+ * @return {@code true} if all the signatures are available with package manager.
+ * {@code false} if any one of the signatures won't match with package manager.
+ */
+ public static boolean validateCallerSignature(Context context, String packageName,
+ List<String> allowListSignatures) {
+ if (TextUtils.isEmpty(packageName) || allowListSignatures.size() == 0) {
+ // package name is mandatory
+ return false;
+ }
+ final PackageManager packageManager = context.getPackageManager();
+ try {
+ MessageDigest sha1MDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM);
+ final PackageInfo packageInfo = packageManager.getPackageInfo(packageName,
+ PackageManager.GET_SIGNATURES);
+ for (Signature signature : packageInfo.signatures) {
+ final byte[] signatureSha1 = sha1MDigest.digest(signature.toByteArray());
+ final String hexSignatureSha1 = IccUtils.bytesToHexString(signatureSha1);
+ if (!allowListSignatures.contains(hexSignatureSha1)) {
+ return false;
+ }
+ }
+ return true;
+ } catch (NoSuchAlgorithmException | PackageManager.NameNotFoundException ex) {
+ Rlog.e(LOG_TAG, "validateCallerSignature: Exception = " + ex);
+ return false;
+ }
+ }
+
+ public int updateJsonForTest(String callerInfo) {
+ try {
+ if (callerInfo == null) {
+ // reset the Json content after testing
+ loadJsonFile(mContext);
+ } else {
+ mDataJSON = new JSONObject(callerInfo);
+ }
+ return 0;
+ } catch (JSONException ex) {
+ Rlog.e(LOG_TAG, "updateJsonForTest: Exception = " + ex);
+ }
+ return -1;
+ }
+
+ private static class CarrierInfo {
+ final private int mCallerCarrierId;
+ final private List<String> mSHAIdList;
+
+ public CarrierInfo(int carrierId, List<String> SHAIds) {
+ mCallerCarrierId = carrierId;
+ mSHAIdList = SHAIds;
+ }
+
+ public int getCallerCarrierId() {
+ return mCallerCarrierId;
+ }
+
+ public List<String> getSHAIdList() {
+ return mSHAIdList;
+ }
+ }
+}
diff --git a/src/com/android/services/telephony/ConferenceParticipantConnection.java b/src/com/android/services/telephony/ConferenceParticipantConnection.java
index cbfe9ed..8179817 100644
--- a/src/com/android/services/telephony/ConferenceParticipantConnection.java
+++ b/src/com/android/services/telephony/ConferenceParticipantConnection.java
@@ -32,6 +32,8 @@
import com.android.phone.PhoneGlobals;
import com.android.telephony.Rlog;
+import java.util.Locale;
+
/**
* Represents a participant in a conference call.
*/
@@ -207,7 +209,7 @@
// The SubscriptionInfo reports ISO country codes in lower case. Convert to upper case,
// since ultimately we use this ISO when formatting the CEP phone number, and the phone
// number formatting library expects uppercase ISO country codes.
- return subInfo.getCountryIso().toUpperCase();
+ return subInfo.getCountryIso().toUpperCase(Locale.ROOT);
}
/**
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index c62b4fa..654fb93 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -980,23 +980,25 @@
// event package; some carriers are known to keep a disconnected participant around in
// subsequent CEP updates with a state of disconnected, even though its no longer part
// of the conference.
- // Note: We consider 0 to still be a single party conference since some carriers will
- // send a conference event package with JUST the host in it when the conference is
- // disconnected. We don't want to change back to conference mode prior to disconnection
- // or we will not log the call.
- boolean isSinglePartyConference = participants.stream()
+ final long numActiveCepParticipantsOtherThanHost = participants.stream()
.filter(p -> {
Pair<Uri, Uri> pIdent = new Pair<>(p.getHandle(), p.getEndpoint());
return !Objects.equals(mHostParticipantIdentity, pIdent)
&& p.getState() != Connection.STATE_DISCONNECTED;
})
- .count() <= 1;
+ .count();
+ // We consider 0 to still be a single party conference since some carriers
+ // will send a conference event package with JUST the host in it when the conference
+ // is disconnected. We don't want to change back to conference mode prior to
+ // disconnection or we will not log the call.
+ final boolean isCepForSinglePartyConference =
+ numActiveCepParticipantsOtherThanHost <= 1;
// We will only process the CEP data if:
// 1. We're not emulating a single party call.
// 2. We're emulating a single party call and the CEP contains more than just the
// single party
- if ((!isMultiparty() && !isSinglePartyConference)
+ if ((!isMultiparty() && !isCepForSinglePartyConference)
|| isMultiparty()) {
// Add any new participants and update existing.
for (ConferenceParticipant participant : participants) {
@@ -1082,15 +1084,17 @@
int newParticipantCount = mConferenceParticipantConnections.size();
Log.v(this, "handleConferenceParticipantsUpdate: oldParticipantCount=%d, "
- + "newParticipantcount=%d", oldParticipantCount, newParticipantCount);
- // If the single party call emulation fature flag is enabled, we can potentially treat
+ + "newParticipantCount=%d, isMultiPty=%b, cepParticipantCt=%d",
+ oldParticipantCount, newParticipantCount, isMultiparty(),
+ numActiveCepParticipantsOtherThanHost);
+ // If the single party call emulation feature flag is enabled, we can potentially treat
// the conference as a single party call when there is just one participant.
if (mFeatureFlagProxy.isUsingSinglePartyCallEmulation() &&
!mConferenceHost.isAdhocConferenceCall()) {
if (oldParticipantCount != 1 && newParticipantCount == 1) {
// If number of participants goes to 1, emulate a single party call.
startEmulatingSinglePartyCall();
- } else if (!isMultiparty() && !isSinglePartyConference) {
+ } else if (!isMultiparty() && !isCepForSinglePartyConference) {
// Number of participants increased, so stop emulating a single party call.
stopEmulatingSinglePartyCall();
}
@@ -1108,8 +1112,8 @@
// OR if the conference had a single participant and is emulating a standalone
// call.
&& (oldParticipantCount > 0 || !isMultiparty())
- // AND the CEP says there is nobody left any more.
- && newParticipantCount == 0) {
+ // AND the CEP says there is nobody left anymore.
+ && numActiveCepParticipantsOtherThanHost == 0) {
Log.i(this, "handleConferenceParticipantsUpdate: empty conference; "
+ "local disconnect.");
onDisconnect();
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index 7cf9415..4200904 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -16,6 +16,7 @@
package com.android.services.telephony;
+import android.annotation.NonNull;
import android.content.Context;
import android.os.PersistableBundle;
import android.telecom.Conference;
@@ -26,17 +27,17 @@
import android.telecom.PhoneAccountHandle;
import android.telephony.CarrierConfigManager;
-import com.android.telephony.Rlog;
-
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.phone.PhoneUtils;
+import com.android.telephony.Rlog;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
+import java.util.Objects;
import java.util.stream.Collectors;
/**
@@ -220,14 +221,33 @@
recalculateConference();
}
+ private PhoneAccountHandle getPhoneAccountHandle(@NonNull Conferenceable c) {
+ if (c instanceof Connection) {
+ Connection connection = (Connection) c;
+ return connection.getPhoneAccountHandle();
+ } else if (c instanceof Conference) {
+ Conference conference = (Conference) c;
+ return conference.getPhoneAccountHandle();
+ }
+ throw new IllegalArgumentException("Unrecognized Conferenceable!" + c);
+ }
+
+ private boolean isSamePhoneAccountHandle(
+ @NonNull Conferenceable left, @NonNull Conferenceable right) {
+ PhoneAccountHandle leftHandle = getPhoneAccountHandle(left);
+ PhoneAccountHandle rightHandle = getPhoneAccountHandle(right);
+ return Objects.equals(leftHandle, rightHandle);
+ }
+
/**
* Calculates the conference-capable state of all GSM connections in this connection service.
+ * Connections from different {@link PhoneAccountHandle}s shall not be conferenceable.
*/
private void recalculateConferenceable() {
Log.v(this, "recalculateConferenceable : %d", mTelephonyConnections.size());
HashSet<Conferenceable> conferenceableSet = new HashSet<>(mTelephonyConnections.size() +
mImsConferences.size());
- HashSet<Conferenceable> conferenceParticipantsSet = new HashSet<>();
+ HashSet<Connection> conferenceParticipantsSet = new HashSet<>();
// Loop through and collect all calls which are active or holding
for (TelephonyConnection connection : mTelephonyConnections) {
@@ -300,11 +320,6 @@
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());
// TODO: Remove this once RemoteConnection#setConferenceableConnections is fixed.
// Add all conference participant connections as conferenceable with a standalone
// Connection. We need to do this to ensure that RemoteConnections work properly.
@@ -313,7 +328,18 @@
// into the conference.
// We should add support for RemoteConnection#setConferenceables, which accepts a
// list of remote conferences and connections in the future.
- conferenceables.addAll(conferenceParticipantsSet);
+ List<Conferenceable> conferenceables = conferenceParticipantsSet
+ .stream()
+ // Removes conference participants from different PhoneAccountHandles.
+ .filter(connection -> isSamePhoneAccountHandle(c, connection))
+ .collect(Collectors.toCollection(ArrayList::new));
+
+ // Removes this connection from the Set and add all others. Removes conferenceables
+ // from different PhoneAccountHandles.
+ conferenceables.addAll(conferenceableSet
+ .stream()
+ .filter(conferenceable -> c != conferenceable
+ && isSamePhoneAccountHandle(c, conferenceable)).toList());
((Connection) c).setConferenceables(conferenceables);
} else if (c instanceof ImsConference) {
@@ -325,10 +351,11 @@
}
// Remove all conferences from the set, since we can not conference a conference
- // to another conference.
+ // to another conference. Removes connections from different PhoneAccountHandles.
List<Connection> connections = conferenceableSet
.stream()
- .filter(conferenceable -> conferenceable instanceof Connection)
+ .filter(conferenceable -> conferenceable instanceof Connection
+ && isSamePhoneAccountHandle(c, conferenceable))
.map(conferenceable -> (Connection) conferenceable)
.collect(Collectors.toList());
// Conference equivalent to setConferenceables that only accepts Connections
diff --git a/src/com/android/services/telephony/PstnIncomingCallNotifier.java b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
index 8615325..d58c211 100644
--- a/src/com/android/services/telephony/PstnIncomingCallNotifier.java
+++ b/src/com/android/services/telephony/PstnIncomingCallNotifier.java
@@ -393,8 +393,9 @@
*/
private PhoneAccountHandle findCorrectPhoneAccountHandle() {
TelecomAccountRegistry telecomAccountRegistry = TelecomAccountRegistry.getInstance(null);
- // Check to see if a the SIM PhoneAccountHandle Exists for the Call.
- PhoneAccountHandle handle = PhoneUtils.makePstnPhoneAccountHandle(mPhone);
+ // Check to see if a SIM PhoneAccountHandle Exists for the Call.
+ PhoneAccountHandle handle = telecomAccountRegistry.getPhoneAccountHandleForSubId(
+ mPhone.getSubId());
if (telecomAccountRegistry.hasAccountEntryForPhoneAccount(handle)) {
return handle;
}
@@ -403,7 +404,8 @@
// receives an MT call while in ECM. Use the Emergency PhoneAccount to receive the account
// if it exists.
PhoneAccountHandle emergencyHandle =
- PhoneUtils.makePstnPhoneAccountHandleWithPrefix(mPhone, "", true);
+ PhoneUtils.makePstnPhoneAccountHandleWithPrefix(mPhone,
+ "", true, mPhone.getUserHandle());
if(telecomAccountRegistry.hasAccountEntryForPhoneAccount(emergencyHandle)) {
Log.i(this, "Receiving MT call in ECM. Using Emergency PhoneAccount Instead.");
return emergencyHandle;
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index a9b4c71..57e65ee 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -64,6 +64,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SubscriptionController;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.phone.PhoneGlobals;
import com.android.phone.PhoneUtils;
import com.android.phone.R;
@@ -72,6 +73,7 @@
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
+import java.util.Locale;
import java.util.Optional;
import java.util.function.Predicate;
@@ -273,6 +275,8 @@
private PhoneAccount registerPstnPhoneAccount(boolean isEmergency, boolean isTestAccount) {
PhoneAccount account = buildPstnPhoneAccount(mIsEmergency, mIsTestAccount);
+ Log.i(this, "registerPstnPhoneAccount: Registering account=%s with "
+ + "Telecom. subId=%d", account, getSubId());
// Register with Telecom and put into the account entry.
mTelecomManager.registerPhoneAccount(account);
return account;
@@ -284,13 +288,18 @@
private PhoneAccount buildPstnPhoneAccount(boolean isEmergency, boolean isTestAccount) {
String testPrefix = isTestAccount ? "Test " : "";
+ // Check if we are registering another user. If we are, ensure that the account
+ // is registered to that user handle.
+ int subId = mPhone.getSubId();
+ // Get user handle from phone's sub id (if we get null, then system user will be used)
+ UserHandle userToRegister = mPhone.getUserHandle();
+
// Build the Phone account handle.
PhoneAccountHandle phoneAccountHandle =
PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
- mPhone, testPrefix, isEmergency);
+ mPhone, testPrefix, isEmergency, userToRegister);
// 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;
@@ -303,8 +312,8 @@
subNumber = "";
}
- String label;
- String description;
+ String label = "";
+ String description = "";
Icon icon = null;
// We can only get the real slotId from the SubInfoRecord, we can't calculate the
@@ -320,7 +329,9 @@
} else if (mTelephonyManager.getPhoneCount() == 1) {
// For single-SIM devices, we show the label and description as whatever the name of
// the network is.
- description = label = tm.getNetworkOperatorName();
+ if (record != null) {
+ description = label = String.valueOf(record.getDisplayName());
+ }
} else {
CharSequence subDisplayName = null;
@@ -354,8 +365,12 @@
// By default all SIM phone accounts can place emergency calls.
int capabilities = PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION |
- PhoneAccount.CAPABILITY_CALL_PROVIDER |
- PhoneAccount.CAPABILITY_MULTI_USER;
+ PhoneAccount.CAPABILITY_CALL_PROVIDER;
+
+ // This is enabled by default. To support work profiles, it should not be enabled.
+ if (userToRegister == null) {
+ capabilities |= PhoneAccount.CAPABILITY_MULTI_USER;
+ }
if (mContext.getResources().getBoolean(R.bool.config_pstnCanPlaceEmergencyCalls)) {
capabilities |= PhoneAccount.CAPABILITY_PLACE_EMERGENCY_CALLS;
@@ -535,18 +550,37 @@
return false;
}
- SubscriptionController controller = SubscriptionController.getInstance();
- if (controller == null) {
- Log.d(this, "isEmergencyPreferredAccount: SubscriptionController not available.");
- return false;
- }
- // Only set an emergency preference on devices with multiple active subscriptions
- // (include opportunistic subscriptions) in this check.
- // API says never null, but this can return null in testing.
- int[] activeSubIds = controller.getActiveSubIdList(false);
- if (activeSubIds == null || activeSubIds.length <= 1) {
- Log.d(this, "isEmergencyPreferredAccount: one or less active subscriptions.");
- return false;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ if (SubscriptionManagerService.getInstance() == null) {
+ Log.d(this,
+ "isEmergencyPreferredAccount: SubscriptionManagerService not "
+ + "available.");
+ return false;
+ }
+ // Only set an emergency preference on devices with multiple active subscriptions
+ // (include opportunistic subscriptions) in this check.
+ // API says never null, but this can return null in testing.
+ int[] activeSubIds = SubscriptionManagerService.getInstance()
+ .getActiveSubIdList(false);
+ if (activeSubIds == null || activeSubIds.length <= 1) {
+ Log.d(this, "isEmergencyPreferredAccount: one or less active subscriptions.");
+ return false;
+ }
+ } else {
+ SubscriptionController controller = SubscriptionController.getInstance();
+ if (controller == null) {
+ Log.d(this,
+ "isEmergencyPreferredAccount: SubscriptionController not available.");
+ return false;
+ }
+ // Only set an emergency preference on devices with multiple active subscriptions
+ // (include opportunistic subscriptions) in this check.
+ // API says never null, but this can return null in testing.
+ int[] activeSubIds = controller.getActiveSubIdList(false);
+ if (activeSubIds == null || activeSubIds.length <= 1) {
+ Log.d(this, "isEmergencyPreferredAccount: one or less active subscriptions.");
+ return false;
+ }
}
// Check to see if this PhoneAccount is associated with the default Data subscription.
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -554,10 +588,21 @@
+ "valid.");
return false;
}
- int userDefaultData = controller.getDefaultDataSubId();
+ int userDefaultData = SubscriptionManager.getDefaultDataSubscriptionId();
boolean isActiveDataValid = SubscriptionManager.isValidSubscriptionId(activeDataSubId);
- boolean isActiveDataOpportunistic = isActiveDataValid
- && controller.isOpportunistic(activeDataSubId);
+
+ boolean isActiveDataOpportunistic;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ SubscriptionInfo subInfo;
+ subInfo = SubscriptionManagerService.getInstance()
+ .getSubscriptionInfo(activeDataSubId);
+ isActiveDataOpportunistic = isActiveDataValid && subInfo != null
+ && subInfo.isOpportunistic();
+ } else {
+ isActiveDataOpportunistic = isActiveDataValid
+ && SubscriptionController.getInstance().isOpportunistic(activeDataSubId);
+ }
+
// compare the activeDataSubId to the subId specified only if it is valid and not an
// opportunistic subscription (only supports data). If not, use the current default
// defined by the user.
@@ -924,7 +969,7 @@
// Next check whether we're in or near a country that supports it
String country =
mPhone.getServiceStateTracker().getLocaleTracker()
- .getLastKnownCountryIso().toLowerCase();
+ .getLastKnownCountryIso().toLowerCase(Locale.ROOT);
String[] supportedCountries = mContext.getResources().getStringArray(
R.array.config_simless_emergency_rtt_supported_countries);
@@ -1132,7 +1177,10 @@
@Override
public void onServiceStateChanged(ServiceState serviceState) {
int newState = serviceState.getState();
+ Log.i(this, "onServiceStateChanged: newState=%d, mServiceState=%d",
+ newState, mServiceState);
if (newState == ServiceState.STATE_IN_SERVICE && mServiceState != newState) {
+ Log.i(this, "onServiceStateChanged: Tearing down and re-setting up accounts.");
tearDownAccounts();
setupAccounts();
} else {
@@ -1545,9 +1593,8 @@
int subscriptionId = phone.getSubId();
Log.i(this, "setupAccounts: 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 (!SubscriptionManager.isValidSubscriptionId(subscriptionId)
- || phone.getFullIccSerialNumber() == null) {
+ // Don't add an account if subscription is not ready.
+ if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
Log.d(this, "setupAccounts: skipping invalid subid %d", subscriptionId);
continue;
}
@@ -1579,6 +1626,7 @@
// Add a fake account entry.
if (DBG && phones.length > 0 && "TRUE".equals(System.getProperty("test_sim"))) {
+ Log.i(this, "setupAccounts: adding a fake AccountEntry");
mAccounts.add(new AccountEntry(phones[0], false /* emergency */,
true /* isTest */));
}
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index f6d3feb..9f248b7 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -16,6 +16,10 @@
package com.android.services.telephony;
+import static android.telephony.ims.ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED;
+import static android.telephony.ims.ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL;
+import static android.telephony.ims.ImsReasonInfo.EXTRA_CODE_CALL_RETRY_EMERGENCY;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
@@ -48,11 +52,13 @@
import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
import android.telephony.ims.RtpHeaderExtension;
import android.telephony.ims.RtpHeaderExtensionType;
+import android.telephony.ims.feature.MmTelFeature;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Pair;
@@ -95,6 +101,7 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -141,6 +148,7 @@
private static final int MSG_REJECT = 21;
private static final int MSG_DTMF_DONE = 22;
private static final int MSG_MEDIA_ATTRIBUTES_CHANGED = 23;
+ private static final int MSG_ON_RTT_INITIATED = 24;
private static final String JAPAN_COUNTRY_CODE_WITH_PLUS_SIGN = "+81";
private static final String JAPAN_ISO_COUNTRY_CODE = "JP";
@@ -328,6 +336,15 @@
args.recycle();
}
break;
+ case MSG_ON_RTT_INITIATED:
+ if (mOriginalConnection != null) {
+ // if mOriginalConnection is null, the properties will get set when
+ // mOriginalConnection gets set.
+ updateConnectionProperties();
+ refreshConferenceSupported();
+ }
+ sendRttInitiationSuccess();
+ break;
}
}
};
@@ -749,13 +766,11 @@
@Override
public void onRttInitiated() {
- if (mOriginalConnection != null) {
- // if mOriginalConnection is null, the properties will get set when
- // mOriginalConnection gets set.
- updateConnectionProperties();
- refreshConferenceSupported();
- }
- sendRttInitiationSuccess();
+ Log.i(TelephonyConnection.this, "onRttInitiated: callId=%s", getTelecomCallId());
+ // Post RTT initiation to the Handler associated with this TelephonyConnection.
+ // This avoids a race condition where a call starts as RTT but ConnectionService call to
+ // handleCreateConnectionComplete happens AFTER the RTT status is reported to Telecom.
+ mHandler.obtainMessage(MSG_ON_RTT_INITIATED).sendToTarget();
}
@Override
@@ -800,6 +815,13 @@
Log.i(this, "onReceivedDtmfDigit: digit=%c", digit);
mDtmfTransport.onDtmfReceived(digit);
}
+
+ @Override
+ public void onAudioModeIsVoipChanged(int imsAudioHandler) {
+ boolean isVoip = imsAudioHandler == MmTelFeature.AUDIO_HANDLER_ANDROID;
+ Log.i(this, "onAudioModeIsVoipChanged isVoip =" + isVoip);
+ setAudioModeIsVoip(isVoip);
+ }
};
private TelephonyConnectionService mTelephonyConnectionService;
@@ -925,6 +947,8 @@
private final Set<TelephonyConnectionListener> mTelephonyListeners = Collections.newSetFromMap(
new ConcurrentHashMap<TelephonyConnectionListener, Boolean>(8, 0.9f, 1));
+ private Integer mEmergencyServiceCategory = null;
+
protected TelephonyConnection(com.android.internal.telephony.Connection originalConnection,
String callId, @android.telecom.Call.Details.CallDirection int callDirection) {
setCallDirection(callDirection);
@@ -1306,6 +1330,8 @@
if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
ImsPhone imsPhone = (ImsPhone) phone;
imsPhone.holdActiveCall();
+ mTelephonyConnectionService.maybeUnholdCallsOnOtherSubs(
+ getPhoneAccountHandle());
return;
}
phone.switchHoldingAndActive();
@@ -1674,7 +1700,8 @@
if (filteredCnapNames != null) {
long cnapNameMatches = Arrays.asList(filteredCnapNames)
.stream()
- .filter(filteredCnapName -> filteredCnapName.equals(cnapName.toUpperCase()))
+ .filter(filteredCnapName -> filteredCnapName.equals(
+ cnapName.toUpperCase(Locale.ROOT)))
.count();
if (cnapNameMatches > 0) {
Log.i(this, "filterCnapName: Filtered CNAP Name: " + cnapName);
@@ -2017,32 +2044,47 @@
}
@VisibleForTesting
- public PersistableBundle getCarrierConfig() {
+ public @NonNull PersistableBundle getCarrierConfig() {
Phone phone = getPhone();
if (phone == null) {
- return null;
+ Log.w(this,
+ "getCarrierConfig: phone is null. Returning CarrierConfigManager"
+ + ".getDefaultConfig()");
+ return CarrierConfigManager.getDefaultConfig();
}
- return PhoneGlobals.getInstance().getCarrierConfigForSubId(phone.getSubId());
+
+ // potential null returned from .getCarrierConfigForSubId() and method guarantees non-null.
+ // hence, need for try/finally block
+ PersistableBundle pb = null;
+ try {
+ pb = PhoneGlobals.getInstance().getCarrierConfigForSubId(phone.getSubId());
+ } catch (Exception e) {
+ Log.e(this, e,
+ "getCarrierConfig: caught Exception when calling "
+ + "PhoneGlobals.getCarrierConfigForSubId(phone.getSubId()). Returning "
+ + "CarrierConfigManager.getDefaultConfig()");
+ } finally {
+ if (pb == null) {
+ pb = CarrierConfigManager.getDefaultConfig();
+ }
+ }
+ return pb;
+ }
+
+ @VisibleForTesting
+ public boolean isRttMergeSupported(@NonNull PersistableBundle pb) {
+ return pb.getBoolean(CarrierConfigManager.KEY_ALLOW_MERGING_RTT_CALLS_BOOL);
}
private boolean canDeflectImsCalls() {
- PersistableBundle b = getCarrierConfig();
- // Return false if the CarrierConfig is unavailable
- if (b != null) {
- return b.getBoolean(
- CarrierConfigManager.KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL) &&
- isValidRingingCall();
- }
- return false;
+ return getCarrierConfig().getBoolean(
+ CarrierConfigManager.KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL)
+ && isValidRingingCall();
}
private boolean isCallTransferSupported() {
- PersistableBundle b = getCarrierConfig();
- // Return false if the CarrierConfig is unavailable
- if (b != null) {
- return b.getBoolean(CarrierConfigManager.KEY_CARRIER_ALLOW_TRANSFER_IMS_CALL_BOOL);
- }
- return false;
+ return getCarrierConfig().getBoolean(
+ CarrierConfigManager.KEY_CARRIER_ALLOW_TRANSFER_IMS_CALL_BOOL);
}
private boolean canTransfer(TelephonyConnection c) {
@@ -2142,7 +2184,7 @@
mPhoneForEvents = null;
}
- @VisibleForTesting
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public void hangup(int telephonyDisconnectCode) {
if (mOriginalConnection != null) {
mHangupDisconnectCause = telephonyDisconnectCode;
@@ -2168,6 +2210,7 @@
Log.e(this, e, "Call to Connection.hangup failed with exception");
}
} else {
+ mTelephonyConnectionService.onLocalHangup(this);
if (getState() == STATE_DISCONNECTED) {
Log.i(this, "hangup called on an already disconnected call!");
close();
@@ -2438,6 +2481,42 @@
setTelephonyConnectionRinging();
break;
case DISCONNECTED:
+ if (mTelephonyConnectionService != null) {
+ ImsReasonInfo reasonInfo = null;
+ if (isImsConnection()) {
+ ImsPhoneConnection imsPhoneConnection =
+ (ImsPhoneConnection) mOriginalConnection;
+ reasonInfo = imsPhoneConnection.getImsReasonInfo();
+ if (reasonInfo != null) {
+ int reasonCode = reasonInfo.getCode();
+ int extraCode = reasonInfo.getExtraCode();
+ if ((reasonCode == CODE_SIP_ALTERNATE_EMERGENCY_CALL)
+ || (reasonCode == CODE_LOCAL_CALL_CS_RETRY_REQUIRED
+ && extraCode == EXTRA_CODE_CALL_RETRY_EMERGENCY)) {
+ EmergencyNumber numberInfo =
+ imsPhoneConnection.getEmergencyNumberInfo();
+ if (numberInfo != null) {
+ mEmergencyServiceCategory =
+ numberInfo.getEmergencyServiceCategoryBitmask();
+ } else {
+ Log.i(this, "mEmergencyServiceCategory no EmergencyNumber");
+ }
+
+ if (mEmergencyServiceCategory != null) {
+ Log.i(this, "mEmergencyServiceCategory="
+ + mEmergencyServiceCategory);
+ }
+ }
+ }
+ }
+
+ if (mTelephonyConnectionService.maybeReselectDomain(this,
+ mOriginalConnection.getPreciseDisconnectCause(), reasonInfo)) {
+ clearOriginalConnection();
+ break;
+ }
+ }
+
if (shouldTreatAsEmergencyCall()
&& (cause
== android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE
@@ -3049,8 +3128,6 @@
if (isIms) {
isVoWifiEnabled = isWfcEnabled(phone);
}
- boolean isRttMergeSupported = getCarrierConfig()
- .getBoolean(CarrierConfigManager.KEY_ALLOW_MERGING_RTT_CALLS_BOOL);
PhoneAccountHandle phoneAccountHandle = isIms ? PhoneUtils
.makePstnPhoneAccountHandle(phone.getDefaultPhone())
: PhoneUtils.makePstnPhoneAccountHandle(phone);
@@ -3088,7 +3165,7 @@
if (mTreatAsEmergencyCall) {
isConferenceSupported = false;
Log.d(this, "refreshConferenceSupported = false; emergency call");
- } else if (isRtt() && !isRttMergeSupported) {
+ } else if (isRtt() && !isRttMergeSupported(getCarrierConfig())) {
isConferenceSupported = false;
Log.d(this, "refreshConferenceSupported = false; rtt call");
} else if (!isConferencingSupported || isIms && !isImsConferencingSupported) {
@@ -3145,12 +3222,9 @@
Phone phone = getPhone();
if (phone != null && (phone.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA)
&& !mOriginalConnection.isIncoming()) {
- PersistableBundle pb = getCarrierConfig();
- if (pb != null) {
- showOrigDialString = pb.getBoolean(CarrierConfigManager
- .KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL);
- Log.d(this, "showOrigDialString: " + showOrigDialString);
- }
+ showOrigDialString = getCarrierConfig().getBoolean(CarrierConfigManager
+ .KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL);
+ Log.d(this, "showOrigDialString: " + showOrigDialString);
}
return showOrigDialString;
}
@@ -3727,8 +3801,7 @@
if (mOriginalConnection.isIncoming()
&& !TextUtils.isEmpty(mOriginalConnection.getAddress())
&& mOriginalConnection.getAddress().startsWith(JAPAN_COUNTRY_CODE_WITH_PLUS_SIGN)) {
- PersistableBundle b = getCarrierConfig();
- return b != null && b.getBoolean(
+ return getCarrierConfig().getBoolean(
CarrierConfigManager.KEY_FORMAT_INCOMING_NUMBER_TO_NATIONAL_FOR_JP_BOOL);
}
return false;
@@ -3753,8 +3826,7 @@
* otherwise.
*/
private boolean supportsD2DUsingRtp() {
- PersistableBundle b = getCarrierConfig();
- return b != null && b.getBoolean(
+ return getCarrierConfig().getBoolean(
CarrierConfigManager.KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_RTP_BOOL);
}
@@ -3762,8 +3834,7 @@
* @return {@code true} if the carrier supports D2D using DTMF digits, {@code false} otherwise.
*/
private boolean supportsD2DUsingDtmf() {
- PersistableBundle b = getCarrierConfig();
- return b != null && b.getBoolean(
+ return getCarrierConfig().getBoolean(
CarrierConfigManager.KEY_SUPPORTS_DEVICE_TO_DEVICE_COMMUNICATION_USING_DTMF_BOOL);
}
@@ -3772,8 +3843,7 @@
* extensions used in D2D comms, {@code false} otherwise.
*/
private boolean supportsSdpNegotiationOfRtpHeaderExtensions() {
- PersistableBundle b = getCarrierConfig();
- return b != null && b.getBoolean(
+ return getCarrierConfig().getBoolean(
CarrierConfigManager
.KEY_SUPPORTS_SDP_NEGOTIATION_OF_D2D_RTP_HEADER_EXTENSIONS_BOOL);
}
@@ -3834,4 +3904,21 @@
public List<TelephonyConnectionListener> getTelephonyConnectionListeners() {
return new ArrayList<>(mTelephonyListeners);
}
+
+ /**
+ * @return An {@link Integer} instance of the emergency service category.
+ */
+ public @Nullable Integer getEmergencyServiceCategory() {
+ return mEmergencyServiceCategory;
+ }
+
+ /**
+ * Sets the emergency service category.
+ *
+ * @param eccCategory The emergency service category.
+ */
+ @VisibleForTesting
+ public void setEmergencyServiceCategory(int eccCategory) {
+ mEmergencyServiceCategory = eccCategory;
+ }
}
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index bb96c7c..7311113 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -16,6 +16,9 @@
package com.android.services.telephony;
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
+import static android.telephony.TelephonyManager.HAL_SERVICE_VOICE;
+
import android.annotation.NonNull;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -29,7 +32,9 @@
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelUuid;
+import android.provider.DeviceConfig;
import android.telecom.Conference;
+import android.telecom.Conferenceable;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
import android.telecom.ConnectionService;
@@ -38,17 +43,24 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
+import android.telephony.Annotation.DisconnectCauses;
import android.telephony.CarrierConfigManager;
+import android.telephony.DomainSelectionService;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.EmergencyRegResult;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneNumberUtils;
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsReasonInfo;
import android.text.TextUtils;
import android.util.Pair;
import android.view.WindowManager;
+import com.android.ims.ImsManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
@@ -62,9 +74,18 @@
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.d2d.Communicator;
import com.android.internal.telephony.data.PhoneSwitcher;
+import com.android.internal.telephony.domainselection.DomainSelectionConnection;
+import com.android.internal.telephony.domainselection.DomainSelectionResolver;
+import com.android.internal.telephony.domainselection.EmergencyCallDomainSelectionConnection;
+import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
+import com.android.internal.telephony.emergency.EmergencyStateTracker;
import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneConnection;
+import com.android.internal.telephony.imsphone.ImsPhoneMmiCode;
+import com.android.internal.telephony.satellite.SatelliteSOSMessageRecommender;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.phone.FrameworksUtils;
import com.android.phone.MMIDialogActivity;
import com.android.phone.PhoneUtils;
@@ -85,6 +106,7 @@
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.regex.Pattern;
@@ -99,6 +121,12 @@
// from the modem.
private static final int DEFAULT_DATA_SWITCH_TIMEOUT_MS = 1000;
+ // Timeout before we terminate the outgoing DSDA call if HOLD did not complete in time on the
+ // existing call.
+ private static final int DEFAULT_DSDA_OUTGOING_CALL_HOLD_TIMEOUT_MS = 1000;
+ private static final String KEY_DOMAIN_COMPARE_FEATURE_ENABLED_FLAG =
+ "is_domain_selection_compare_feature_enabled";
+
// If configured, reject attempts to dial numbers matching this pattern.
private static final Pattern CDMA_ACTIVATION_CODE_REGEX_PATTERN =
Pattern.compile("\\*228[0-9]{0,2}");
@@ -115,6 +143,12 @@
}
@Override
public void addConference(ImsConference mImsConference) {
+ Connection conferenceHost = mImsConference.getConferenceHost();
+ if (conferenceHost instanceof TelephonyConnection) {
+ TelephonyConnection tcConferenceHost = (TelephonyConnection) conferenceHost;
+ tcConferenceHost.setTelephonyConnectionService(TelephonyConnectionService.this);
+ tcConferenceHost.setPhoneAccountHandle(mImsConference.getPhoneAccountHandle());
+ }
TelephonyConnectionService.this.addTelephonyConference(mImsConference);
}
@Override
@@ -175,24 +209,43 @@
@VisibleForTesting
public Pair<WeakReference<TelephonyConnection>, Queue<Phone>> mEmergencyRetryCache;
private DeviceState mDeviceState = new DeviceState();
+ private EmergencyStateTracker mEmergencyStateTracker;
+ private SatelliteSOSMessageRecommender mSatelliteSOSMessageRecommender;
+ private DomainSelectionResolver mDomainSelectionResolver;
+ private EmergencyCallDomainSelectionConnection mEmergencyCallDomainSelectionConnection;
+ private TelephonyConnection mEmergencyConnection;
+ private String mEmergencyCallId = null;
+ private Executor mDomainSelectionMainExecutor;
+ private ImsManager mImsManager = null;
+ private DomainSelectionConnection mDomainSelectionConnection;
+ private TelephonyConnection mNormalCallConnection;
/**
* Keeps track of the status of a SIM slot.
*/
private static class SlotStatus {
public int slotId;
+ public int activeSubId;
// RAT capabilities
public int capabilities;
// By default, we will assume that the slots are not locked.
public boolean isLocked = false;
// Is the emergency number associated with the slot
public boolean hasDialedEmergencyNumber = false;
- //SimState
+ //SimState.
public int simState;
- public SlotStatus(int slotId, int capabilities) {
+ //helper to check if sim is really 'present' in the traditional sense.
+ // since eSIM always reports SIM_STATE_READY
+ public boolean isSubActiveAndSimPresent() {
+ return (simState != TelephonyManager.SIM_STATE_ABSENT
+ && activeSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ }
+
+ public SlotStatus(int slotId, int capabilities, int activeSubId) {
this.slotId = slotId;
this.capabilities = capabilities;
+ this.activeSubId = activeSubId;
}
}
@@ -202,6 +255,7 @@
@VisibleForTesting
public interface SubscriptionManagerProxy {
int getDefaultVoicePhoneId();
+ int getDefaultDataPhoneId();
int getSimStateForSlotIdx(int slotId);
int getPhoneId(int subId);
}
@@ -213,14 +267,20 @@
}
@Override
+ public int getDefaultDataPhoneId() {
+ return getPhoneId(SubscriptionManager.getDefaultDataSubscriptionId());
+ }
+
+ @Override
public int getSimStateForSlotIdx(int slotId) {
- return SubscriptionManager.getSimStateForSlotIndex(slotId);
+ return TelephonyManager.getSimStateForSlotIndex(slotId);
}
@Override
public int getPhoneId(int subId) {
return SubscriptionManager.getPhoneId(subId);
}
+
};
/**
@@ -229,10 +289,20 @@
@VisibleForTesting
public interface TelephonyManagerProxy {
int getPhoneCount();
- boolean hasIccCard(int slotId);
boolean isCurrentEmergencyNumber(String number);
Map<Integer, List<EmergencyNumber>> getCurrentEmergencyNumberList();
+
+ /**
+ * Determines whether concurrent IMS calls across both SIMs are possible, based on whether
+ * the device is DSDA capable, or if the DSDS device supports virtual DSDA.
+ */
boolean isConcurrentCallsPossible();
+
+ /**
+ * Gets the maximum number of SIMs that can be active, based on the device's multisim
+ * configuration. Returns 1 for DSDS, 2 for DSDA.
+ */
+ int getMaxNumberOfSimultaneouslyActiveSims();
}
private TelephonyManagerProxy mTelephonyManagerProxy;
@@ -251,11 +321,6 @@
}
@Override
- public boolean hasIccCard(int slotId) {
- return mTelephonyManager.hasIccCard(slotId);
- }
-
- @Override
public boolean isCurrentEmergencyNumber(String number) {
try {
return mTelephonyManager.isEmergencyNumber(number);
@@ -274,9 +339,22 @@
}
@Override
+ public int getMaxNumberOfSimultaneouslyActiveSims() {
+ try {
+ return mTelephonyManager.getMaxNumberOfSimultaneouslyActiveSims();
+ } catch (IllegalStateException ise) {
+ return 1;
+ }
+ }
+
+ @Override
public boolean isConcurrentCallsPossible() {
- // Under DSDA, need to be determined by voice capabilities
- return mTelephonyManager.getMaxNumberOfSimultaneouslyActiveSims() > 1;
+ try {
+ return getMaxNumberOfSimultaneouslyActiveSims() > 1
+ || mTelephonyManager.getPhoneCapability().getMaxActiveVoiceSubscriptions() > 1;
+ } catch (IllegalStateException ise) {
+ return false;
+ }
}
}
@@ -332,7 +410,8 @@
@Override
public PhoneAccountHandle makePstnPhoneAccountHandleWithPrefix(Phone phone, String prefix,
boolean isEmergency) {
- return PhoneUtils.makePstnPhoneAccountHandleWithPrefix(phone, prefix, isEmergency);
+ return PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
+ phone, prefix, isEmergency, phone.getUserHandle());
}
};
@@ -465,6 +544,209 @@
}
/**
+ * A listener for emergency calls.
+ */
+ private final TelephonyConnection.TelephonyConnectionListener mEmergencyConnectionListener =
+ new TelephonyConnection.TelephonyConnectionListener() {
+ @Override
+ public void onOriginalConnectionConfigured(TelephonyConnection c) {
+ com.android.internal.telephony.Connection origConn = c.getOriginalConnection();
+ if (origConn == null) return;
+ // Update the domain in the case that it changes,for example during initial
+ // setup or when there was an srvcc or internal redial.
+ mEmergencyStateTracker.onEmergencyCallDomainUpdated(
+ origConn.getPhoneType(), c.getTelecomCallId());
+ }
+
+ @Override
+ public void onStateChanged(Connection connection,
+ @Connection.ConnectionState int state) {
+ if (mEmergencyCallDomainSelectionConnection == null) return;
+ if (connection == null) return;
+ TelephonyConnection c = (TelephonyConnection) connection;
+ Log.i(this, "onStateChanged callId=" + c.getTelecomCallId()
+ + ", state=" + state);
+ if (c.getState() == Connection.STATE_ACTIVE) {
+ mEmergencyStateTracker.onEmergencyCallStateChanged(
+ c.getOriginalConnection().getState(), c.getTelecomCallId());
+ releaseEmergencyCallDomainSelection(false);
+ }
+ }
+ };
+
+ private final TelephonyConnection.TelephonyConnectionListener
+ mEmergencyConnectionSatelliteListener =
+ new TelephonyConnection.TelephonyConnectionListener() {
+ @Override
+ public void onStateChanged(Connection connection,
+ @Connection.ConnectionState int state) {
+ if (connection == null) {
+ Log.d(this,
+ "onStateChanged for satellite listener: connection is null");
+ return;
+ }
+ if (mSatelliteSOSMessageRecommender == null) {
+ Log.d(this, "onStateChanged for satellite listener: "
+ + "mSatelliteSOSMessageRecommender is null");
+ return;
+ }
+
+ TelephonyConnection c = (TelephonyConnection) connection;
+ mSatelliteSOSMessageRecommender.onEmergencyCallConnectionStateChanged(
+ c.getTelecomCallId(), state);
+ if (state == Connection.STATE_DISCONNECTED
+ || state == Connection.STATE_ACTIVE) {
+ c.removeTelephonyConnectionListener(mEmergencyConnectionSatelliteListener);
+ mSatelliteSOSMessageRecommender = null;
+ }
+ }
+ };
+
+ /**
+ * A listener for calls.
+ */
+ private final TelephonyConnection.TelephonyConnectionListener mNormalCallConnectionListener =
+ new TelephonyConnection.TelephonyConnectionListener() {
+ @Override
+ public void onStateChanged(
+ Connection connection, @Connection.ConnectionState int state) {
+ TelephonyConnection c = (TelephonyConnection) connection;
+ if (c != null) {
+ switch(c.getState()) {
+ case Connection.STATE_ACTIVE: {
+ Log.d(LOG_TAG, "Call State->ACTIVE."
+ + "Clearing DomainSelectionConnection");
+ if (mDomainSelectionConnection != null) {
+ mDomainSelectionConnection.finishSelection();
+ mDomainSelectionConnection = null;
+ }
+ mNormalCallConnection = null;
+ }
+ break;
+
+ case Connection.STATE_DISCONNECTED: {
+ c.removeTelephonyConnectionListener(mNormalCallConnectionListener);
+ }
+ break;
+ }
+ }
+ }
+ };
+
+ private static class StateHoldingListener extends
+ TelephonyConnection.TelephonyConnectionListener {
+ private final CompletableFuture<Boolean> mStateHoldingFuture;
+
+ StateHoldingListener(CompletableFuture<Boolean> future) {
+ mStateHoldingFuture = future;
+ }
+
+ @Override
+ public void onStateChanged(
+ Connection connection, @Connection.ConnectionState int state) {
+ TelephonyConnection c = (TelephonyConnection) connection;
+ if (c != null) {
+ switch (c.getState()) {
+ case Connection.STATE_HOLDING: {
+ Log.d(LOG_TAG, "Connection " + connection
+ + " changed to STATE_HOLDING!");
+ mStateHoldingFuture.complete(true);
+ c.removeTelephonyConnectionListener(this);
+ }
+ break;
+ case Connection.STATE_DISCONNECTED: {
+ Log.d(LOG_TAG, "Connection " + connection
+ + " changed to STATE_DISCONNECTED!");
+ mStateHoldingFuture.complete(false);
+ c.removeTelephonyConnectionListener(this);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private final DomainSelectionConnection.DomainSelectionConnectionCallback
+ mEmergencyDomainSelectionConnectionCallback =
+ new DomainSelectionConnection.DomainSelectionConnectionCallback() {
+ @Override
+ public void onSelectionTerminated(@DisconnectCauses int cause) {
+ mDomainSelectionMainExecutor.execute(() -> {
+ Log.i(this, "onSelectionTerminated cause=" + cause);
+ if (mEmergencyCallDomainSelectionConnection == null) {
+ Log.i(this, "onSelectionTerminated no DomainSelectionConnection");
+ return;
+ }
+
+ // Cross stack redial
+ if (cause == android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE
+ || cause == android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE) {
+ if (mEmergencyConnection != null) {
+ boolean isPermanentFailure =
+ cause == android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE;
+ Log.i(this, "onSelectionTerminated permanent=" + isPermanentFailure);
+ TelephonyConnection c = mEmergencyConnection;
+ Phone phone = mEmergencyCallDomainSelectionConnection.getPhone();
+ mEmergencyConnection.removeTelephonyConnectionListener(
+ mEmergencyConnectionListener);
+ releaseEmergencyCallDomainSelection(true);
+ mEmergencyStateTracker.endCall(mEmergencyCallId);
+ mEmergencyCallId = null;
+ retryOutgoingOriginalConnection(c, phone, isPermanentFailure);
+ return;
+ }
+ }
+ if (mEmergencyConnection != null) {
+ mEmergencyConnection.hangup(android.telephony.DisconnectCause.OUT_OF_NETWORK);
+ mEmergencyConnection = null;
+ }
+ });
+ }
+ };
+
+ private final DomainSelectionConnection.DomainSelectionConnectionCallback
+ mCallDomainSelectionConnectionCallback =
+ new DomainSelectionConnection.DomainSelectionConnectionCallback() {
+ @Override
+ public void onSelectionTerminated(@DisconnectCauses int cause) {
+ mDomainSelectionMainExecutor.execute(new Runnable() {
+ int mCause = cause;
+ @Override
+ public void run() {
+ Log.v(this, "Call domain selection terminated.");
+ if (mDomainSelectionConnection != null) {
+ mDomainSelectionConnection = null;
+ }
+ if (mNormalCallConnection != null) {
+ // TODO: To support ShowPreciseFailedCause, TelephonyConnection
+ // .getShowPreciseFailedCause API should be added.
+
+ // If cause is NOT_VALID then, it's a redial cancellation and
+ // use cause code from original connection.
+ com.android.internal.telephony.Connection connection =
+ mNormalCallConnection.getOriginalConnection();
+ if (connection != null) {
+ if (mCause == android.telephony.DisconnectCause.NOT_VALID) {
+ mCause = connection.getDisconnectCause();
+ }
+
+ String reason = connection.getVendorDisconnectCause();
+ int phoneId = mNormalCallConnection.getPhone().getPhoneId();
+ mNormalCallConnection.setTelephonyConnectionDisconnected(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(
+ mCause, reason, phoneId));
+ Log.d(this, "Call connection closed. Cause: " + mCause
+ + " Reason: " + reason);
+ }
+ mNormalCallConnection.close();
+ mNormalCallConnection = null;
+ }
+ }
+ });
+ }
+ };
+
+ /**
* A listener to actionable events specific to the TelephonyConnection.
*/
private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
@@ -476,7 +758,7 @@
@Override
public void onOriginalConnectionRetry(TelephonyConnection c, boolean isPermanentFailure) {
- retryOutgoingOriginalConnection(c, isPermanentFailure);
+ retryOutgoingOriginalConnection(c, c.getPhone(), isPermanentFailure);
}
};
@@ -503,6 +785,8 @@
TelecomAccountRegistry.getInstance(this).setTelephonyConnectionService(this);
mHoldTracker = new HoldTracker();
mIsTtyEnabled = mDeviceState.isTtyModeEnabled(this);
+ mDomainSelectionMainExecutor = getApplicationContext().getMainExecutor();
+ mDomainSelectionResolver = DomainSelectionResolver.getInstance();
IntentFilter intentFilter = new IntentFilter(
TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
@@ -770,6 +1054,17 @@
/* Note: when not an emergency, handle can be null for unknown callers */
handle == null ? null : handle.getSchemeSpecificPart());
+ if (mDomainSelectionResolver.isDomainSelectionSupported()) {
+ // Normal routing emergency number shall be handled by normal call domain selctor.
+ if (isEmergencyNumber && !isNormalRouting(phone, number)) {
+ final Connection resultConnection =
+ placeEmergencyConnection(phone,
+ request, numberToDial, isTestEmergencyNumber,
+ handle, needToTurnOnRadio);
+ if (resultConnection != null) return resultConnection;
+ }
+ }
+
if (needToTurnOnRadio) {
final Uri resultHandle = handle;
final int originalPhoneType = phone.getPhoneType();
@@ -795,7 +1090,8 @@
// an isTesting parameter. For HAL 1.4+, do not wait for IN_SERVICE, this will
// be handled at the RIL/vendor level by emergencyDial(...).
boolean waitForInServiceToDialEmergency = isTestEmergencyNumber
- && phone.getHalVersion().less(RIL.RADIO_HAL_VERSION_1_4);
+ && phone.getHalVersion(HAL_SERVICE_VOICE)
+ .less(RIL.RADIO_HAL_VERSION_1_4);
if (isEmergencyNumber && !waitForInServiceToDialEmergency) {
// 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
@@ -804,6 +1100,19 @@
return (phone.getState() == PhoneConstants.State.OFFHOOK)
|| phone.getServiceStateTracker().isRadioOn();
} else {
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ SubscriptionInfoInternal subInfo = SubscriptionManagerService
+ .getInstance().getSubscriptionInfoInternal(phone.getSubId());
+ // Wait until we are in service and ready to make calls. This can happen
+ // when we power down the radio on bluetooth to save power on watches or
+ // if it is a test emergency number and we have to wait for the device
+ // to move IN_SERVICE before the call can take place over normal
+ // routing.
+ return (phone.getState() == PhoneConstants.State.OFFHOOK)
+ // Do not wait for voice in service on opportunistic SIMs.
+ || (subInfo != null && subInfo.isOpportunistic())
+ || serviceState == ServiceState.STATE_IN_SERVICE;
+ }
// Wait until we are in service and ready to make calls. This can happen
// when we power down the radio on bluetooth to save power on watches or if
// it is a test emergency number and we have to wait for the device to move
@@ -841,6 +1150,21 @@
}
return resultConnection;
} else {
+ if (mTelephonyManagerProxy.isConcurrentCallsPossible()) {
+ delayDialForOtherSubHold(phone, request.getAccountHandle(), (result) -> {
+ Log.d(this,
+ "onCreateOutgoingConn - delayDialForOtherSubHold result = "
+ + result);
+ if (result) {
+ placeOutgoingConnection(request, resultConnection, phone);
+ } else {
+ ((TelephonyConnection) resultConnection).hangup(
+ android.telephony.DisconnectCause.LOCAL);
+ }
+ });
+ return resultConnection;
+ }
+ // The standard case.
return placeOutgoingConnection(request, resultConnection, phone);
}
} else {
@@ -964,9 +1288,16 @@
// Notify Telecom of the new Connection type.
// TODO: Switch out the underlying connection instead of creating a new
// one and causing UI Jank.
- boolean noActiveSimCard = SubscriptionController.getInstance()
- .getActiveSubInfoCount(phone.getContext().getOpPackageName(),
- phone.getContext().getAttributionTag()) == 0;
+ boolean noActiveSimCard;
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ noActiveSimCard = SubscriptionManagerService.getInstance()
+ .getActiveSubInfoCount(phone.getContext().getOpPackageName(),
+ phone.getContext().getAttributionTag()) == 0;
+ } else {
+ noActiveSimCard = SubscriptionController.getInstance()
+ .getActiveSubInfoCount(phone.getContext().getOpPackageName(),
+ phone.getContext().getAttributionTag()) == 0;
+ }
// If there's no active sim card and the device is in emergency mode, use E account.
addExistingConnection(mPhoneUtilsProxy.makePstnPhoneAccountHandleWithPrefix(
phone, "", isEmergencyNumber && noActiveSimCard), repConnection);
@@ -1593,7 +1924,7 @@
// Update the mEmergencyRetryCache by removing the Phone used to call the last failed emergency
// number and then moving it to the back of the queue if it is not a permanent failure cause
// from the modem.
- private void updateCachedConnectionPhonePair(TelephonyConnection c,
+ private void updateCachedConnectionPhonePair(TelephonyConnection c, Phone phone,
boolean isPermanentFailure) {
// No cache exists, create a new one.
if (mEmergencyRetryCache == null) {
@@ -1608,7 +1939,7 @@
Queue<Phone> cachedPhones = mEmergencyRetryCache.second;
// Need to refer default phone considering ImsPhone because
// cachedPhones is a list that contains default phones.
- Phone phoneUsed = c.getPhone().getDefaultPhone();
+ Phone phoneUsed = phone.getDefaultPhone();
if (phoneUsed == null) {
return;
}
@@ -1637,9 +1968,10 @@
* This will continue until there are no more slots to dial on.
*/
@VisibleForTesting
- public void retryOutgoingOriginalConnection(TelephonyConnection c, boolean isPermanentFailure) {
- int phoneId = (c.getPhone() == null) ? -1 : c.getPhone().getPhoneId();
- updateCachedConnectionPhonePair(c, isPermanentFailure);
+ public void retryOutgoingOriginalConnection(TelephonyConnection c,
+ Phone phone, boolean isPermanentFailure) {
+ int phoneId = (phone == null) ? -1 : phone.getPhoneId();
+ updateCachedConnectionPhonePair(c, phone, isPermanentFailure);
// Pull next phone to use from the cache or null if it is empty
Phone newPhoneToUse = (mEmergencyRetryCache.second != null)
? mEmergencyRetryCache.second.peek() : null;
@@ -1649,12 +1981,16 @@
Log.i(this, "retryOutgoingOriginalConnection, redialing on Phone Id: " + newPhoneToUse);
c.clearOriginalConnection();
if (phoneId != newPhoneToUse.getPhoneId()) {
- if (!mTelephonyManagerProxy.isConcurrentCallsPossible()) {
+ if (mTelephonyManagerProxy.getMaxNumberOfSimultaneouslyActiveSims() < 2) {
disconnectAllCallsOnOtherSubs(
mPhoneUtilsProxy.makePstnPhoneAccountHandle(newPhoneToUse));
}
updatePhoneAccount(c, newPhoneToUse);
}
+ if (mDomainSelectionResolver.isDomainSelectionSupported()) {
+ onEmergencyRedial(c, newPhoneToUse);
+ return;
+ }
placeOutgoingConnection(c, newPhoneToUse, videoState, connExtras);
} else {
// We have run out of Phones to use. Disconnect the call and destroy the connection.
@@ -1709,9 +2045,10 @@
final com.android.internal.telephony.Connection originalConnection;
try {
if (phone != null) {
- EmergencyNumber emergencyNumber =
- phone.getEmergencyNumberTracker().getEmergencyNumber(number);
- if (emergencyNumber != null) {
+ boolean isEmergency = mTelephonyManagerProxy.isCurrentEmergencyNumber(number);
+ Log.i(this, "placeOutgoingConnection isEmergency=" + isEmergency);
+ if (isEmergency) {
+ handleEmergencyCallStartedForSatelliteSOSMessageRecommender(connection, phone);
if (!getAllConnections().isEmpty()) {
if (!shouldHoldForEmergencyCall(phone)) {
// If we do not support holding ongoing calls for an outgoing
@@ -1747,12 +2084,25 @@
}
}
}
+ if (mDomainSelectionResolver.isDomainSelectionSupported()) {
+ if (isNormalRouting(phone, number)
+ && handleOutgoingCallConnection(number, connection,
+ phone, videoState)) {
+ /** Normal routing emergency number shall be handled
+ * by normal call domain selctor.*/
+ Log.i(this, "placeOutgoingConnection normal routing number");
+ return;
+ }
+ }
+ } else if (handleOutgoingCallConnection(number, connection,
+ phone, videoState)) {
+ return;
}
originalConnection = phone.dial(number, new ImsPhone.ImsDialArgs.Builder()
- .setVideoState(videoState)
- .setIntentExtras(extras)
- .setRttTextStream(connection.getRttTextStream())
- .build(),
+ .setVideoState(videoState)
+ .setIntentExtras(extras)
+ .setRttTextStream(connection.getRttTextStream())
+ .build(),
// We need to wait until the phone has been chosen in GsmCdmaPhone to
// register for the associated TelephonyConnection call event listeners.
connection::registerForCallEvents);
@@ -1765,12 +2115,11 @@
handleCallStateException(e, connection, phone);
return;
}
-
if (originalConnection == null) {
int telephonyDisconnectCause = android.telephony.DisconnectCause.OUTGOING_FAILURE;
// On GSM phones, null connection means that we dialed an MMI code
if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
- phone.isUtEnabled()) {
+ phone.isUtEnabled()) {
Log.d(this, "dialed MMI code");
int subId = phone.getSubId();
Log.d(this, "subId: "+subId);
@@ -1803,6 +2152,635 @@
}
}
+ private void handleOutgoingCallConnectionByCallDomainSelection(
+ int domain, Phone phone, String number, int videoState) {
+ Log.d(this, "Call Domain Selected : " + domain);
+ try {
+ Bundle extras = mNormalCallConnection.getExtras();
+ if (extras == null) {
+ extras = new Bundle();
+ }
+ extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, domain);
+ // Add flag to bundle for comparing legacy and new domain selection results. When
+ // EXTRA_COMPARE_DOMAIN flag is true, legacy domain selection result is used for
+ // placing the call and if both the results are not same then bug report is generated.
+ DeviceConfig.Properties properties = //read all telephony properties
+ DeviceConfig.getProperties(DeviceConfig.NAMESPACE_TELEPHONY);
+ boolean compareDomainSelection =
+ properties.getBoolean(KEY_DOMAIN_COMPARE_FEATURE_ENABLED_FLAG, false);
+ extras.putBoolean(PhoneConstants.EXTRA_COMPARE_DOMAIN, compareDomainSelection);
+
+ if (phone != null) {
+ Log.v(LOG_TAG, "Call dialing. Domain: " + domain);
+ com.android.internal.telephony.Connection connection =
+ phone.dial(number, new ImsPhone.ImsDialArgs.Builder()
+ .setVideoState(videoState)
+ .setIntentExtras(extras)
+ .setRttTextStream(mNormalCallConnection.getRttTextStream())
+ .setIsWpsCall(NormalCallDomainSelectionConnection
+ .isWpsCall(number))
+ .build(),
+ mNormalCallConnection::registerForCallEvents);
+
+ mNormalCallConnection.setOriginalConnection(connection);
+ mNormalCallConnection.addTelephonyConnectionListener(mNormalCallConnectionListener);
+ return;
+ } else {
+ Log.w(this, "placeOutgoingCallConnection. Dialing failed. Phone is null");
+ mNormalCallConnection.setTelephonyConnectionDisconnected(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.OUTGOING_FAILURE,
+ "Phone is null", phone.getPhoneId()));
+ mNormalCallConnection.close();
+ }
+ } catch (CallStateException e) {
+ Log.e(this, e, "Call placeOutgoingCallConnection, phone.dial exception: " + e);
+ mNormalCallConnection.unregisterForCallEvents();
+ handleCallStateException(e, mNormalCallConnection, phone);
+ } catch (Exception e) {
+ Log.e(this, e, "Call exception in placeOutgoingCallConnection:" + e);
+ mNormalCallConnection.unregisterForCallEvents();
+ mNormalCallConnection.setTelephonyConnectionDisconnected(DisconnectCauseUtil
+ .toTelecomDisconnectCause(android.telephony.DisconnectCause.OUTGOING_FAILURE,
+ e.getMessage(), phone.getPhoneId()));
+ mNormalCallConnection.close();
+ }
+ if (mDomainSelectionConnection != null) {
+ mDomainSelectionConnection.finishSelection();
+ mDomainSelectionConnection = null;
+ }
+ mNormalCallConnection = null;
+ }
+
+ private boolean handleOutgoingCallConnection(
+ String number, TelephonyConnection connection, Phone phone, int videoState) {
+
+ if (!mDomainSelectionResolver.isDomainSelectionSupported()) {
+ return false;
+ }
+
+ if (phone == null) {
+ return false;
+ }
+
+ String dialPart = PhoneNumberUtils.extractNetworkPortionAlt(
+ PhoneNumberUtils.stripSeparators(number));
+ boolean isMmiCode = (dialPart.startsWith("*") || dialPart.startsWith("#"))
+ && dialPart.endsWith("#");
+ boolean isSuppServiceCode = ImsPhoneMmiCode.isSuppServiceCodes(dialPart, phone);
+
+ // If the number is both an MMI code and a supplementary service code,
+ // it shall be treated as UT. In this case, domain selection is not performed.
+ if (isMmiCode && isSuppServiceCode) {
+ Log.v(LOG_TAG, "UT code not handled by call domain selection.");
+ return false;
+ }
+
+ // Check and select same domain as ongoing call on the same subscription (if exists)
+ int activeCallDomain = getActiveCallDomain(phone.getSubId());
+ if (activeCallDomain != NetworkRegistrationInfo.DOMAIN_UNKNOWN
+ && !NormalCallDomainSelectionConnection.isWpsCall(number)) {
+ Log.d(LOG_TAG, "Selecting same domain as ongoing call on same subId");
+ mNormalCallConnection = connection;
+ handleOutgoingCallConnectionByCallDomainSelection(
+ activeCallDomain, phone, number, videoState);
+ return true;
+ }
+
+ mDomainSelectionConnection = mDomainSelectionResolver
+ .getDomainSelectionConnection(phone, SELECTOR_TYPE_CALLING, false);
+ if (mDomainSelectionConnection == null) {
+ return false;
+ }
+ Log.d(LOG_TAG, "Call Connection created");
+ SelectionAttributes selectionAttributes =
+ new SelectionAttributes.Builder(phone.getPhoneId(), phone.getSubId(),
+ SELECTOR_TYPE_CALLING)
+ .setNumber(number)
+ .setEmergency(false)
+ .setVideoCall(VideoProfile.isVideo(videoState))
+ .build();
+
+ NormalCallDomainSelectionConnection normalCallDomainSelectionConnection =
+ (NormalCallDomainSelectionConnection) mDomainSelectionConnection;
+ CompletableFuture<Integer> future = normalCallDomainSelectionConnection
+ .createNormalConnection(selectionAttributes,
+ mCallDomainSelectionConnectionCallback);
+ Log.d(LOG_TAG, "Call Domain selection triggered.");
+
+ mNormalCallConnection = connection;
+ future.thenAcceptAsync((domain) -> handleOutgoingCallConnectionByCallDomainSelection(
+ domain, phone, number, videoState), mDomainSelectionMainExecutor);
+ return true;
+ }
+
+ @SuppressWarnings("FutureReturnValueIgnored")
+ private Connection placeEmergencyConnection(
+ final Phone phone, final ConnectionRequest request,
+ final String numberToDial, final boolean isTestEmergencyNumber,
+ final Uri handle, final boolean needToTurnOnRadio) {
+
+ final Connection resultConnection =
+ getTelephonyConnection(request, numberToDial, true, handle, phone);
+
+ if (resultConnection instanceof TelephonyConnection) {
+ Log.i(this, "placeEmergencyConnection");
+
+ mIsEmergencyCallPending = true;
+ ((TelephonyConnection) resultConnection).addTelephonyConnectionListener(
+ mEmergencyConnectionListener);
+
+ if (mEmergencyStateTracker == null) {
+ mEmergencyStateTracker = EmergencyStateTracker.getInstance();
+ }
+
+ mEmergencyCallId = resultConnection.getTelecomCallId();
+ CompletableFuture<Integer> future = mEmergencyStateTracker.startEmergencyCall(
+ phone, mEmergencyCallId, isTestEmergencyNumber);
+ future.thenAccept((result) -> {
+ Log.d(this, "startEmergencyCall-complete result=" + result);
+ if (mEmergencyCallId == null) {
+ Log.i(this, "startEmergencyCall-complete dialing canceled");
+ return;
+ }
+ if (result == android.telephony.DisconnectCause.NOT_DISCONNECTED) {
+ createEmergencyConnection(phone, (TelephonyConnection) resultConnection,
+ numberToDial, request, needToTurnOnRadio,
+ mEmergencyStateTracker.getEmergencyRegResult());
+ } else {
+ mEmergencyConnection = null;
+ String reason = "Couldn't setup emergency call";
+ if (result == android.telephony.DisconnectCause.POWER_OFF) {
+ reason = "Failed to turn on radio.";
+ }
+ ((TelephonyConnection) resultConnection).setTelephonyConnectionDisconnected(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(result, reason));
+ ((TelephonyConnection) resultConnection).close();
+ mIsEmergencyCallPending = false;
+ }
+ });
+ mEmergencyConnection = (TelephonyConnection) resultConnection;
+ return resultConnection;
+ }
+ Log.i(this, "placeEmergencyConnection returns null");
+ return null;
+ }
+
+ @SuppressWarnings("FutureReturnValueIgnored")
+ private void createEmergencyConnection(final Phone phone,
+ final TelephonyConnection resultConnection, final String number,
+ final ConnectionRequest request, boolean needToTurnOnRadio,
+ final EmergencyRegResult regResult) {
+ Log.i(this, "createEmergencyConnection");
+
+ if (phone.getImsPhone() == null) {
+ // Dialing emergency calls over IMS is not available without ImsPhone instance.
+ Log.w(this, "createEmergencyConnection no ImsPhone");
+ dialCsEmergencyCall(phone, resultConnection, request);
+ return;
+ }
+
+ ImsManager imsManager = mImsManager;
+ if (imsManager == null) {
+ // mImsManager is not null only while unit test.
+ imsManager = ImsManager.getInstance(phone.getContext(), phone.getPhoneId());
+ }
+ if (!imsManager.isNonTtyOrTtyOnVolteEnabled()) {
+ Log.w(this, "createEmergencyConnection - TTY on VoLTE is not supported.");
+ dialCsEmergencyCall(phone, resultConnection, request);
+ return;
+ }
+
+ DomainSelectionConnection selectConnection =
+ mDomainSelectionResolver.getDomainSelectionConnection(
+ phone, SELECTOR_TYPE_CALLING, true);
+
+ if (selectConnection == null) {
+ // While the domain selection service is enabled, the valid
+ // {@link DomainSelectionConnection} is not available.
+ // This can happen when the domain selection service is not available.
+ Log.w(this, "createEmergencyConnection - no selectionConnection");
+ dialCsEmergencyCall(phone, resultConnection, request);
+ return;
+ }
+
+ mEmergencyCallDomainSelectionConnection =
+ (EmergencyCallDomainSelectionConnection) selectConnection;
+
+ DomainSelectionService.SelectionAttributes attr =
+ EmergencyCallDomainSelectionConnection.getSelectionAttributes(
+ phone.getPhoneId(), phone.getSubId(), needToTurnOnRadio,
+ request.getTelecomCallId(), number, 0, null, regResult);
+
+ CompletableFuture<Integer> future =
+ mEmergencyCallDomainSelectionConnection.createEmergencyConnection(
+ attr, mEmergencyDomainSelectionConnectionCallback);
+ future.thenAcceptAsync((result) -> {
+ Log.d(this, "createEmergencyConnection-complete result=" + result);
+ if (mEmergencyCallId == null) {
+ Log.i(this, "createEmergencyConnection-complete dialing canceled");
+ return;
+ }
+ Bundle extras = request.getExtras();
+ extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, result);
+ placeOutgoingConnection(request, resultConnection, phone);
+ mIsEmergencyCallPending = false;
+ }, mDomainSelectionMainExecutor);
+ }
+
+ private void dialCsEmergencyCall(final Phone phone,
+ final TelephonyConnection resultConnection, final ConnectionRequest request) {
+ Log.d(this, "dialCsEmergencyCall");
+ Bundle extras = request.getExtras();
+ extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, NetworkRegistrationInfo.DOMAIN_CS);
+ mDomainSelectionMainExecutor.execute(
+ () -> {
+ if (mEmergencyCallId == null) {
+ Log.i(this, "dialCsEmergencyCall dialing canceled");
+ return;
+ }
+ placeOutgoingConnection(request, resultConnection, phone);
+ });
+ }
+
+ private void releaseEmergencyCallDomainSelection(boolean cancel) {
+ if (mEmergencyCallDomainSelectionConnection != null) {
+ if (cancel) mEmergencyCallDomainSelectionConnection.cancelSelection();
+ else mEmergencyCallDomainSelectionConnection.finishSelection();
+ mEmergencyCallDomainSelectionConnection = null;
+ }
+ mIsEmergencyCallPending = false;
+ mEmergencyConnection = null;
+ }
+
+ /**
+ * Determine whether reselection of domain is required or not.
+ * @param c the {@link Connection} instance.
+ * @param callFailCause the reason why CS call is disconnected. Allowed values are defined in
+ * {@link com.android.internal.telephony.CallFailCause}.
+ * @param reasonInfo the reason why PS call is disconnected.
+ * @return {@code true} if reselection of domain is required.
+ */
+ public boolean maybeReselectDomain(final TelephonyConnection c,
+ int callFailCause, ImsReasonInfo reasonInfo) {
+ if (!mDomainSelectionResolver.isDomainSelectionSupported()) return false;
+
+ Log.i(this, "maybeReselectDomain csCause=" + callFailCause + ", psCause=" + reasonInfo);
+ if (TextUtils.equals(mEmergencyCallId, c.getTelecomCallId())) {
+ if (mEmergencyCallDomainSelectionConnection != null) {
+ return maybeReselectDomainForEmergencyCall(c, callFailCause, reasonInfo);
+ }
+ Log.i(this, "maybeReselectDomain endCall()");
+ c.removeTelephonyConnectionListener(mEmergencyConnectionListener);
+ mEmergencyStateTracker.endCall(c.getTelecomCallId());
+ mEmergencyCallId = null;
+ return false;
+ }
+
+ if (reasonInfo != null) {
+ int reasonCode = reasonInfo.getCode();
+ int extraCode = reasonInfo.getExtraCode();
+ if ((reasonCode == ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL)
+ || (reasonCode == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
+ && extraCode == ImsReasonInfo.EXTRA_CODE_CALL_RETRY_EMERGENCY)) {
+ // clear normal call domain selector
+ c.removeTelephonyConnectionListener(mNormalCallConnectionListener);
+ if (mDomainSelectionConnection != null) {
+ mDomainSelectionConnection.finishSelection();
+ mDomainSelectionConnection = null;
+ }
+ mNormalCallConnection = null;
+
+ onEmergencyRedial(c, c.getPhone().getDefaultPhone());
+ return true;
+ }
+ }
+
+ return maybeReselectDomainForNormalCall(c, callFailCause, reasonInfo);
+ }
+
+ private boolean maybeReselectDomainForEmergencyCall(final TelephonyConnection c,
+ int callFailCause, ImsReasonInfo reasonInfo) {
+ Log.i(this, "maybeReselectDomainForEmergencyCall "
+ + "csCause=" + callFailCause + ", psCause=" + reasonInfo);
+
+ if (c.getOriginalConnection() != null
+ && c.getOriginalConnection().getDisconnectCause()
+ != android.telephony.DisconnectCause.LOCAL
+ && c.getOriginalConnection().getDisconnectCause()
+ != android.telephony.DisconnectCause.POWER_OFF) {
+
+ DomainSelectionService.SelectionAttributes attr =
+ EmergencyCallDomainSelectionConnection.getSelectionAttributes(
+ c.getPhone().getPhoneId(), c.getPhone().getSubId(), false,
+ c.getTelecomCallId(), c.getAddress().getSchemeSpecificPart(),
+ callFailCause, reasonInfo, null);
+
+ CompletableFuture<Integer> future =
+ mEmergencyCallDomainSelectionConnection.reselectDomain(attr);
+ // TeleponyConnection will clear original connection. Keep the reference to Phone.
+ final Phone phone = c.getPhone().getDefaultPhone();
+ if (future != null) {
+ future.thenAcceptAsync((result) -> {
+ Log.d(this, "reselectDomain-complete");
+ if (mEmergencyCallId == null) {
+ Log.i(this, "reselectDomain-complete dialing canceled");
+ return;
+ }
+ onEmergencyRedialOnDomain(c, phone, result);
+ }, mDomainSelectionMainExecutor);
+ return true;
+ }
+ }
+
+ Log.i(this, "maybeReselectDomainForEmergencyCall endCall()");
+ c.removeTelephonyConnectionListener(mEmergencyConnectionListener);
+ releaseEmergencyCallDomainSelection(true);
+ mEmergencyStateTracker.endCall(c.getTelecomCallId());
+ mEmergencyCallId = null;
+ return false;
+ }
+
+ private boolean isNormalRouting(Phone phone, String number) {
+ if (phone.getEmergencyNumberTracker() != null) {
+ EmergencyNumber num = phone.getEmergencyNumberTracker().getEmergencyNumber(number);
+ if (num != null) {
+ return num.getEmergencyCallRouting()
+ == EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL;
+ }
+ }
+ return false;
+ }
+
+ private boolean maybeReselectDomainForNormalCall(
+ final TelephonyConnection c, int callFailCause, ImsReasonInfo reasonInfo) {
+
+ Log.i(LOG_TAG, "maybeReselectDomainForNormalCall " + "csCause:" + callFailCause
+ + ", psCause:" + reasonInfo);
+
+ if (mDomainSelectionConnection != null && c.getOriginalConnection() != null) {
+ Phone phone = c.getPhone().getDefaultPhone();
+ final String number = c.getAddress().getSchemeSpecificPart();
+ int videoState = c.getOriginalConnection().getVideoState();
+ SelectionAttributes selectionAttributes = NormalCallDomainSelectionConnection
+ .getSelectionAttributes(phone.getPhoneId(), phone.getSubId(),
+ c.getTelecomCallId(), number, VideoProfile.isVideo(videoState),
+ callFailCause, reasonInfo);
+
+ Log.d(LOG_TAG, "Reselecting the domain for call");
+ mNormalCallConnection = c;
+ CompletableFuture<Integer> future = mDomainSelectionConnection
+ .reselectDomain(selectionAttributes);
+ if (future != null) {
+ future.thenAcceptAsync((result) -> {
+ onNormalCallRedial(c, phone, result, videoState);
+ }, mDomainSelectionMainExecutor);
+ return true;
+ }
+ }
+
+ c.removeTelephonyConnectionListener(mTelephonyConnectionListener);
+ if (mDomainSelectionConnection != null) {
+ mDomainSelectionConnection.finishSelection();
+ mDomainSelectionConnection = null;
+ }
+ mNormalCallConnection = null;
+ Log.d(LOG_TAG, "Reselect call domain not triggered.");
+ return false;
+ }
+
+ private void onEmergencyRedialOnDomain(TelephonyConnection connection,
+ final Phone phone, @NetworkRegistrationInfo.Domain int domain) {
+ Log.i(this, "onEmergencyRedialOnDomain phoneId=" + phone.getPhoneId()
+ + ", domain=" + DomainSelectionService.getDomainName(domain));
+
+ String number = connection.getAddress().getSchemeSpecificPart();
+
+ // Indicates undetectable emergency number with DialArgs
+ boolean isEmergency = false;
+ int eccCategory = EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+ if (connection.getEmergencyServiceCategory() != null) {
+ isEmergency = true;
+ eccCategory = connection.getEmergencyServiceCategory();
+ Log.i(this, "onEmergencyRedialOnDomain eccCategory=" + eccCategory);
+ }
+
+ Bundle extras = new Bundle();
+ extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, domain);
+
+ com.android.internal.telephony.Connection originalConnection =
+ connection.getOriginalConnection();
+ try {
+ if (phone != null) {
+ originalConnection = phone.dial(number, new ImsPhone.ImsDialArgs.Builder()
+ .setVideoState(VideoProfile.STATE_AUDIO_ONLY)
+ .setIntentExtras(extras)
+ .setRttTextStream(connection.getRttTextStream())
+ .setIsEmergency(isEmergency)
+ .setEccCategory(eccCategory)
+ .build(),
+ connection::registerForCallEvents);
+ }
+ } catch (CallStateException e) {
+ Log.e(this, e, "onEmergencyRedialOnDomain, exception: " + e);
+ }
+ if (originalConnection == null) {
+ Log.d(this, "onEmergencyRedialOnDomain, phone.dial returned null");
+ connection.setDisconnected(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.ERROR_UNSPECIFIED,
+ "unknown error"));
+ } else {
+ connection.setOriginalConnection(originalConnection);
+ }
+ }
+
+ @SuppressWarnings("FutureReturnValueIgnored")
+ private void onEmergencyRedial(final TelephonyConnection c, final Phone phone) {
+ Log.i(this, "onEmergencyRedial phoneId=" + phone.getPhoneId());
+
+ final String number = c.getAddress().getSchemeSpecificPart();
+ final boolean isTestEmergencyNumber = isEmergencyNumberTestNumber(number);
+
+ mIsEmergencyCallPending = true;
+ c.addTelephonyConnectionListener(mEmergencyConnectionListener);
+ handleEmergencyCallStartedForSatelliteSOSMessageRecommender(c, phone);
+
+ if (mEmergencyStateTracker == null) {
+ mEmergencyStateTracker = EmergencyStateTracker.getInstance();
+ }
+
+ mEmergencyCallId = c.getTelecomCallId();
+ CompletableFuture<Integer> future = mEmergencyStateTracker.startEmergencyCall(
+ phone, mEmergencyCallId, isTestEmergencyNumber);
+ future.thenAccept((result) -> {
+ Log.d(this, "onEmergencyRedial-complete result=" + result);
+ if (mEmergencyCallId == null) {
+ Log.i(this, "onEmergencyRedial-complete dialing canceled");
+ return;
+ }
+ if (result == android.telephony.DisconnectCause.NOT_DISCONNECTED) {
+ DomainSelectionConnection selectConnection =
+ mDomainSelectionResolver.getDomainSelectionConnection(
+ phone, SELECTOR_TYPE_CALLING, true);
+
+ if (selectConnection == null) {
+ Log.w(this, "onEmergencyRedial no selectionConnection, dial CS emergency call");
+ mIsEmergencyCallPending = false;
+ mDomainSelectionMainExecutor.execute(
+ () -> recreateEmergencyConnection(c, phone,
+ NetworkRegistrationInfo.DOMAIN_CS));
+ return;
+ }
+
+ mEmergencyCallDomainSelectionConnection =
+ (EmergencyCallDomainSelectionConnection) selectConnection;
+
+ mEmergencyConnection = c;
+
+ DomainSelectionService.SelectionAttributes attr =
+ EmergencyCallDomainSelectionConnection.getSelectionAttributes(
+ phone.getPhoneId(),
+ phone.getSubId(), false,
+ c.getTelecomCallId(),
+ c.getAddress().getSchemeSpecificPart(),
+ 0, null, mEmergencyStateTracker.getEmergencyRegResult());
+
+ CompletableFuture<Integer> domainFuture =
+ mEmergencyCallDomainSelectionConnection.createEmergencyConnection(
+ attr, mEmergencyDomainSelectionConnectionCallback);
+ domainFuture.thenAcceptAsync((domain) -> {
+ Log.d(this, "onEmergencyRedial-createEmergencyConnection-complete domain="
+ + domain);
+ recreateEmergencyConnection(c, phone, domain);
+ mIsEmergencyCallPending = false;
+ }, mDomainSelectionMainExecutor);
+ } else {
+ c.setTelephonyConnectionDisconnected(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(result, "unknown error"));
+ c.close();
+ mIsEmergencyCallPending = false;
+ }
+ });
+ }
+
+ private void recreateEmergencyConnection(final TelephonyConnection connection,
+ final Phone phone, final @NetworkRegistrationInfo.Domain int result) {
+ Log.d(this, "recreateEmergencyConnection result=" + result);
+ if (mEmergencyCallId == null) {
+ Log.i(this, "recreateEmergencyConnection dialing canceled");
+ return;
+ }
+ if (!getAllConnections().isEmpty()) {
+ if (!shouldHoldForEmergencyCall(phone)) {
+ // If we do not support holding ongoing calls for an outgoing
+ // emergency call, disconnect the ongoing calls.
+ for (Connection c : getAllConnections()) {
+ if (!c.equals(connection)
+ && c.getState() != Connection.STATE_DISCONNECTED
+ && c instanceof TelephonyConnection) {
+ ((TelephonyConnection) c).hangup(
+ android.telephony.DisconnectCause
+ .OUTGOING_EMERGENCY_CALL_PLACED);
+ }
+ }
+ for (Conference c : getAllConferences()) {
+ if (c.getState() != Connection.STATE_DISCONNECTED) {
+ c.onDisconnect();
+ }
+ }
+ } else if (!isVideoCallHoldAllowed(phone)) {
+ // If we do not support holding ongoing video call for an outgoing
+ // emergency call, disconnect the ongoing video call.
+ for (Connection c : getAllConnections()) {
+ if (!c.equals(connection)
+ && c.getState() == Connection.STATE_ACTIVE
+ && VideoProfile.isVideo(c.getVideoState())
+ && c instanceof TelephonyConnection) {
+ ((TelephonyConnection) c).hangup(
+ android.telephony.DisconnectCause
+ .OUTGOING_EMERGENCY_CALL_PLACED);
+ break;
+ }
+ }
+ }
+ }
+ onEmergencyRedialOnDomain(connection, phone, result);
+ }
+
+ private void onNormalCallRedial(TelephonyConnection connection, Phone phone,
+ @NetworkRegistrationInfo.Domain int domain, int videocallState) {
+
+ Log.v(LOG_TAG, "Redialing the call in domain:"
+ + DomainSelectionService.getDomainName(domain));
+
+ String number = connection.getAddress().getSchemeSpecificPart();
+
+ Bundle extras = new Bundle();
+ extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, domain);
+ // Add flag to bundle for comparing legacy and new domain selection results. When
+ // EXTRA_COMPARE_DOMAIN flag is true, legacy domain selection result is used for
+ // placing the call and if both the results are not same then bug report is generated.
+ DeviceConfig.Properties properties = //read all telephony properties
+ DeviceConfig.getProperties(DeviceConfig.NAMESPACE_TELEPHONY);
+ boolean compareDomainSelection =
+ properties.getBoolean(KEY_DOMAIN_COMPARE_FEATURE_ENABLED_FLAG, false);
+ extras.putBoolean(PhoneConstants.EXTRA_COMPARE_DOMAIN, compareDomainSelection);
+
+ com.android.internal.telephony.Connection originalConnection =
+ connection.getOriginalConnection();
+ if (originalConnection instanceof ImsPhoneConnection) {
+ if (((ImsPhoneConnection) originalConnection).isRttEnabledForCall()) {
+ extras.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_RTT, true);
+ }
+ }
+
+ try {
+ if (phone != null) {
+ Log.d(LOG_TAG, "Redialing Call.");
+ originalConnection = phone.dial(number, new ImsPhone.ImsDialArgs.Builder()
+ .setVideoState(videocallState)
+ .setIntentExtras(extras)
+ .setRttTextStream(connection.getRttTextStream())
+ .setIsEmergency(false)
+ .build(),
+ connection::registerForCallEvents);
+ }
+ } catch (Exception e) {
+ Log.e(LOG_TAG, e, "Call redial exception: " + e);
+ }
+ if (originalConnection == null) {
+ Log.e(LOG_TAG, new Exception("Phone is null"),
+ "Call redial failure due to phone.dial returned null");
+ connection.setDisconnected(mDisconnectCauseFactory.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.OUTGOING_FAILURE, "connection is null"));
+ connection.close();
+ } else {
+ connection.setOriginalConnection(originalConnection);
+ }
+ }
+
+ protected void onLocalHangup(TelephonyConnection c) {
+ if (TextUtils.equals(mEmergencyCallId, c.getTelecomCallId())) {
+ Log.i(this, "onLocalHangup " + mEmergencyCallId);
+ c.removeTelephonyConnectionListener(mEmergencyConnectionListener);
+ releaseEmergencyCallDomainSelection(true);
+ mEmergencyStateTracker.endCall(c.getTelecomCallId());
+ mEmergencyCallId = null;
+ }
+ }
+
+ @VisibleForTesting
+ public TelephonyConnection.TelephonyConnectionListener getEmergencyConnectionListener() {
+ return mEmergencyConnectionListener;
+ }
+
+ @VisibleForTesting
+ public TelephonyConnection.TelephonyConnectionListener
+ getEmergencyConnectionSatelliteListener() {
+ return mEmergencyConnectionSatelliteListener;
+ }
+
private boolean isVideoCallHoldAllowed(Phone phone) {
CarrierConfigManager cfgManager = (CarrierConfigManager)
phone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
@@ -1852,6 +2830,9 @@
case CallStateException.ERROR_OTASP_PROVISIONING_IN_PROCESS:
cause = android.telephony.DisconnectCause.OTASP_PROVISIONING_IN_PROCESS;
break;
+ case CallStateException.ERROR_FDN_BLOCKED:
+ cause = android.telephony.DisconnectCause.FDN_BLOCKED;
+ break;
}
connection.setTelephonyConnectionDisconnected(
DisconnectCauseUtil.toTelecomDisconnectCause(cause, e.getMessage(),
@@ -1966,6 +2947,7 @@
if (phone == null) {
// Do not block indefinitely.
completeConsumer.accept(false);
+ return;
}
try {
// Waiting for PhoneSwitcher to complete the operation.
@@ -2085,6 +3067,64 @@
return modemResultFuture;
}
+ private void addTelephonyConnectionListener(Conferenceable c,
+ TelephonyConnection.TelephonyConnectionListener listener) {
+ if (c instanceof TelephonyConnection) {
+ TelephonyConnection telephonyConnection = (TelephonyConnection) c;
+ telephonyConnection.addTelephonyConnectionListener(listener);
+ } else if (c instanceof ImsConference) {
+ ImsConference imsConference = (ImsConference) c;
+ TelephonyConnection conferenceHost =
+ (TelephonyConnection) imsConference.getConferenceHost();
+ conferenceHost.addTelephonyConnectionListener(listener);
+ } else {
+ throw new IllegalArgumentException(
+ "addTelephonyConnectionListener(): Unexpected conferenceable! " + c);
+ }
+ }
+
+ private CompletableFuture<Boolean> listenForHoldStateChanged(
+ @NonNull Conferenceable conferenceable) {
+ CompletableFuture<Boolean> future = new CompletableFuture<>();
+ final StateHoldingListener stateHoldingListener = new StateHoldingListener(future);
+ addTelephonyConnectionListener(conferenceable, stateHoldingListener);
+ return future;
+ }
+
+ // If there are any live calls on the other subscription, sends a hold request for the live call
+ // and waits for the STATE_HOLDING confirmation, to sequence the dial of the outgoing call.
+ private void delayDialForOtherSubHold(Phone phone, PhoneAccountHandle phoneAccountHandle,
+ Consumer<Boolean> completeConsumer) {
+ Conferenceable c = maybeHoldCallsOnOtherSubs(phoneAccountHandle);
+ if (c == null) {
+ // Nothing to hold.
+ completeConsumer.accept(true);
+ return;
+ }
+
+ if (phone == null) {
+ completeConsumer.accept(false);
+ return;
+ }
+
+ try {
+ // We have dispatched a 'hold' command to a live call (Connection or Conference) on the
+ // other sub. Listen to state changed events to see if this entered hold state.
+ CompletableFuture<Boolean> stateHoldingFuture = listenForHoldStateChanged(c);
+ // a timeout that will complete the future to not block the outgoing call indefinitely.
+ CompletableFuture<Boolean> timeout = new CompletableFuture<>();
+ phone.getContext().getMainThreadHandler().postDelayed(
+ () -> timeout.complete(false), DEFAULT_DSDA_OUTGOING_CALL_HOLD_TIMEOUT_MS);
+ // Ensure that the Consumer is completed on the main thread.
+ stateHoldingFuture.acceptEitherAsync(timeout, completeConsumer,
+ phone.getContext().getMainExecutor());
+ } catch (Exception e) {
+ Log.w(this, "delayDialForOtherSubHold - exception= "
+ + e.getMessage());
+ completeConsumer.accept(false);
+ }
+ }
+
/**
* Get the Phone to use for an emergency call of the given emergency number address:
* a) If there are multiple Phones with the Subscriptions that support the emergency number
@@ -2103,7 +3143,7 @@
for (Phone phone : mPhoneFactoryProxy.getPhones()) {
if (phone.getEmergencyNumberTracker() != null) {
if (phone.getEmergencyNumberTracker().isEmergencyNumber(
- emergencyNumberAddress, true)) {
+ emergencyNumberAddress)) {
if (isAvailableForEmergencyCalls(phone)) {
// a)
if (phone.getPhoneId() == defaultVoicePhoneId) {
@@ -2134,39 +3174,57 @@
/**
* Retrieves the most sensible Phone to use for an emergency call using the following Priority
* 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) Prioritize phones that have the dialed emergency number as part of their emergency
+ * 1) The Phone that is in emergency SMS mode
+ * 2) The phone based on User's SIM preference of Voice calling or Data in order
+ * 3) The First Phone that is currently IN_SERVICE or is available for emergency calling
+ * 4) Prioritize phones that have the dialed emergency number as part of their emergency
* number list
- * 4) If there is a PUK locked SIM, compare the SIMs that are not PUK locked. If all the SIMs
- * are locked, skip to condition 5).
- * 5) The Phone with more Capabilities.
- * 6) The First Phone that has a SIM card in it (Starting from Slot 0...N)
- * 7) The Default Phone (Currently set as Slot 0)
+ * 5) If there is a PUK locked SIM, compare the SIMs that are not PUK locked. If all the SIMs
+ * are locked, skip to condition 6).
+ * 6) The Phone with more Capabilities.
+ * 7) The First Phone that has a SIM card in it (Starting from Slot 0...N)
+ * 8) The Default Phone (Currently set as Slot 0)
*/
@VisibleForTesting
+ @NonNull
public Phone getFirstPhoneForEmergencyCall(List<Phone> phonesWithEmergencyNumber) {
- // 1)
+ int phoneCount = mTelephonyManagerProxy.getPhoneCount();
+ for (int i = 0; i < phoneCount; i++) {
+ Phone phone = mPhoneFactoryProxy.getPhone(i);
+ // 1)
+ if (phone != null && phone.isInEmergencySmsMode()) {
+ if (isAvailableForEmergencyCalls(phone)) {
+ if (phonesWithEmergencyNumber == null
+ || phonesWithEmergencyNumber.contains(phone)) {
+ return phone;
+ }
+ }
+ }
+ }
+
+ // 2)
int phoneId = mSubscriptionManagerProxy.getDefaultVoicePhoneId();
+ if (phoneId == SubscriptionManager.INVALID_PHONE_INDEX) {
+ phoneId = mSubscriptionManagerProxy.getDefaultDataPhoneId();
+ }
if (phoneId != SubscriptionManager.INVALID_PHONE_INDEX) {
- Phone defaultPhone = mPhoneFactoryProxy.getPhone(phoneId);
- if (defaultPhone != null && isAvailableForEmergencyCalls(defaultPhone)) {
+ Phone selectedPhone = mPhoneFactoryProxy.getPhone(phoneId);
+ if (selectedPhone != null && isAvailableForEmergencyCalls(selectedPhone)) {
if (phonesWithEmergencyNumber == null
- || phonesWithEmergencyNumber.contains(defaultPhone)) {
- return defaultPhone;
+ || phonesWithEmergencyNumber.contains(selectedPhone)) {
+ return selectedPhone;
}
}
}
Phone firstPhoneWithSim = null;
- int phoneCount = mTelephonyManagerProxy.getPhoneCount();
List<SlotStatus> phoneSlotStatus = new ArrayList<>(phoneCount);
for (int i = 0; i < phoneCount; i++) {
Phone phone = mPhoneFactoryProxy.getPhone(i);
if (phone == null) {
continue;
}
- // 2)
+ // 3)
if (isAvailableForEmergencyCalls(phone)) {
if (phonesWithEmergencyNumber == null
|| phonesWithEmergencyNumber.contains(phone)) {
@@ -2176,14 +3234,15 @@
return phone;
}
}
- // 5)
+ // 6)
// Store the RAF Capabilities for sorting later.
int radioAccessFamily = phone.getRadioAccessFamily();
- SlotStatus status = new SlotStatus(i, radioAccessFamily);
+ SlotStatus status = new SlotStatus(i, radioAccessFamily, phone.getSubId());
phoneSlotStatus.add(status);
Log.i(this, "getFirstPhoneForEmergencyCall, RAF:" +
- Integer.toHexString(radioAccessFamily) + " saved for Phone Id:" + i);
- // 4)
+ Integer.toHexString(radioAccessFamily) + " saved for Phone Id:" + i + " subId:"
+ + phone.getSubId());
+ // 5)
// Report Slot's PIN/PUK lock status for sorting later.
int simState = mSubscriptionManagerProxy.getSimStateForSlotIdx(i);
// Record SimState.
@@ -2192,7 +3251,8 @@
simState == TelephonyManager.SIM_STATE_PUK_REQUIRED) {
status.isLocked = true;
}
- // 3) Store if the Phone has the corresponding emergency number
+
+ // 4) Store if the Phone has the corresponding emergency number
if (phonesWithEmergencyNumber != null) {
for (Phone phoneWithEmergencyNumber : phonesWithEmergencyNumber) {
if (phoneWithEmergencyNumber != null
@@ -2201,41 +3261,49 @@
}
}
}
- // 6)
- if (firstPhoneWithSim == null && mTelephonyManagerProxy.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
+ // 7)
+ if (firstPhoneWithSim == null &&
+ (phone.getSubId() != SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
+ // The slot has a SIM card inserted (and an active subscription), 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).
firstPhoneWithSim = phone;
- Log.i(this, "getFirstPhoneForEmergencyCall, SIM card inserted, Phone Id:" +
- firstPhoneWithSim.getPhoneId());
+ Log.i(this, "getFirstPhoneForEmergencyCall, SIM with active sub, Phone Id:" +
+ firstPhoneWithSim.getPhoneId());
}
}
- // 7)
+ // 8)
if (firstPhoneWithSim == null && phoneSlotStatus.isEmpty()) {
- if (phonesWithEmergencyNumber == null || phonesWithEmergencyNumber.isEmpty()) {
- // No Phones available, get the default
- Log.i(this, "getFirstPhoneForEmergencyCall, return default phone");
- return mPhoneFactoryProxy.getDefaultPhone();
+ if (phonesWithEmergencyNumber != null) {
+ for (Phone phoneWithEmergencyNumber : phonesWithEmergencyNumber) {
+ if (phoneWithEmergencyNumber != null) {
+ return phoneWithEmergencyNumber;
+ }
+ }
}
- return phonesWithEmergencyNumber.get(0);
+
+ // No Phones available, get the default
+ Log.i(this, "getFirstPhoneForEmergencyCall, return default phone");
+ return mPhoneFactoryProxy.getDefaultPhone();
} else {
- // 5)
+ // 6)
final int defaultPhoneId = mPhoneFactoryProxy.getDefaultPhone().getPhoneId();
final Phone firstOccupiedSlot = firstPhoneWithSim;
if (!phoneSlotStatus.isEmpty()) {
+ Log.i(this, "getFirstPhoneForEmergencyCall, list size: " + phoneSlotStatus.size()
+ + " defaultPhoneId: " + defaultPhoneId + " firstOccupiedSlot: "
+ + firstOccupiedSlot);
// Only sort if there are enough elements to do so.
if (phoneSlotStatus.size() > 1) {
Collections.sort(phoneSlotStatus, (o1, o2) -> {
- // Sort by non-absent SIM.
- if (o1.simState == TelephonyManager.SIM_STATE_ABSENT
- && o2.simState != TelephonyManager.SIM_STATE_ABSENT) {
- return -1;
- }
- if (o2.simState == TelephonyManager.SIM_STATE_ABSENT
- && o1.simState != TelephonyManager.SIM_STATE_ABSENT) {
+ // Sort by non-absent SIM (SIM without active sub is considered absent).
+ if (o1.isSubActiveAndSimPresent() && !o2.isSubActiveAndSimPresent()) {
return 1;
}
+ if (o2.isSubActiveAndSimPresent() && !o1.isSubActiveAndSimPresent()) {
+ return -1;
+ }
// First start by seeing if either of the phone slots are locked. If they
// are, then sort by non-locked SIM first. If they are both locked, sort
// by capability instead.
@@ -2282,7 +3350,7 @@
"with highest capability");
return mPhoneFactoryProxy.getPhone(mostCapablePhoneId);
} else {
- // 6)
+ // 7)
return firstPhoneWithSim;
}
}
@@ -2585,8 +3653,8 @@
}
/**
- * For the passed in incoming {@link TelephonyConnection}, add
- * {@link Connection#EXTRA_ANSWERING_DROPS_FG_CALL} if there are ongoing calls on another
+ * For the passed in incoming {@link TelephonyConnection}, for non- dual active voice devices,
+ * adds {@link Connection#EXTRA_ANSWERING_DROPS_FG_CALL} if there are ongoing calls on another
* subscription (ie phone account handle) than the one passed in.
* @param connection The connection.
* @param phoneAccountHandle The {@link PhoneAccountHandle} the incoming call originated on;
@@ -2597,6 +3665,9 @@
*/
public void maybeIndicateAnsweringWillDisconnect(@NonNull TelephonyConnection connection,
@NonNull PhoneAccountHandle phoneAccountHandle) {
+ if (mTelephonyManagerProxy.isConcurrentCallsPossible()) {
+ return;
+ }
if (isCallPresentOnOtherSub(phoneAccountHandle)) {
Log.i(this, "maybeIndicateAnsweringWillDisconnect; answering call %s will cause a call "
+ "on another subscription to drop.", connection.getTelecomCallId());
@@ -2622,37 +3693,46 @@
/**
* Where there are ongoing calls on another subscription other than the one specified,
- * disconnect these calls. This is used where there is an incoming call on one sub, but there
- * are ongoing calls on another sub which need to be disconnected.
+ * disconnect these calls for non-DSDA devices. This is used where there is an incoming call on
+ * one sub, but there are ongoing calls on another sub which need to be disconnected.
* @param incomingHandle The incoming {@link PhoneAccountHandle}.
*/
public void maybeDisconnectCallsOnOtherSubs(@NonNull PhoneAccountHandle incomingHandle) {
Log.i(this, "maybeDisconnectCallsOnOtherSubs: check for calls not on %s", incomingHandle);
- maybeDisconnectCallsOnOtherSubs(getAllConnections(), incomingHandle);
+ maybeDisconnectCallsOnOtherSubs(getAllConnections(), incomingHandle,
+ mTelephonyManagerProxy);
}
/**
- * Used by {@link #maybeDisconnectCallsOnOtherSubs(PhoneAccountHandle)} to perform call
- * disconnection. This method exists as a convenience so that it is possible to unit test
+ * Used by {@link #maybeDisconnectCallsOnOtherSubs(PhoneAccountHandle)} to evaluate and perform
+ * call disconnection. This method exists as a convenience so that it is possible to unit test
* the core functionality.
* @param connections the calls to check.
* @param incomingHandle the incoming handle.
+ * @param telephonyManagerProxy the proxy to the {@link TelephonyManager} instance.
*/
@VisibleForTesting
public static void maybeDisconnectCallsOnOtherSubs(@NonNull Collection<Connection> connections,
- @NonNull PhoneAccountHandle incomingHandle) {
+ @NonNull PhoneAccountHandle incomingHandle,
+ TelephonyManagerProxy telephonyManagerProxy) {
+ if (telephonyManagerProxy.isConcurrentCallsPossible()) {
+ return;
+ }
connections.stream()
.filter(c ->
// Exclude multiendpoint calls as they're not on this device.
- (c.getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL) == 0
+ (c.getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL)
+ == 0
// Include any calls not on same sub as current connection.
&& !Objects.equals(c.getPhoneAccountHandle(), incomingHandle))
.forEach(c -> {
if (c instanceof TelephonyConnection) {
TelephonyConnection tc = (TelephonyConnection) c;
if (!tc.shouldTreatAsEmergencyCall()) {
- Log.i(LOG_TAG, "maybeDisconnectCallsOnOtherSubs: disconnect %s due to "
- + "incoming call on other sub.", tc.getTelecomCallId());
+ Log.i(LOG_TAG,
+ "maybeDisconnectCallsOnOtherSubs: disconnect %s due to "
+ + "incoming call on other sub.",
+ tc.getTelecomCallId());
// Note: intentionally calling hangup instead of onDisconnect.
// onDisconnect posts the disconnection to a handle which means that the
// disconnection will take place AFTER we answer the incoming call.
@@ -2662,6 +3742,156 @@
});
}
+ static void onHold(Conferenceable conferenceable) {
+ if (conferenceable instanceof Connection) {
+ Connection connection = (Connection) conferenceable;
+ connection.onHold();
+ } else if (conferenceable instanceof Conference) {
+ Conference conference = (Conference) conferenceable;
+ conference.onHold();
+ } else {
+ throw new IllegalArgumentException(
+ "onHold(): Unexpected conferenceable! " + conferenceable);
+ }
+ }
+
+ static void onUnhold(Conferenceable conferenceable) {
+ if (conferenceable instanceof Connection) {
+ Connection connection = (Connection) conferenceable;
+ connection.onUnhold();
+ } else if (conferenceable instanceof Conference) {
+ Conference conference = (Conference) conferenceable;
+ conference.onUnhold();
+ } else {
+ throw new IllegalArgumentException(
+ "onUnhold(): Unexpected conferenceable! " + conferenceable);
+ }
+ }
+
+ /**
+ * Evaluates whether a connection or conference exists on subscriptions other than the one
+ * corresponding to the existing {@link PhoneAccountHandle}.
+ * @param connections all individual connections, including conference participants.
+ * @param conferences all conferences.
+ * @param currentHandle the existing call handle;
+ * @param telephonyManagerProxy the proxy to the {@link TelephonyManager} instance.
+ */
+ private static @Nullable Conferenceable maybeGetFirstConferenceableFromOtherSubscription(
+ @NonNull Collection<Connection> connections,
+ @NonNull Collection<Conference> conferences,
+ @NonNull PhoneAccountHandle currentHandle,
+ TelephonyManagerProxy telephonyManagerProxy) {
+ if (!telephonyManagerProxy.isConcurrentCallsPossible()) {
+ return null;
+ }
+
+ List<Conference> otherSubConferences = conferences.stream()
+ .filter(c ->
+ // Exclude multiendpoint calls as they're not on this device.
+ (c.getConnectionProperties()
+ & Connection.PROPERTY_IS_EXTERNAL_CALL) == 0
+ // Include any conferences not on same sub as current connection.
+ && !Objects.equals(c.getPhoneAccountHandle(),
+ currentHandle))
+ .toList();
+ if (!otherSubConferences.isEmpty()) {
+ return otherSubConferences.get(0);
+ }
+
+ // Considers Connections (including conference participants) only if no conferences.
+ List<Connection> otherSubConnections = connections.stream()
+ .filter(c ->
+ // Exclude multiendpoint calls as they're not on this device.
+ (c.getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL) == 0
+ // Include any calls not on same sub as current connection.
+ && !Objects.equals(c.getPhoneAccountHandle(),
+ currentHandle)).toList();
+
+ if (!otherSubConnections.isEmpty()) {
+ if (otherSubConnections.size() > 1) {
+ Log.w(LOG_TAG, "Unexpected number of connections: "
+ + otherSubConnections.size() + " on other sub!");
+ }
+ return otherSubConnections.get(0);
+ }
+ return null;
+ }
+
+ /**
+ * Where there are ongoing calls on multiple subscriptions for DSDA devices, let the 'hold'
+ * button perform an unhold on the other sub's Connection or Conference. This covers for Dialer
+ * apps that may not have a dedicated 'swap' button for calls across different subs.
+ * @param currentHandle The {@link PhoneAccountHandle} of the current active voice call.
+ */
+ public void maybeUnholdCallsOnOtherSubs(
+ @NonNull PhoneAccountHandle currentHandle) {
+ Log.i(this, "maybeUnholdCallsOnOtherSubs: check for calls not on %s",
+ currentHandle);
+ maybeUnholdCallsOnOtherSubs(getAllConnections(), getAllConferences(),
+ currentHandle, mTelephonyManagerProxy);
+ }
+
+ /**
+ * Where there are ongoing calls on multiple subscriptions for DSDA devices, let the 'hold'
+ * button perform an unhold on the other sub's Connection or Conference. This is a convenience
+ * method to unit test the core functionality.
+ *
+ * @param connections all individual connections, including conference participants.
+ * @param conferences all conferences.
+ * @param currentHandle The {@link PhoneAccountHandle} of the current active call.
+ * @param telephonyManagerProxy the proxy to the {@link TelephonyManager} instance.
+ */
+ @VisibleForTesting
+ protected static void maybeUnholdCallsOnOtherSubs(@NonNull Collection<Connection> connections,
+ @NonNull Collection<Conference> conferences,
+ @NonNull PhoneAccountHandle currentHandle,
+ TelephonyManagerProxy telephonyManagerProxy) {
+ Conferenceable c = maybeGetFirstConferenceableFromOtherSubscription(
+ connections, conferences, currentHandle, telephonyManagerProxy);
+ if (c != null) {
+ onUnhold(c);
+ }
+ }
+
+ /**
+ * For DSDA devices, when an outgoing call is dialed out from the 2nd sub, holds the first call.
+ *
+ * @param outgoingHandle The outgoing {@link PhoneAccountHandle}.
+ * @return the Conferenceable representing the Connection or Conference to be held.
+ */
+ private @Nullable Conferenceable maybeHoldCallsOnOtherSubs(
+ @NonNull PhoneAccountHandle outgoingHandle) {
+ Log.i(this, "maybeHoldCallsOnOtherSubs: check for calls not on %s",
+ outgoingHandle);
+ return maybeHoldCallsOnOtherSubs(getAllConnections(), getAllConferences(),
+ outgoingHandle, mTelephonyManagerProxy);
+ }
+
+ /**
+ * For DSDA devices, when an outgoing call is dialed out from the 2nd sub, holds the first call.
+ * This is a convenience method to unit test the core functionality.
+ *
+ * @param connections all individual connections, including conference participants.
+ * @param conferences all conferences.
+ * @param outgoingHandle The outgoing {@link PhoneAccountHandle}.
+ * @param telephonyManagerProxy the proxy to the {@link TelephonyManager} instance.
+ * @return the {@link Conferenceable} representing the Connection or Conference to be held.
+ */
+ @VisibleForTesting
+ protected static @Nullable Conferenceable maybeHoldCallsOnOtherSubs(
+ @NonNull Collection<Connection> connections,
+ @NonNull Collection<Conference> conferences,
+ @NonNull PhoneAccountHandle outgoingHandle,
+ TelephonyManagerProxy telephonyManagerProxy) {
+ Conferenceable c = maybeGetFirstConferenceableFromOtherSubscription(
+ connections, conferences, outgoingHandle, telephonyManagerProxy);
+ if (c != null) {
+ onHold(c);
+ return c;
+ }
+ return null;
+ }
+
private void disconnectAllCallsOnOtherSubs (@NonNull PhoneAccountHandle handle) {
Collection<Connection>connections = getAllConnections();
connections.stream()
@@ -2680,4 +3910,35 @@
}
});
}
+
+ private @NetworkRegistrationInfo.Domain int getActiveCallDomain(int subId) {
+ for (Connection c: getAllConnections()) {
+ if ((c instanceof TelephonyConnection)) {
+ TelephonyConnection connection = (TelephonyConnection) c;
+ Phone phone = connection.getPhone();
+ if (phone == null) {
+ continue;
+ }
+
+ if (phone.getSubId() == subId) {
+ if (phone instanceof GsmCdmaPhone) {
+ return NetworkRegistrationInfo.DOMAIN_CS;
+ } else if (phone instanceof ImsPhone) {
+ return NetworkRegistrationInfo.DOMAIN_PS;
+ }
+ }
+ }
+ }
+ return NetworkRegistrationInfo.DOMAIN_UNKNOWN;
+ }
+
+ private void handleEmergencyCallStartedForSatelliteSOSMessageRecommender(
+ @NonNull TelephonyConnection connection, @NonNull Phone phone) {
+ if (mSatelliteSOSMessageRecommender == null) {
+ mSatelliteSOSMessageRecommender = new SatelliteSOSMessageRecommender(
+ phone.getContext().getMainLooper());
+ }
+ connection.addTelephonyConnectionListener(mEmergencyConnectionSatelliteListener);
+ mSatelliteSOSMessageRecommender.onEmergencyCallStarted(connection, phone);
+ }
}
diff --git a/src/com/android/services/telephony/domainselection/CrossSimRedialingController.java b/src/com/android/services/telephony/domainselection/CrossSimRedialingController.java
new file mode 100644
index 0000000..f1bb78c
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/CrossSimRedialingController.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2023 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.domainselection;
+
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.REDIAL_TIMER_DISABLED;
+import static android.telephony.PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.os.SystemProperties;
+import android.telephony.Annotation.PreciseDisconnectCauses;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.LocalLog;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+
+import java.util.ArrayList;
+
+/** Controls the cross stack redialing. */
+public class CrossSimRedialingController extends Handler {
+ private static final String TAG = "CrossSimRedialingCtrl";
+ private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1);
+ private static final int LOG_SIZE = 50;
+
+ /** An interface of a helper to check emergency number. */
+ public interface EmergencyNumberHelper {
+ /**
+ * Returns whether the number is an emergency number in the given modem slot.
+ *
+ * @param slotId The slot id to be checked.
+ * @param number The number.
+ * @return {@code true} if the number is an emergency number in the given slot.
+ */
+ boolean isEmergencyNumber(int slotId, String number);
+ }
+
+ @VisibleForTesting
+ public static final int MSG_CROSS_STACK_TIMEOUT = 1;
+ @VisibleForTesting
+ public static final int MSG_QUICK_CROSS_STACK_TIMEOUT = 2;
+
+ private static final LocalLog sLocalLog = new LocalLog(LOG_SIZE);
+
+ private final ArrayList<Integer> mStackSelectionHistory = new ArrayList<>();
+ private final ArrayList<Integer> mPermanentRejectedSlots = new ArrayList<>();
+ private final TelephonyManager mTelephonyManager;
+
+ private EmergencyNumberHelper mEmergencyNumberHelper = new EmergencyNumberHelper() {
+ @Override
+ public boolean isEmergencyNumber(int slotId, String number) {
+ // TODO(b/258112541) Add System api to check emergency number per subscription.
+ try {
+ Phone phone = PhoneFactory.getPhone(slotId);
+ if (phone != null
+ && phone.getEmergencyNumberTracker() != null
+ && phone.getEmergencyNumberTracker().isEmergencyNumber(number)) {
+ return true;
+ }
+ } catch (IllegalStateException e) {
+ loge("isEmergencyNumber e=" + e);
+ }
+ return false;
+ }
+ };
+
+ private int mModemCount;
+
+ /** A cache of the carrier config {@link #KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT}. */
+ private int mCrossStackTimer;
+ /** A cache of the carrier config {@link #KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT}. */
+ private int mQuickCrossStackTimer;
+ /**
+ * A cache of the carrier config
+ * {@link #KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL}.
+ */
+ private boolean mStartQuickCrossStackTimerWhenInService;
+
+ private String mCallId;
+ private EmergencyCallDomainSelector mSelector;
+ private String mNumber;
+ private int mSlotId;
+ private int mSubId;
+
+ /**
+ * Creates an instance.
+ *
+ * @param context The Context this is associated with.
+ * @param looper The Looper to run the CrossSimRedialingController.
+ */
+ public CrossSimRedialingController(@NonNull Context context, @NonNull Looper looper) {
+ super(looper);
+
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
+ }
+
+ /** For unit test only */
+ @VisibleForTesting
+ public CrossSimRedialingController(@NonNull Context context, @NonNull Looper looper,
+ EmergencyNumberHelper emergencyNumberHelper) {
+ this(context, looper);
+
+ mEmergencyNumberHelper = emergencyNumberHelper;
+ }
+
+ /**
+ * Starts the timer.
+ *
+ * @param context The Context this is associated with.
+ * @param selector The instance of {@link EmergencyCallDomainSelector}.
+ * @param callId The call identifier.
+ * @param number The dialing number.
+ * @param inService Indiates that normal service is available.
+ * @param roaming Indicates that it's in roaming or non-domestic network.
+ * @param modemCount The number of active modem count
+ */
+ public void startTimer(@NonNull Context context,
+ @NonNull EmergencyCallDomainSelector selector,
+ @NonNull String callId, @NonNull String number,
+ boolean inService, boolean roaming, int modemCount) {
+ logi("startTimer callId=" + callId
+ + ", in service=" + inService + ", roaming=" + roaming);
+
+ if (!TextUtils.equals(mCallId, callId)) {
+ logi("startTimer callId changed");
+ mCallId = callId;
+ mStackSelectionHistory.clear();
+ mPermanentRejectedSlots.clear();
+ }
+ mSelector = selector;
+ mSlotId = selector.getSlotId();
+ mSubId = selector.getSubId();
+ mNumber = number;
+ mModemCount = modemCount;
+
+ updateCarrierConfiguration(context);
+
+ boolean firstAttempt = !mStackSelectionHistory.contains(mSlotId);
+ logi("startTimer slot=" + mSlotId + ", firstAttempt=" + firstAttempt);
+ mStackSelectionHistory.add(mSlotId);
+
+ if (firstAttempt && mQuickCrossStackTimer > REDIAL_TIMER_DISABLED && !roaming) {
+ if (inService || !mStartQuickCrossStackTimerWhenInService) {
+ logi("startTimer quick timer started");
+ sendEmptyMessageDelayed(MSG_QUICK_CROSS_STACK_TIMEOUT,
+ mQuickCrossStackTimer);
+ return;
+ }
+ }
+
+ if (mCrossStackTimer > REDIAL_TIMER_DISABLED) {
+ logi("startTimer timer started");
+ sendEmptyMessageDelayed(MSG_CROSS_STACK_TIMEOUT, mCrossStackTimer);
+ }
+ }
+
+ /** Stops the timers. */
+ public void stopTimer() {
+ logi("stopTimer");
+ removeMessages(MSG_CROSS_STACK_TIMEOUT);
+ removeMessages(MSG_QUICK_CROSS_STACK_TIMEOUT);
+ }
+
+ /**
+ * Informs the call failure.
+ * @param cause The call failure cause.
+ */
+ public void notifyCallFailure(@PreciseDisconnectCauses int cause) {
+ logi("notifyCallFailure cause=" + cause);
+ if (cause == EMERGENCY_PERM_FAILURE) {
+ mPermanentRejectedSlots.add(mSlotId);
+ }
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_CROSS_STACK_TIMEOUT:
+ case MSG_QUICK_CROSS_STACK_TIMEOUT:
+ handleCrossStackTimeout();
+ break;
+ default:
+ super.handleMessage(msg);
+ break;
+ }
+ }
+
+ private void handleCrossStackTimeout() {
+ logi("handleCrossStackTimeout");
+
+ if (isThereOtherSlot()) {
+ mSelector.notifyCrossStackTimerExpired();
+ }
+ }
+
+ /**
+ * Returns whether there is another slot emergency capable.
+ *
+ * @return {@code true} if there is another slot emergency capable,
+ * {@code false} otherwise.
+ */
+ public boolean isThereOtherSlot() {
+ logi("isThereOtherSlot modemCount=" + mModemCount);
+ if (mModemCount < 2) return false;
+
+ for (int i = 0; i < mModemCount; i++) {
+ if (i == mSlotId) continue;
+
+ if (mPermanentRejectedSlots.contains(i)) {
+ logi("isThereOtherSlot index=" + i + ", permanent rejected");
+ continue;
+ }
+
+ int simState = mTelephonyManager.getSimState(i);
+ if (simState != TelephonyManager.SIM_STATE_READY) {
+ logi("isThereOtherSlot index=" + i + ", simState=" + simState);
+ continue;
+ }
+
+ if (mEmergencyNumberHelper.isEmergencyNumber(i, mNumber)) {
+ logi("isThereOtherSlot index=" + i + ", found");
+ return true;
+ } else {
+ logi("isThereOtherSlot index=" + i + ", not emergency number");
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Caches the configuration.
+ */
+ private void updateCarrierConfiguration(Context context) {
+ CarrierConfigManager configMgr = context.getSystemService(CarrierConfigManager.class);
+ PersistableBundle b = configMgr.getConfigForSubId(mSubId,
+ KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT,
+ KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT,
+ KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL);
+ if (b == null) {
+ b = CarrierConfigManager.getDefaultConfig();
+ }
+
+ mCrossStackTimer = b.getInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT) * 1000;
+ mQuickCrossStackTimer =
+ b.getInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT) * 1000;
+ mStartQuickCrossStackTimerWhenInService =
+ b.getBoolean(KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL);
+
+ logi("updateCarrierConfiguration "
+ + ", crossStackTimer=" + mCrossStackTimer
+ + ", quickCrossStackTimer=" + mQuickCrossStackTimer
+ + ", startQuickTimerInService=" + mStartQuickCrossStackTimerWhenInService);
+ }
+
+ /** Destroys the instance. */
+ public void destroy() {
+ if (DBG) logd("destroy");
+
+ removeMessages(MSG_CROSS_STACK_TIMEOUT);
+ removeMessages(MSG_QUICK_CROSS_STACK_TIMEOUT);
+ }
+
+ private void logd(String s) {
+ Log.d(TAG, "[" + mSlotId + "|" + mSubId + "] " + s);
+ }
+
+ private void logi(String s) {
+ Log.i(TAG, "[" + mSlotId + "|" + mSubId + "] " + s);
+ sLocalLog.log(s);
+ }
+
+ private void loge(String s) {
+ Log.e(TAG, "[" + mSlotId + "|" + mSubId + "] " + s);
+ sLocalLog.log(s);
+ }
+}
diff --git a/src/com/android/services/telephony/domainselection/DomainSelectorBase.java b/src/com/android/services/telephony/domainselection/DomainSelectorBase.java
new file mode 100644
index 0000000..1a7c992
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/DomainSelectorBase.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.DomainSelector;
+import android.telephony.TransportSelectorCallback;
+import android.telephony.WwanSelectorCallback;
+import android.util.IndentingPrintWriter;
+import android.util.LocalLog;
+import android.util.Log;
+
+import com.android.internal.annotations.Keep;
+
+import java.io.PrintWriter;
+
+/**
+ * An abstract base class to implement domain selector for a specific use case.
+ */
+@Keep
+public abstract class DomainSelectorBase extends Handler implements DomainSelector {
+ /**
+ * A listener used to inform the DomainSelectorService that this DomainSelector has been
+ * destroyed.
+ */
+ public interface DestroyListener {
+ /**
+ * Called when the specified domain selector is being destroyed.
+ * This MUST be called when this domain selector is no longer available after
+ * {@link DomainSelector#finishSelection} called.
+ */
+ void onDomainSelectorDestroyed(DomainSelectorBase selector);
+ }
+
+ // Persistent Logging
+ protected final LocalLog mEventLog = new LocalLog(30);
+ protected final Context mContext;
+ protected final ImsStateTracker mImsStateTracker;
+ protected SelectionAttributes mSelectionAttributes;
+ protected TransportSelectorCallback mTransportSelectorCallback;
+ protected WwanSelectorCallback mWwanSelectorCallback;
+ private final int mSlotId;
+ private final int mSubId;
+ private final DestroyListener mDestroyListener;
+ private final String mLogTag;
+
+ public DomainSelectorBase(Context context, int slotId, int subId, @NonNull Looper looper,
+ @NonNull ImsStateTracker imsStateTracker, @NonNull DestroyListener destroyListener,
+ String logTag) {
+ super(looper);
+ mContext = context;
+ mImsStateTracker = imsStateTracker;
+ mSlotId = slotId;
+ mSubId = subId;
+ mDestroyListener = destroyListener;
+ mLogTag = logTag;
+ }
+
+ /**
+ * Selects a domain for the specified attributes and callback.
+ *
+ * @param attr The attributes required to determine the domain.
+ * @param callback The callback called when the transport selection is completed.
+ */
+ public abstract void selectDomain(SelectionAttributes attr, TransportSelectorCallback callback);
+
+ /**
+ * Destroys this domain selector.
+ */
+ protected void destroy() {
+ removeCallbacksAndMessages(null);
+ notifyDomainSelectorDestroyed();
+ }
+
+ /**
+ * Notifies the application that this domain selector is being destroyed.
+ */
+ protected void notifyDomainSelectorDestroyed() {
+ if (mDestroyListener != null) {
+ mDestroyListener.onDomainSelectorDestroyed(this);
+ }
+ }
+
+ /**
+ * Returns the slot index for this domain selector.
+ */
+ protected int getSlotId() {
+ return mSlotId;
+ }
+
+ /**
+ * Returns the subscription index for this domain selector.
+ */
+ protected int getSubId() {
+ return mSubId;
+ }
+
+ /**
+ * Dumps this instance into a readable format for dumpsys usage.
+ */
+ protected void dump(@NonNull PrintWriter pw) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.println(mLogTag + ":");
+ ipw.increaseIndent();
+ ipw.println("SlotId: " + getSlotId());
+ ipw.println("SubId: " + getSubId());
+ mEventLog.dump(ipw);
+ ipw.decreaseIndent();
+ }
+
+ protected void logd(String s) {
+ Log.d(mLogTag, "[" + getSlotId() + "|" + getSubId() + "] " + s);
+ }
+
+ protected void logi(String s) {
+ Log.i(mLogTag, "[" + getSlotId() + "|" + getSubId() + "] " + s);
+ mEventLog.log("[" + getSlotId() + "|" + getSubId() + "] " + s);
+ }
+
+ protected void loge(String s) {
+ Log.e(mLogTag, "[" + getSlotId() + "|" + getSubId() + "] " + s);
+ mEventLog.log("[" + getSlotId() + "|" + getSubId() + "] " + s);
+ }
+}
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
new file mode 100644
index 0000000..b1c288c
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -0,0 +1,1455 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.CDMA2000;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.NGRAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.UNKNOWN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.UTRAN;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
+import static android.telephony.BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.DOMAIN_CS;
+import static android.telephony.CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP;
+import static android.telephony.CarrierConfigManager.ImsEmergency.DOMAIN_PS_NON_3GPP;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_SCAN_TIMER_SEC_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE;
+import static android.telephony.CarrierConfigManager.ImsEmergency.VOWIFI_REQUIRES_SETTING_ENABLED;
+import static android.telephony.CarrierConfigManager.ImsEmergency.VOWIFI_REQUIRES_VALID_EID;
+import static android.telephony.CarrierConfigManager.ImsWfc.KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL;
+import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
+import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING;
+import static android.telephony.PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
+import static android.telephony.PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.CancellationSignal;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.os.PowerManager;
+import android.os.SystemProperties;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
+import android.telephony.AccessNetworkConstants.TransportType;
+import android.telephony.BarringInfo;
+import android.telephony.CarrierConfigManager;
+import android.telephony.DisconnectCause;
+import android.telephony.DomainSelectionService;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.EmergencyRegResult;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.TransportSelectorCallback;
+import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ProvisioningManager;
+import android.text.TextUtils;
+import android.util.LocalLog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.IntFunction;
+
+/**
+ * Selects the domain for emergency calling.
+ */
+public class EmergencyCallDomainSelector extends DomainSelectorBase
+ implements ImsStateTracker.BarringInfoListener, ImsStateTracker.ImsStateListener {
+ private static final String TAG = "DomainSelector-EmergencyCall";
+ private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1);
+ private static final int LOG_SIZE = 50;
+
+ private static final int MSG_START_DOMAIN_SELECTION = 11;
+ @VisibleForTesting
+ public static final int MSG_NETWORK_SCAN_TIMEOUT = 12;
+ private static final int MSG_NETWORK_SCAN_RESULT = 13;
+
+ private static final int NOT_SUPPORTED = -1;
+
+ private static final LocalLog sLocalLog = new LocalLog(LOG_SIZE);
+
+ private static final ArrayList<String> sAllowOnlyWithSimReady = new ArrayList<>();
+
+ static {
+ // b/177967010, JP
+ sAllowOnlyWithSimReady.add("jp"); // Japan
+ // b/198393826, DE
+ sAllowOnlyWithSimReady.add("de"); // Germany
+ // b/230443699, IN and SG
+ sAllowOnlyWithSimReady.add("in"); // India
+ sAllowOnlyWithSimReady.add("sg"); // Singapore
+ }
+
+ /**
+ * Network callback used to determine whether Wi-Fi is connected or not.
+ */
+ private ConnectivityManager.NetworkCallback mNetworkCallback =
+ new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onAvailable(Network network) {
+ logi("onAvailable: " + network);
+ mWiFiAvailable = true;
+ }
+
+ @Override
+ public void onLost(Network network) {
+ logi("onLost: " + network);
+ mWiFiAvailable = false;
+ }
+
+ @Override
+ public void onUnavailable() {
+ logi("onUnavailable");
+ mWiFiAvailable = false;
+ }
+ };
+
+ private boolean mIsEmergencyBarred;
+ private boolean mImsRegistered;
+ private boolean mIsVoiceCapable;
+ private boolean mBarringInfoReceived;
+ private boolean mImsRegStateReceived;
+ private boolean mMmTelCapabilitiesReceived;
+ private int mVoWifiTrialCount = 0;
+
+ private @RadioAccessNetworkType int mCsNetworkType = UNKNOWN;
+ private @RadioAccessNetworkType int mPsNetworkType = UNKNOWN;
+ private @RadioAccessNetworkType int mLastNetworkType = UNKNOWN;
+ private @TransportType int mLastTransportType = TRANSPORT_TYPE_INVALID;
+ private @DomainSelectionService.EmergencyScanType int mScanType;
+ private @RadioAccessNetworkType List<Integer> mLastPreferredNetworks;
+ private boolean mIsTestEmergencyNumber;
+
+ private CancellationSignal mCancelSignal;
+
+ private @RadioAccessNetworkType int[] mImsRatsConfig;
+ private @RadioAccessNetworkType int[] mCsRatsConfig;
+ private @RadioAccessNetworkType int[] mImsRoamRatsConfig;
+ private @RadioAccessNetworkType int[] mCsRoamRatsConfig;
+ private @CarrierConfigManager.ImsEmergency.EmergencyDomain int[] mDomainPreference;
+ private @CarrierConfigManager.ImsEmergency.EmergencyDomain int[] mDomainPreferenceRoam;
+ private List<String> mCdmaPreferredNumbers;
+ private boolean mPreferImsWhenCallsOnCs;
+ private int mVoWifiRequiresCondition;
+ private boolean mIsMonitoringConnectivity;
+ private boolean mWiFiAvailable;
+ private int mScanTimeout;
+ private int mMaxNumOfVoWifiTries;
+ private boolean mVoWifiOverEmergencyPdn;
+ private @CarrierConfigManager.ImsEmergency.EmergencyScanType int mPreferredNetworkScanType;
+ private int mCallSetupTimerOnCurrentRat;
+ private boolean mRequiresImsRegistration;
+ private boolean mRequiresVoLteEnabled;
+ private boolean mLtePreferredAfterNrFailure;
+ private boolean mTryCsWhenPsFails;
+ private boolean mTryEpsFallback;
+ private int mModemCount;
+
+ /** Indicates whether this instance is deactivated. */
+ private boolean mDestroyed = false;
+ /** Indicates whether emergency network scan is requested. */
+ private boolean mIsScanRequested = false;
+ /** Indicates whether selected domain has been notified. */
+ private boolean mDomainSelected = false;
+ /** Indicates whether the cross sim redialing timer has expired. */
+ private boolean mCrossStackTimerExpired = false;
+
+ /**
+ * Indicates whether {@link #selectDomain(SelectionAttributes, TransportSelectionCallback)}
+ * is called or not.
+ */
+ private boolean mDomainSelectionRequested = false;
+
+ private final PowerManager.WakeLock mPartialWakeLock;
+ private final CrossSimRedialingController mCrossSimRedialingController;
+
+ /** Constructor. */
+ public EmergencyCallDomainSelector(Context context, int slotId, int subId,
+ @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
+ @NonNull DestroyListener destroyListener,
+ @NonNull CrossSimRedialingController csrController) {
+ super(context, slotId, subId, looper, imsStateTracker, destroyListener, TAG);
+
+ mImsStateTracker.addBarringInfoListener(this);
+ mImsStateTracker.addImsStateListener(this);
+
+ PowerManager pm = context.getSystemService(PowerManager.class);
+ mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+
+ mCrossSimRedialingController = csrController;
+ acquireWakeLock();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ if (mDestroyed) return;
+
+ switch(msg.what) {
+ case MSG_START_DOMAIN_SELECTION:
+ startDomainSelection();
+ break;
+
+ case MSG_NETWORK_SCAN_TIMEOUT:
+ handleNetworkScanTimeout();
+ break;
+
+ case MSG_NETWORK_SCAN_RESULT:
+ handleScanResult((EmergencyRegResult) msg.obj);
+ break;
+
+ default:
+ super.handleMessage(msg);
+ break;
+ }
+ }
+
+ /**
+ * Handles the scan result.
+ *
+ * @param result The scan result.
+ */
+ private void handleScanResult(EmergencyRegResult result) {
+ logi("handleScanResult result=" + result);
+
+ if (mLastTransportType == TRANSPORT_TYPE_WLAN) {
+ logi("handleScanResult timer expired, WLAN has been selected, ignore stale result");
+ return;
+ }
+
+ // Detected the country and found that emergency calls are not allowed with this slot.
+ if (!allowEmergencyCalls(result)) {
+ terminateSelectionPermanentlyForSlot();
+ return;
+ }
+
+ if (result.getAccessNetwork() == UNKNOWN) {
+ if ((mPreferredNetworkScanType == SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE)
+ && (mScanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE)) {
+ mScanType = DomainSelectionService.SCAN_TYPE_LIMITED_SERVICE;
+ mWwanSelectorCallback.onRequestEmergencyNetworkScan(
+ mLastPreferredNetworks, mScanType, mCancelSignal,
+ (regResult) -> {
+ logi("requestScan-onComplete");
+ sendMessage(obtainMessage(MSG_NETWORK_SCAN_RESULT, regResult));
+ });
+ } else {
+ // Continuous scan, do not start a new timer.
+ requestScan(false);
+ }
+ return;
+ }
+
+ removeMessages(MSG_NETWORK_SCAN_TIMEOUT);
+ onWwanNetworkTypeSelected(getAccessNetworkType(result));
+ mCancelSignal = null;
+ }
+
+ /**
+ * Determines the scanned network type.
+ *
+ * @param result The result of network scan.
+ * @return The selected network type.
+ */
+ private @RadioAccessNetworkType int getAccessNetworkType(EmergencyRegResult result) {
+ int accessNetworkType = result.getAccessNetwork();
+ if (accessNetworkType != EUTRAN) return accessNetworkType;
+
+ int regState = result.getRegState();
+ int domain = result.getDomain();
+
+ // Emergency is not supported with LTE, but CSFB is possible.
+ if ((regState == REGISTRATION_STATE_HOME || regState == REGISTRATION_STATE_ROAMING)
+ && (domain == NetworkRegistrationInfo.DOMAIN_CS)) {
+ logi("getAccessNetworkType emergency not supported but CSFB is possible");
+ accessNetworkType = UTRAN;
+ }
+
+ return accessNetworkType;
+ }
+
+ @Override
+ public void cancelSelection() {
+ logi("cancelSelection");
+ finishSelection();
+ }
+
+ @Override
+ public void reselectDomain(SelectionAttributes attr) {
+ logi("reselectDomain attr=" + attr);
+ mSelectionAttributes = attr;
+ post(() -> { reselectDomain(); });
+ }
+
+ private void reselectDomain() {
+ logi("reselectDomain tryCsWhenPsFails=" + mTryCsWhenPsFails);
+
+ int cause = mSelectionAttributes.getCsDisconnectCause();
+ mCrossSimRedialingController.notifyCallFailure(cause);
+
+ // TODO(b/258112541) make EMERGENCY_PERM_FAILURE and EMERGENCY_TEMP_FAILURE public api
+ if (cause == EMERGENCY_PERM_FAILURE
+ || cause == EMERGENCY_TEMP_FAILURE) {
+ logi("reselectDomain should redial on the other subscription");
+ terminateSelectionForCrossSimRedialing(cause == EMERGENCY_PERM_FAILURE);
+ return;
+ }
+
+ if (mCrossStackTimerExpired) {
+ logi("reselectDomain cross stack timer expired");
+ terminateSelectionForCrossSimRedialing(false);
+ return;
+ }
+
+ if (mIsTestEmergencyNumber) {
+ selectDomainForTestEmergencyNumber();
+ return;
+ }
+
+ if (mTryCsWhenPsFails) {
+ mTryCsWhenPsFails = false;
+ // Initial state was CSFB available and dial PS failed.
+ // Dial CS for CSFB instead of scanning with CS preferred network list.
+ logi("reselectDomain tryCs=" + accessNetworkTypeToString(mCsNetworkType));
+ if (mCsNetworkType != UNKNOWN) {
+ onWwanNetworkTypeSelected(mCsNetworkType);
+ return;
+ }
+ }
+
+ if (mLastTransportType == TRANSPORT_TYPE_WLAN) {
+ // Dialing over Wi-Fi failed. Try scanning cellular networks.
+ onWwanSelected(this::reselectDomainInternal);
+ return;
+ }
+
+ requestScan(true);
+ mDomainSelected = false;
+ }
+
+ private void reselectDomainInternal() {
+ post(() -> {
+ requestScan(true, false, true);
+ mDomainSelected = false;
+ });
+ }
+
+ @Override
+ public void finishSelection() {
+ logi("finishSelection");
+ destroy();
+ }
+
+ @Override
+ public void onBarringInfoUpdated(BarringInfo barringInfo) {
+ if (mDestroyed) return;
+
+ mBarringInfoReceived = true;
+ BarringInfo.BarringServiceInfo serviceInfo =
+ barringInfo.getBarringServiceInfo(BARRING_SERVICE_TYPE_EMERGENCY);
+ mIsEmergencyBarred = serviceInfo.isBarred();
+ logi("onBarringInfoUpdated emergencyBarred=" + mIsEmergencyBarred
+ + ", serviceInfo=" + serviceInfo);
+ selectDomain();
+ }
+
+ @Override
+ public void selectDomain(SelectionAttributes attr, TransportSelectorCallback cb) {
+ logi("selectDomain attr=" + attr);
+ mTransportSelectorCallback = cb;
+ mSelectionAttributes = attr;
+ mIsTestEmergencyNumber = isTestEmergencyNumber(attr.getNumber());
+
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ mModemCount = tm.getActiveModemCount();
+
+ sendEmptyMessage(MSG_START_DOMAIN_SELECTION);
+ }
+
+ private void startDomainSelection() {
+ logi("startDomainSelection modemCount=" + mModemCount);
+ updateCarrierConfiguration();
+ mDomainSelectionRequested = true;
+ startCrossStackTimer();
+ if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ selectDomain();
+ } else {
+ logi("startDomainSelection invalid subId");
+ onImsRegistrationStateChanged();
+ onImsMmTelCapabilitiesChanged();
+ }
+ }
+
+ @Override
+ public void onImsMmTelFeatureAvailableChanged() {
+ // DOMAIN_CS shall be selected when ImsService is not available.
+ // TODO(b/258289015) Recover the temporary failure in ImsService connection.
+ }
+
+ @Override
+ public void onImsRegistrationStateChanged() {
+ mImsRegStateReceived = true;
+ mImsRegistered = mImsStateTracker.isImsRegistered();
+ logi("onImsRegistrationStateChanged " + mImsRegistered);
+ selectDomain();
+ }
+
+ @Override
+ public void onImsMmTelCapabilitiesChanged() {
+ mMmTelCapabilitiesReceived = true;
+ mIsVoiceCapable = mImsStateTracker.isImsVoiceCapable();
+ logi("onImsMmTelCapabilitiesChanged " + mIsVoiceCapable);
+ selectDomain();
+ }
+
+ /**
+ * Caches the configuration.
+ */
+ private void updateCarrierConfiguration() {
+ CarrierConfigManager configMgr = mContext.getSystemService(CarrierConfigManager.class);
+ PersistableBundle b = configMgr.getConfigForSubId(getSubId());
+ if (b == null) {
+ b = CarrierConfigManager.getDefaultConfig();
+ }
+
+ mImsRatsConfig =
+ b.getIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY);
+ mImsRoamRatsConfig = b.getIntArray(
+ KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY);
+ if (!SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ // Default configuration includes only EUTRAN . In case of no SIM, add NGRAN.
+ mImsRatsConfig = new int[] { EUTRAN, NGRAN };
+ mImsRoamRatsConfig = new int[] { EUTRAN, NGRAN };
+ }
+
+ mCsRatsConfig =
+ b.getIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY);
+ mCsRoamRatsConfig = b.getIntArray(
+ KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY);
+ mDomainPreference = b.getIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY);
+ mDomainPreferenceRoam = b.getIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY);
+ mPreferImsWhenCallsOnCs = b.getBoolean(
+ KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL);
+ mVoWifiRequiresCondition = b.getInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT);
+ mScanTimeout = b.getInt(KEY_EMERGENCY_SCAN_TIMER_SEC_INT) * 1000;
+ mMaxNumOfVoWifiTries = b.getInt(KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT);
+ mVoWifiOverEmergencyPdn = b.getBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL);
+ mPreferredNetworkScanType = b.getInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT);
+ mCallSetupTimerOnCurrentRat = b.getInt(
+ KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT) * 1000;
+ mRequiresImsRegistration = b.getBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL);
+ mRequiresVoLteEnabled = b.getBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL);
+ mLtePreferredAfterNrFailure = b.getBoolean(
+ KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL);
+ String[] numbers = b.getStringArray(KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY);
+
+ if (mImsRatsConfig == null) mImsRatsConfig = new int[0];
+ if (mCsRatsConfig == null) mCsRatsConfig = new int[0];
+ if (mImsRoamRatsConfig == null) mImsRoamRatsConfig = new int[0];
+ if (mCsRoamRatsConfig == null) mCsRoamRatsConfig = new int[0];
+ if (mDomainPreference == null) mDomainPreference = new int[0];
+ if (mDomainPreferenceRoam == null) mDomainPreferenceRoam = new int[0];
+ if (numbers == null) numbers = new String[0];
+
+ logi("updateCarrierConfiguration "
+ + "imsRats=" + arrayToString(mImsRatsConfig,
+ EmergencyCallDomainSelector::accessNetworkTypeToString)
+ + ", csRats=" + arrayToString(mCsRatsConfig,
+ EmergencyCallDomainSelector::accessNetworkTypeToString)
+ + ", imsRoamRats=" + arrayToString(mImsRoamRatsConfig,
+ EmergencyCallDomainSelector::accessNetworkTypeToString)
+ + ", csRoamRats=" + arrayToString(mCsRoamRatsConfig,
+ EmergencyCallDomainSelector::accessNetworkTypeToString)
+ + ", domainPref=" + arrayToString(mDomainPreference,
+ EmergencyCallDomainSelector::domainPreferenceToString)
+ + ", domainPrefRoam=" + arrayToString(mDomainPreferenceRoam,
+ EmergencyCallDomainSelector::domainPreferenceToString)
+ + ", preferImsOnCs=" + mPreferImsWhenCallsOnCs
+ + ", voWifiRequiresCondition=" + mVoWifiRequiresCondition
+ + ", scanTimeout=" + mScanTimeout
+ + ", maxNumOfVoWifiTries=" + mMaxNumOfVoWifiTries
+ + ", voWifiOverEmergencyPdn=" + mVoWifiOverEmergencyPdn
+ + ", preferredScanType=" + carrierConfigNetworkScanTypeToString(
+ mPreferredNetworkScanType)
+ + ", callSetupTimer=" + mCallSetupTimerOnCurrentRat
+ + ", requiresImsReg=" + mRequiresImsRegistration
+ + ", requiresVoLteEnabled=" + mRequiresVoLteEnabled
+ + ", ltePreferredAfterNr=" + mLtePreferredAfterNrFailure
+ + ", cdmaPreferredNumbers=" + arrayToString(numbers));
+
+ mCdmaPreferredNumbers = Arrays.asList(numbers);
+
+ if ((mPreferredNetworkScanType == CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE)
+ || (mPreferredNetworkScanType
+ == SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE)) {
+ mScanType = DomainSelectionService.SCAN_TYPE_FULL_SERVICE;
+ } else {
+ mScanType = DomainSelectionService.SCAN_TYPE_NO_PREFERENCE;
+ }
+ }
+
+ private void selectDomain() {
+ // State updated right after creation.
+ if (!mDomainSelectionRequested) return;
+
+ // Emergency network scan requested has not been completed.
+ if (mIsScanRequested) return;
+
+ // Domain selection completed, {@link #reselectDomain()} will restart domain selection.
+ if (mDomainSelected) return;
+
+ if (!mBarringInfoReceived || !mImsRegStateReceived || !mMmTelCapabilitiesReceived) {
+ logi("selectDomain not received"
+ + " BarringInfo, IMS registration state, or MMTEL capabilities");
+ return;
+ }
+
+ if (!allowEmergencyCalls(mSelectionAttributes.getEmergencyRegResult())) {
+ // Detected the country and found that emergency calls are not allowed with this slot.
+ terminateSelectionPermanentlyForSlot();
+ return;
+ }
+
+ if (isWifiPreferred()) {
+ onWlanSelected();
+ return;
+ }
+
+ onWwanSelected(this::selectDomainInternal);
+ }
+
+ private void selectDomainInternal() {
+ post(this::selectDomainFromInitialState);
+ }
+
+ private void selectDomainFromInitialState() {
+ if (mIsTestEmergencyNumber) {
+ selectDomainForTestEmergencyNumber();
+ return;
+ }
+
+ boolean csInService = isCsInService();
+ boolean psInService = isPsInService();
+
+ if (!csInService && !psInService) {
+ mPsNetworkType = getSelectablePsNetworkType(false);
+ logi("selectDomain limited service ps=" + accessNetworkTypeToString(mPsNetworkType));
+ if (mPsNetworkType == UNKNOWN) {
+ requestScan(true);
+ } else {
+ onWwanNetworkTypeSelected(mPsNetworkType);
+ }
+ return;
+ }
+
+ // Domain selection per 3GPP TS 23.167 Table H.1.
+ // PS is preferred in case selection between CS and PS is implementation option.
+ mCsNetworkType = UNKNOWN;
+ mPsNetworkType = UNKNOWN;
+ if (csInService) mCsNetworkType = getSelectableCsNetworkType();
+ if (psInService) mPsNetworkType = getSelectablePsNetworkType(true);
+
+ boolean csAvailable = mCsNetworkType != UNKNOWN;
+ boolean psAvailable = mPsNetworkType != UNKNOWN;
+
+ logi("selectDomain CS={" + csInService + ", " + accessNetworkTypeToString(mCsNetworkType)
+ + "}, PS={" + psInService + ", " + accessNetworkTypeToString(mPsNetworkType) + "}");
+ if (csAvailable && psAvailable) {
+ if (mPreferImsWhenCallsOnCs || isImsRegisteredWithVoiceCapability()) {
+ mTryCsWhenPsFails = true;
+ onWwanNetworkTypeSelected(mPsNetworkType);
+ } else if (isDeactivatedSim()) {
+ // Deactivated SIM but PS is in service and supports emergency calls.
+ onWwanNetworkTypeSelected(mPsNetworkType);
+ } else {
+ onWwanNetworkTypeSelected(mCsNetworkType);
+ }
+ } else if (psAvailable) {
+ mTryEpsFallback = (mPsNetworkType == NGRAN) && isEpsFallbackAvailable();
+ if (!mRequiresImsRegistration || isImsRegisteredWithVoiceCapability()) {
+ onWwanNetworkTypeSelected(mPsNetworkType);
+ } else if (isDeactivatedSim()) {
+ // Deactivated SIM but PS is in service and supports emergency calls.
+ onWwanNetworkTypeSelected(mPsNetworkType);
+ } else {
+ // Carrier configuration requires IMS registration for emergency services over PS,
+ // but not registered. Try CS emergency call.
+ mTryEpsFallback = false;
+ requestScan(true, true);
+ }
+ } else if (csAvailable) {
+ onWwanNetworkTypeSelected(mCsNetworkType);
+ } else {
+ // PS is in service but not supports emergency calls.
+ if (mRequiresImsRegistration && !isImsRegisteredWithVoiceCapability()) {
+ // Carrier configuration requires IMS registration for emergency services over PS,
+ // but not registered. Try CS emergency call.
+ requestScan(true, true);
+ } else {
+ mTryEpsFallback = isEpsFallbackAvailable();
+ requestScan(true);
+ }
+ }
+ }
+
+ /**
+ * Requests network scan.
+ *
+ * @param startVoWifiTimer Indicates whether a VoWifi timer will be started.
+ */
+ private void requestScan(boolean startVoWifiTimer) {
+ requestScan(startVoWifiTimer, false);
+ }
+
+ /**
+ * Requests network scan.
+ *
+ * @param startVoWifiTimer Indicates whether a VoWifi timer will be started.
+ * @param csPreferred Indicates whether CS preferred scan is requested.
+ */
+ private void requestScan(boolean startVoWifiTimer, boolean csPreferred) {
+ requestScan(startVoWifiTimer, csPreferred, false);
+ }
+
+ /**
+ * Requests network scan.
+ *
+ * @param startVoWifiTimer Indicates whether a VoWifi timer will be started.
+ * @param csPreferred Indicates whether CS preferred scan is requested.
+ * @param wifiFailed Indicates dialing over Wi-Fi has failed.
+ */
+ private void requestScan(boolean startVoWifiTimer, boolean csPreferred, boolean wifiFailed) {
+ logi("requestScan timer=" + startVoWifiTimer + ", csPreferred=" + csPreferred
+ + ", wifiFailed=" + wifiFailed);
+
+ mCancelSignal = new CancellationSignal();
+ // In case dialing over Wi-Fi has failed, do not the change the domain preference.
+ if (!wifiFailed) {
+ mLastPreferredNetworks = getNextPreferredNetworks(csPreferred, mTryEpsFallback);
+ }
+ mTryEpsFallback = false;
+
+ if (isInRoaming()
+ && (mPreferredNetworkScanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE)) {
+ // FULL_SERVICE only preference is available only when not in roaming.
+ mScanType = DomainSelectionService.SCAN_TYPE_NO_PREFERENCE;
+ }
+
+ mIsScanRequested = true;
+ mWwanSelectorCallback.onRequestEmergencyNetworkScan(
+ mLastPreferredNetworks, mScanType, mCancelSignal,
+ (result) -> {
+ logi("requestScan-onComplete");
+ sendMessage(obtainMessage(MSG_NETWORK_SCAN_RESULT, result));
+ });
+
+ if (startVoWifiTimer && SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ if (isEmcOverWifiSupported()
+ && mScanTimeout > 0 && mVoWifiTrialCount < mMaxNumOfVoWifiTries) {
+ logi("requestScan start scan timer");
+ // remove any pending timers.
+ removeMessages(MSG_NETWORK_SCAN_TIMEOUT);
+ sendEmptyMessageDelayed(MSG_NETWORK_SCAN_TIMEOUT, mScanTimeout);
+ registerForConnectivityChanges();
+ }
+ }
+ }
+
+ /**
+ * Gets the list of preferred network type for the new scan request.
+ *
+ * @param csPreferred Indicates whether CS preferred scan is requested.
+ * @param tryEpsFallback Indicates whether scan requested for EPS fallback.
+ * @return The list of preferred network types.
+ */
+ @VisibleForTesting
+ public @RadioAccessNetworkType List<Integer> getNextPreferredNetworks(boolean csPreferred,
+ boolean tryEpsFallback) {
+ if (mRequiresVoLteEnabled && !isAdvancedCallingSettingEnabled()) {
+ // Emergency call over IMS is not supported.
+ logi("getNextPreferredNetworks VoLte setting is not enabled.");
+ return generatePreferredNetworks(getCsNetworkTypeConfiguration());
+ }
+
+ List<Integer> preferredNetworks = new ArrayList<>();
+
+ List<Integer> domains = getDomainPreference();
+ int psPriority = domains.indexOf(DOMAIN_PS_3GPP);
+ int csPriority = domains.indexOf(DOMAIN_CS);
+ logi("getNextPreferredNetworks psPriority=" + psPriority + ", csPriority=" + csPriority
+ + ", csPreferred=" + csPreferred + ", epsFallback=" + tryEpsFallback
+ + ", lastNetworkType=" + accessNetworkTypeToString(mLastNetworkType));
+
+ if (!csPreferred && (mLastNetworkType == UNKNOWN || tryEpsFallback)) {
+ // Generate the list per the domain preference.
+
+ if (psPriority == NOT_SUPPORTED && csPriority == NOT_SUPPORTED) {
+ // should not reach here. However, to avoid unexpected problems.
+ preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration(),
+ getImsNetworkTypeConfiguration());
+ } else if (psPriority == NOT_SUPPORTED && csPriority > NOT_SUPPORTED) {
+ // CS networks only.
+ preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration());
+ } else if (psPriority > NOT_SUPPORTED && csPriority == NOT_SUPPORTED) {
+ // PS networks only.
+ preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration());
+ } else if (psPriority < csPriority) {
+ // PS preferred.
+ preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration(),
+ getCsNetworkTypeConfiguration());
+ } else {
+ // CS preferred.
+ preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration(),
+ getImsNetworkTypeConfiguration());
+ }
+
+ // Make NGRAN have the lowest priority
+ if (tryEpsFallback && preferredNetworks.contains(NGRAN)) {
+ preferredNetworks.remove(Integer.valueOf(NGRAN));
+ preferredNetworks.add(NGRAN);
+ }
+ } else if (csPreferred || mLastNetworkType == EUTRAN || mLastNetworkType == NGRAN) {
+ if (!csPreferred && mLastNetworkType == NGRAN && mLtePreferredAfterNrFailure) {
+ // LTE is preferred after dialing over NR failed.
+ List<Integer> imsRats = getImsNetworkTypeConfiguration();
+ imsRats.remove(Integer.valueOf(NGRAN));
+ preferredNetworks = generatePreferredNetworks(imsRats,
+ getCsNetworkTypeConfiguration());
+ } else if (csPriority > NOT_SUPPORTED) {
+ // PS tried, generate the list with CS preferred.
+ preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration(),
+ getImsNetworkTypeConfiguration());
+ } else {
+ // CS not suppored.
+ preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration());
+ }
+ } else {
+ // CS tried, generate the list with PS preferred.
+ if (psPriority > NOT_SUPPORTED) {
+ preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration(),
+ getCsNetworkTypeConfiguration());
+ } else {
+ // PS not suppored.
+ preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration());
+ }
+ }
+
+ return preferredNetworks;
+ }
+
+ private @RadioAccessNetworkType List<Integer> generatePreferredNetworks(List<Integer>...lists) {
+ List<Integer> preferredNetworks = new ArrayList<>();
+ for (List<Integer> list : lists) {
+ preferredNetworks.addAll(list);
+ }
+
+ return preferredNetworks;
+ }
+
+ private void handleNetworkScanTimeout() {
+ logi("handleNetworkScanTimeout overEmergencyPdn=" + mVoWifiOverEmergencyPdn
+ + ", wifiAvailable=" + mWiFiAvailable);
+ boolean available = mWiFiAvailable;
+ if (mVoWifiOverEmergencyPdn) {
+ // SOS APN
+ if (!available && isImsRegisteredOverCrossSim()) {
+ available = true;
+ }
+ if (available) {
+ switch (mVoWifiRequiresCondition) {
+ case VOWIFI_REQUIRES_SETTING_ENABLED:
+ available = isWifiCallingSettingEnabled();
+ break;
+ case VOWIFI_REQUIRES_VALID_EID:
+ available = isWifiCallingActivated();
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+ // IMS APN. When IMS is already registered over Wi-Fi.
+ available = isImsRegisteredWithVoiceCapability() && isImsRegisteredOverWifi();
+ }
+
+ logi("handleNetworkScanTimeout VoWi-Fi available=" + available);
+ if (available) {
+ if (mCancelSignal != null) {
+ mCancelSignal.cancel();
+ mCancelSignal = null;
+ }
+ onWlanSelected();
+ }
+ }
+
+ /**
+ * Determines whether CS is in service.
+ *
+ * @return {@code true} if CS is in service.
+ */
+ private boolean isCsInService() {
+ EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ if (regResult == null) return false;
+
+ int regState = regResult.getRegState();
+ int domain = regResult.getDomain();
+
+ if ((regState == REGISTRATION_STATE_HOME || regState == REGISTRATION_STATE_ROAMING)
+ && ((domain & NetworkRegistrationInfo.DOMAIN_CS) > 0)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines the network type of the circuit-switched(CS) network.
+ *
+ * @return The network type of the CS network.
+ */
+ private @RadioAccessNetworkType int getSelectableCsNetworkType() {
+ EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ logi("getSelectableCsNetworkType regResult=" + regResult);
+ if (regResult == null) return UNKNOWN;
+
+ int accessNetwork = regResult.getAccessNetwork();
+
+ List<Integer> ratList = getCsNetworkTypeConfiguration();
+ if (ratList.contains(accessNetwork)) {
+ return accessNetwork;
+ }
+
+ if ((regResult.getAccessNetwork() == EUTRAN)
+ && ((regResult.getDomain() & NetworkRegistrationInfo.DOMAIN_CS) > 0)) {
+ if (ratList.contains(UTRAN)) return UTRAN;
+ }
+
+ return UNKNOWN;
+ }
+
+ /**
+ * Determines whether PS is in service.
+ *
+ * @return {@code true} if PS is in service.
+ */
+ private boolean isPsInService() {
+ EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ if (regResult == null) return false;
+
+ int regState = regResult.getRegState();
+ int domain = regResult.getDomain();
+
+ if ((regState == REGISTRATION_STATE_HOME || regState == REGISTRATION_STATE_ROAMING)
+ && ((domain & NetworkRegistrationInfo.DOMAIN_PS) > 0)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Determines the network type supporting emergency services over packet-switched(PS) network.
+ *
+ * @param inService Indicates whether PS is IN_SERVICE state.
+ * @return The network type if the network supports emergency services over PS network.
+ */
+ private @RadioAccessNetworkType int getSelectablePsNetworkType(boolean inService) {
+ EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ logi("getSelectablePsNetworkType regResult=" + regResult);
+ if (regResult == null) return UNKNOWN;
+ if (mRequiresVoLteEnabled && !isAdvancedCallingSettingEnabled()) {
+ // Emergency call over IMS is not supported.
+ logi("getSelectablePsNetworkType VoLte setting is not enabled.");
+ return UNKNOWN;
+ }
+
+ int accessNetwork = regResult.getAccessNetwork();
+ List<Integer> ratList = getImsNetworkTypeConfiguration();
+ if (ratList.contains(accessNetwork)) {
+ if (mIsEmergencyBarred) {
+ logi("getSelectablePsNetworkType barred");
+ return UNKNOWN;
+ }
+ if (accessNetwork == NGRAN) {
+ return (regResult.getNwProvidedEmc() > 0 && regResult.isVopsSupported())
+ ? NGRAN : UNKNOWN;
+ } else if (accessNetwork == EUTRAN) {
+ return (regResult.isEmcBearerSupported()
+ && (regResult.isVopsSupported() || !inService))
+ ? EUTRAN : UNKNOWN;
+ }
+ }
+
+ return UNKNOWN;
+ }
+
+ private boolean isEpsFallbackAvailable() {
+ EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ if (regResult == null) return false;
+
+ List<Integer> ratList = getImsNetworkTypeConfiguration();
+ if (ratList.contains(EUTRAN)) {
+ return (regResult.getNwProvidedEmf() > 0);
+ }
+ return false;
+ }
+
+ /**
+ * Determines whether the SIM is a deactivated one.
+ *
+ * @return {@code true} if the SIM is a deactivated one.
+ */
+ private boolean isDeactivatedSim() {
+ if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ tm = tm.createForSubscriptionId(getSubId());
+ int state = tm.getDataActivationState();
+ logi("isDeactivatedSim state=" + state);
+ return (state == TelephonyManager.SIM_ACTIVATION_STATE_DEACTIVATED);
+ }
+ return false;
+ }
+
+ /**
+ * Determines whether emergency call over Wi-Fi is allowed.
+ *
+ * @return {@code true} if emergency call over Wi-Fi allowed.
+ */
+ private boolean isEmcOverWifiSupported() {
+ if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ List<Integer> domains = getDomainPreference();
+ return domains.contains(DOMAIN_PS_NON_3GPP);
+ }
+ return false;
+ }
+
+ /**
+ * Determines whether Wi-Fi is preferred when IMS registered over Wi-Fi.
+ *
+ * @return {@code true} if Wi-Fi is preferred when IMS registered over Wi-Fi.
+ */
+ private boolean isWifiPreferred() {
+ if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ List<Integer> domains = getDomainPreference();
+ int priority = domains.indexOf(DOMAIN_PS_NON_3GPP);
+ logi("isWifiPreferred priority=" + priority);
+
+ if ((priority == 0)
+ && isImsRegisteredWithVoiceCapability()
+ && isImsRegisteredOverWifi()) {
+ logi("isWifiPreferred try emergency call over Wi-Fi");
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean isAdvancedCallingSettingEnabled() {
+ try {
+ if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ ImsManager imsMngr = mContext.getSystemService(ImsManager.class);
+ ImsMmTelManager mmTelManager = imsMngr.getImsMmTelManager(getSubId());
+ boolean result = mmTelManager.isAdvancedCallingSettingEnabled();
+ logi("isAdvancedCallingSettingEnabled " + result);
+ return result;
+ }
+ } catch (Exception e) {
+ logi("isAdvancedCallingSettingEnabled e=" + e);
+ }
+ return true;
+ }
+
+ private boolean isWifiCallingActivated() {
+ try {
+ ImsManager imsMngr = mContext.getSystemService(ImsManager.class);
+ ProvisioningManager pm = imsMngr.getProvisioningManager(getSubId());
+ String eid = pm.getProvisioningStringValue(
+ ProvisioningManager.KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID);
+ boolean activated = (!TextUtils.isEmpty(eid)) && (!TextUtils.equals("0", eid));
+ logi("isWifiCallingActivated " + activated);
+ return activated;
+ } catch (Exception e) {
+ logi("isWifiCallingActivated e=" + e);
+ }
+ return false;
+ }
+
+ private boolean isWifiCallingSettingEnabled() {
+ boolean result = false;
+ try {
+ if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ ImsManager imsMngr = mContext.getSystemService(ImsManager.class);
+ ImsMmTelManager mmTelManager = imsMngr.getImsMmTelManager(getSubId());
+ if (isInRoaming()) {
+ result = mmTelManager.isVoWiFiRoamingSettingEnabled();
+ } else {
+ result = mmTelManager.isVoWiFiSettingEnabled();
+ }
+ logi("isWifiCallingSettingEnabled " + result);
+ return result;
+ }
+ } catch (Exception e) {
+ logi("isWifiCallingSettingEnabled e=" + e);
+ }
+ return result;
+ }
+
+ private @NonNull List<Integer> getImsNetworkTypeConfiguration() {
+ int[] rats = mImsRatsConfig;
+ if (isInRoaming()) rats = mImsRoamRatsConfig;
+
+ List<Integer> ratList = new ArrayList<Integer>();
+ for (int i = 0; i < rats.length; i++) {
+ ratList.add(rats[i]);
+ }
+ return ratList;
+ }
+
+ private @NonNull List<Integer> getCsNetworkTypeConfiguration() {
+ int[] rats = mCsRatsConfig;
+ if (isInRoaming()) rats = mCsRoamRatsConfig;
+
+ List<Integer> ratList = new ArrayList<Integer>();
+ for (int i = 0; i < rats.length; i++) {
+ ratList.add(rats[i]);
+ }
+
+ if (!mCdmaPreferredNumbers.isEmpty()) {
+ if (mCdmaPreferredNumbers.contains(mSelectionAttributes.getNumber())) {
+ // The number will be dialed over CDMA.
+ ratList.clear();
+ ratList.add(new Integer(CDMA2000));
+ } else {
+ // The number will be dialed over UTRAN or GERAN.
+ ratList.remove(new Integer(CDMA2000));
+ }
+ }
+
+ return ratList;
+ }
+
+ private @NonNull List<Integer> getDomainPreference() {
+ int[] domains = mDomainPreference;
+ if (isInRoaming()) domains = mDomainPreferenceRoam;
+
+ List<Integer> domainList = new ArrayList<Integer>();
+ for (int i = 0; i < domains.length; i++) {
+ domainList.add(domains[i]);
+ }
+ return domainList;
+ }
+
+ private boolean isInRoaming() {
+ if (!SubscriptionManager.isValidSubscriptionId(getSubId())) return false;
+
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ tm = tm.createForSubscriptionId(getSubId());
+ String netIso = tm.getNetworkCountryIso();
+
+ EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ if (regResult != null) {
+ if (regResult.getRegState() == REGISTRATION_STATE_HOME) return false;
+ if (regResult.getRegState() == REGISTRATION_STATE_ROAMING) return true;
+
+ String iso = regResult.getIso();
+ if (!TextUtils.isEmpty(iso)) netIso = iso;
+ }
+
+ String simIso = tm.getSimCountryIso();
+ logi("isInRoaming simIso=" + simIso + ", netIso=" + netIso);
+
+ if (TextUtils.isEmpty(simIso)) return false;
+ if (TextUtils.isEmpty(netIso)) return false;
+
+ return !(TextUtils.equals(simIso, netIso));
+ }
+
+ /**
+ * Determines whether IMS is registered over Wi-Fi.
+ *
+ * @return {@code true} if IMS is registered over Wi-Fi.
+ */
+ private boolean isImsRegisteredOverWifi() {
+ boolean ret = false;
+ if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ ret = mImsStateTracker.isImsRegisteredOverWlan();
+ }
+
+ logi("isImsRegisteredOverWifi " + ret);
+ return ret;
+ }
+
+ /**
+ * Determines whether IMS is registered over the mobile data of another subscription.
+ *
+ * @return {@code true} if IMS is registered over the mobile data of another subscription.
+ */
+ private boolean isImsRegisteredOverCrossSim() {
+ boolean ret = false;
+ if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ ret = mImsStateTracker.isImsRegisteredOverCrossSim();
+ }
+
+ logi("isImsRegisteredOverCrossSim " + ret);
+ return ret;
+ }
+
+ /**
+ * Determines whether IMS is registered with voice capability.
+ *
+ * @return {@code true} if IMS is registered with voice capability.
+ */
+ private boolean isImsRegisteredWithVoiceCapability() {
+ boolean ret = mImsRegistered && mIsVoiceCapable;
+
+ logi("isImsRegisteredWithVoiceCapability " + ret);
+ return ret;
+ }
+
+ private void onWlanSelected() {
+ logi("onWlanSelected");
+ if (mLastTransportType == TRANSPORT_TYPE_WLAN) {
+ logi("onWlanSelected ignore duplicated callback");
+ return;
+ }
+
+ mDomainSelected = true;
+ mLastTransportType = TRANSPORT_TYPE_WLAN;
+ mVoWifiTrialCount++;
+ mTransportSelectorCallback.onWlanSelected(mVoWifiOverEmergencyPdn);
+ mWwanSelectorCallback = null;
+ }
+
+ private void onWwanSelected(Runnable runnable) {
+ logi("onWwanSelected");
+ if (mLastTransportType == TRANSPORT_TYPE_WWAN) {
+ logi("onWwanSelected ignore duplicated callback");
+ return;
+ }
+
+ mLastTransportType = TRANSPORT_TYPE_WWAN;
+ mTransportSelectorCallback.onWwanSelected((callback) -> {
+ mWwanSelectorCallback = callback;
+ runnable.run();
+ });
+ }
+
+ private void onWwanNetworkTypeSelected(@RadioAccessNetworkType int accessNetworkType) {
+ logi("onWwanNetworkTypeSelected " + accessNetworkTypeToString(accessNetworkType));
+ if (mWwanSelectorCallback == null) {
+ logi("onWwanNetworkTypeSelected callback is null");
+ return;
+ }
+
+ mDomainSelected = true;
+ mLastNetworkType = accessNetworkType;
+ int domain = NetworkRegistrationInfo.DOMAIN_CS;
+ if (accessNetworkType == EUTRAN || accessNetworkType == NGRAN) {
+ domain = NetworkRegistrationInfo.DOMAIN_PS;
+ }
+ mWwanSelectorCallback.onDomainSelected(domain,
+ (domain == NetworkRegistrationInfo.DOMAIN_PS));
+ }
+
+ /**
+ * Registers for changes to network connectivity.
+ */
+ private void registerForConnectivityChanges() {
+ if (mIsMonitoringConnectivity) {
+ return;
+ }
+
+ ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ if (cm != null) {
+ logi("registerForConnectivityChanges");
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ cm.registerNetworkCallback(builder.build(), mNetworkCallback);
+ mIsMonitoringConnectivity = true;
+ }
+ }
+
+ /**
+ * Unregisters for connectivity changes.
+ */
+ private void unregisterForConnectivityChanges() {
+ if (!mIsMonitoringConnectivity) {
+ return;
+ }
+
+ ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
+ if (cm != null) {
+ logi("unregisterForConnectivityChanges");
+ cm.unregisterNetworkCallback(mNetworkCallback);
+ mIsMonitoringConnectivity = false;
+ }
+ }
+
+ private boolean allowEmergencyCalls(EmergencyRegResult regResult) {
+ if (mModemCount < 2) return true;
+ if (regResult == null) {
+ loge("allowEmergencyCalls null regResult");
+ return true;
+ }
+
+ String iso = regResult.getIso();
+ if (sAllowOnlyWithSimReady.contains(iso)) {
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ int simState = tm.getSimState(getSlotId());
+ if (simState != TelephonyManager.SIM_STATE_READY) {
+ logi("allowEmergencyCalls not ready, simState=" + simState + ", iso=" + iso);
+ if (mCrossSimRedialingController.isThereOtherSlot()) {
+ return false;
+ }
+ logi("allowEmergencyCalls there is no other slot available");
+ }
+ }
+
+ return true;
+ }
+
+ private void terminateSelectionPermanentlyForSlot() {
+ logi("terminateSelectionPermanentlyForSlot");
+ terminateSelection(true);
+ }
+
+ private void terminateSelectionForCrossSimRedialing(boolean permanent) {
+ logi("terminateSelectionForCrossSimRedialing perm=" + permanent);
+ terminateSelection(permanent);
+ }
+
+ private void terminateSelection(boolean permanent) {
+ mTransportSelectorCallback.onSelectionTerminated(permanent
+ ? DisconnectCause.EMERGENCY_PERM_FAILURE
+ : DisconnectCause.EMERGENCY_TEMP_FAILURE);
+
+ if (mIsScanRequested && mCancelSignal != null) {
+ mCancelSignal.cancel();
+ mCancelSignal = null;
+ }
+ }
+
+ /** Starts the cross stack timer. */
+ public void startCrossStackTimer() {
+ boolean inService = false;
+ boolean inRoaming = false;
+
+ if (mModemCount == 1) return;
+
+ EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ if (regResult != null) {
+ int regState = regResult.getRegState();
+
+ if ((regResult.getDomain() > 0)
+ && (regState == REGISTRATION_STATE_HOME
+ || regState == REGISTRATION_STATE_ROAMING)) {
+ inService = true;
+ }
+ inRoaming = (regState == REGISTRATION_STATE_ROAMING) || isInRoaming();
+ }
+
+ mCrossSimRedialingController.startTimer(mContext, this, mSelectionAttributes.getCallId(),
+ mSelectionAttributes.getNumber(), inService, inRoaming, mModemCount);
+ }
+
+ /** Notifies that the cross stack redilaing timer has been expired. */
+ public void notifyCrossStackTimerExpired() {
+ logi("notifyCrossStackTimerExpired");
+
+ mCrossStackTimerExpired = true;
+ if (mDomainSelected) {
+ // When reselecting domain, terminateSelection will be called.
+ return;
+ }
+ terminateSelectionForCrossSimRedialing(false);
+ }
+
+ private static String arrayToString(int[] intArray, IntFunction<String> func) {
+ int length = intArray.length;
+ StringBuilder sb = new StringBuilder("{");
+ if (length > 0) {
+ int i = 0;
+ sb.append(func.apply(intArray[i++]));
+ while (i < length) {
+ sb.append(", ").append(func.apply(intArray[i++]));
+ }
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ private static String arrayToString(String[] stringArray) {
+ StringBuilder sb;
+ int length = stringArray.length;
+ sb = new StringBuilder("{");
+ if (length > 0) {
+ int i = 0;
+ sb.append(stringArray[i++]);
+ while (i < length) {
+ sb.append(", ").append(stringArray[i++]);
+ }
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+
+ private static String domainPreferenceToString(
+ @CarrierConfigManager.ImsEmergency.EmergencyDomain int domain) {
+ switch (domain) {
+ case DOMAIN_CS: return "CS";
+ case DOMAIN_PS_3GPP: return "PS_3GPP";
+ case DOMAIN_PS_NON_3GPP: return "PS_NON_3GPP";
+ default: return "UNKNOWN";
+ }
+ }
+
+ private static String carrierConfigNetworkScanTypeToString(
+ @CarrierConfigManager.ImsEmergency.EmergencyScanType int scanType) {
+ switch (scanType) {
+ case CarrierConfigManager.ImsEmergency.SCAN_TYPE_NO_PREFERENCE: return "NO_PREF";
+ case CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE: return "FULL";
+ case SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE: return "FULL_N_LIMITED";
+ default: return "UNKNOWN";
+ }
+ }
+
+ private static String accessNetworkTypeToString(
+ @RadioAccessNetworkType int accessNetworkType) {
+ switch (accessNetworkType) {
+ case AccessNetworkType.UNKNOWN: return "UNKNOWN";
+ case AccessNetworkType.GERAN: return "GERAN";
+ case AccessNetworkType.UTRAN: return "UTRAN";
+ case AccessNetworkType.EUTRAN: return "EUTRAN";
+ case AccessNetworkType.CDMA2000: return "CDMA2000";
+ case AccessNetworkType.IWLAN: return "IWLAN";
+ case AccessNetworkType.NGRAN: return "NGRAN";
+ default: return Integer.toString(accessNetworkType);
+ }
+ }
+
+ /**
+ * Destroys the instance.
+ */
+ @VisibleForTesting
+ public void destroy() {
+ if (DBG) logd("destroy");
+
+ mCrossSimRedialingController.stopTimer();
+ releaseWakeLock();
+
+ mDestroyed = true;
+ mImsStateTracker.removeBarringInfoListener(this);
+ mImsStateTracker.removeImsStateListener(this);
+ unregisterForConnectivityChanges();
+
+ super.destroy();
+ }
+
+ private void acquireWakeLock() {
+ if (mPartialWakeLock != null) {
+ synchronized (mPartialWakeLock) {
+ logi("acquireWakeLock");
+ mPartialWakeLock.acquire();
+ }
+ }
+ }
+
+ private void releaseWakeLock() {
+ if (mPartialWakeLock != null) {
+ synchronized (mPartialWakeLock) {
+ if (mPartialWakeLock.isHeld()) {
+ logi("releaseWakeLock");
+ mPartialWakeLock.release();
+ }
+ }
+ }
+ }
+
+ private void selectDomainForTestEmergencyNumber() {
+ logi("selectDomainForTestEmergencyNumber");
+ if (isImsRegisteredWithVoiceCapability()) {
+ onWwanNetworkTypeSelected(EUTRAN);
+ } else {
+ onWwanNetworkTypeSelected(UTRAN);
+ }
+ }
+
+ private boolean isTestEmergencyNumber(String number) {
+ number = PhoneNumberUtils.stripSeparators(number);
+ Map<Integer, List<EmergencyNumber>> list = new HashMap<>();
+ try {
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ list = tm.getEmergencyNumberList();
+ } catch (IllegalStateException ise) {
+ loge("isTestEmergencyNumber ise=" + ise);
+ }
+
+ for (Integer sub : list.keySet()) {
+ for (EmergencyNumber eNumber : list.get(sub)) {
+ if (number.equals(eNumber.getNumber())
+ && eNumber.isFromSources(EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST)) {
+ logd("isTestEmergencyNumber: " + number + " is a test emergency number.");
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ protected void logi(String msg) {
+ super.logi(msg);
+ sLocalLog.log(msg);
+ }
+
+ @Override
+ protected void loge(String msg) {
+ super.loge(msg);
+ sLocalLog.log(msg);
+ }
+}
diff --git a/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelector.java
new file mode 100644
index 0000000..cd588e1
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelector.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.BarringInfo;
+import android.telephony.CarrierConfigManager;
+import android.telephony.DataSpecificRegistrationInfo;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.telephony.VopsSupportInfo;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Implements an emergency SMS domain selector for sending an emergency SMS.
+ */
+public class EmergencySmsDomainSelector extends SmsDomainSelector implements
+ ImsStateTracker.BarringInfoListener, ImsStateTracker.ServiceStateListener {
+ /**
+ * Stores the configuration value of
+ * {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL}.
+ * This value is always updated whenever the domain selection is requested.
+ */
+ private Boolean mEmergencySmsOverImsSupportedByConfig;
+ private ServiceState mServiceState;
+ private boolean mServiceStateReceived;
+ private BarringInfo mBarringInfo;
+ private boolean mBarringInfoReceived;
+
+ public EmergencySmsDomainSelector(Context context, int slotId, int subId,
+ @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
+ @NonNull DestroyListener listener) {
+ super(context, slotId, subId, looper, imsStateTracker, listener,
+ "DomainSelector-EmergencySMS");
+
+ mImsStateTracker.addServiceStateListener(this);
+ mImsStateTracker.addBarringInfoListener(this);
+ }
+
+ @Override
+ public void destroy() {
+ if (mDestroyed) {
+ return;
+ }
+ mImsStateTracker.removeServiceStateListener(this);
+ mImsStateTracker.removeBarringInfoListener(this);
+ super.destroy();
+ }
+
+ @Override
+ public void finishSelection() {
+ super.finishSelection();
+ mServiceStateReceived = false;
+ mServiceState = null;
+ mBarringInfoReceived = false;
+ mBarringInfo = null;
+ mEmergencySmsOverImsSupportedByConfig = null;
+ }
+
+ @Override
+ public void onBarringInfoUpdated(BarringInfo barringInfo) {
+ mBarringInfoReceived = true;
+ mBarringInfo = barringInfo;
+ sendMessageForDomainSelection();
+ }
+
+ @Override
+ public void onServiceStateUpdated(ServiceState serviceState) {
+ mServiceStateReceived = true;
+ mServiceState = serviceState;
+ sendMessageForDomainSelection();
+ }
+
+ /**
+ * Checks whether the domain selector is ready to select the domain or not.
+ * The emergency SMS requires to be updated for the {@link ServiceState} and
+ * {@link BarringInfo} to confirm that the cellular network supports to send emergency SMS
+ * messages over IMS.
+ */
+ @VisibleForTesting
+ public boolean isDomainSelectionReady() {
+ return mServiceStateReceived && mBarringInfoReceived;
+ }
+
+ @Override
+ protected boolean isSmsOverImsAvailable() {
+ if (super.isSmsOverImsAvailable()) {
+ /**
+ * Even though IMS is successfully registered, the cellular domain should be
+ * available for the emergency SMS according to the carrier's requirement
+ * when {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL} is set
+ * to true.
+ */
+ if (isEmergencySmsOverImsSupportedByConfig()) {
+ /**
+ * Emergency SMS should be supported via emergency PDN.
+ * If this condition is false, then need to fallback to CS network
+ * because the current PS network does not allow the emergency service.
+ */
+ return isNetworkAvailableForImsEmergencySms();
+ }
+
+ // Emergency SMS is supported via IMS PDN.
+ return true;
+ }
+
+ return isImsEmergencySmsAvailable();
+ }
+
+ @Override
+ protected void selectDomain() {
+ if (!isDomainSelectionRequested()) {
+ logi("Domain selection is not requested!");
+ return;
+ }
+
+ if (!isDomainSelectionReady()) {
+ logd("Wait for the readiness of the domain selection!");
+ return;
+ }
+
+ logi("selectDomain: " + mImsStateTracker.imsStateToString());
+
+ if (isSmsOverImsAvailable()) {
+ if (mImsStateTracker.isImsRegisteredOverWlan()) {
+ if (!isEmergencySmsOverImsSupportedByConfig()) {
+ notifyWlanSelected();
+ return;
+ }
+
+ /**
+ * When {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL}
+ * is set to true, the emergency SMS supports on the LTE network using the
+ * emergency PDN. So, considering EUTRAN only at this point.
+ */
+ logi("DomainSelected: WLAN >> WWAN");
+ }
+ notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_PS);
+ } else {
+ notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_CS);
+ }
+ }
+
+ /**
+ * Checks if the emergency SMS messages over IMS is available according to the carrier
+ * configuration and the current network states.
+ */
+ private boolean isImsEmergencySmsAvailable() {
+ boolean emergencySmsOverImsSupportedByConfig = isEmergencySmsOverImsSupportedByConfig();
+ boolean networkAvailable = isNetworkAvailableForImsEmergencySms();
+
+ logi("isImsEmergencySmsAvailable: "
+ + "emergencySmsOverIms=" + emergencySmsOverImsSupportedByConfig
+ + ", mmTelFeatureAvailable=" + mImsStateTracker.isMmTelFeatureAvailable()
+ + ", networkAvailable=" + networkAvailable);
+
+ return emergencySmsOverImsSupportedByConfig
+ && mImsStateTracker.isMmTelFeatureAvailable()
+ && networkAvailable;
+ }
+
+ /**
+ * Checks if sending emergency SMS messages over IMS is supported when in LTE/limited LTE
+ * (Emergency only) service mode from the carrier configuration.
+ */
+ private boolean isEmergencySmsOverImsSupportedByConfig() {
+ if (mEmergencySmsOverImsSupportedByConfig == null) {
+ CarrierConfigManager ccm = mContext.getSystemService(CarrierConfigManager.class);
+
+ if (ccm == null) {
+ loge("CarrierConfigManager is null");
+ return false;
+ }
+
+ PersistableBundle b = ccm.getConfigForSubId(getSubId());
+
+ if (b == null) {
+ loge("PersistableBundle is null");
+ return false;
+ }
+
+ mEmergencySmsOverImsSupportedByConfig = b.getBoolean(
+ CarrierConfigManager.KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL);
+ }
+
+ return mEmergencySmsOverImsSupportedByConfig;
+ }
+
+ /**
+ * Checks if the emergency service is available in the LTE service mode.
+ */
+ private boolean isLteEmergencyAvailableInService() {
+ if (mServiceState == null) {
+ return false;
+ }
+
+ final NetworkRegistrationInfo regInfo = mServiceState.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ if (regInfo != null
+ && regInfo.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_LTE
+ && regInfo.isRegistered()) {
+ return isEmergencyServiceSupported(regInfo) && isEmergencyServiceAllowed();
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the emergency service is available in the limited LTE service(Emergency only) mode.
+ */
+ private boolean isLteEmergencyAvailableInLimitedService() {
+ if (mServiceState == null) {
+ return false;
+ }
+
+ final NetworkRegistrationInfo regInfo = mServiceState.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (regInfo != null
+ && regInfo.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_LTE
+ && regInfo.isEmergencyEnabled()) {
+ return isEmergencyServiceSupported(regInfo) && isEmergencyServiceAllowed();
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the network is available for the IMS emergency SMS.
+ */
+ private boolean isNetworkAvailableForImsEmergencySms() {
+ return isLteEmergencyAvailableInService()
+ || isLteEmergencyAvailableInLimitedService();
+ }
+
+ /**
+ * Checks if the emergency service is supported by the network.
+ *
+ * This checks if "Emergency bearer services indicator (EMC-BS)" field (bits) set to
+ * the "Emergency bearer services in S1 mode supported".
+ *
+ * @return {@code true} if the emergency service is supported by the network,
+ * {@code false} otherwise.
+ */
+ private boolean isEmergencyServiceSupported(@NonNull NetworkRegistrationInfo regInfo) {
+ final DataSpecificRegistrationInfo dsRegInfo = regInfo.getDataSpecificInfo();
+ if (dsRegInfo != null) {
+ final VopsSupportInfo vopsSupportInfo = dsRegInfo.getVopsSupportInfo();
+ return vopsSupportInfo != null
+ && vopsSupportInfo.isEmergencyServiceSupported();
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the emergency service is allowed (not barred) by the network.
+ *
+ * This checks if SystemInformationBlockType2 includes the ac-BarringInfo and
+ * with the ac-BarringForEmergency set to FALSE or
+ * if the SystemInformationBlockType2 does not include the ac-BarringInfo.
+ *
+ * @return {@code true} if the emergency service is allowed by the network,
+ * {@code false} otherwise.
+ */
+ private boolean isEmergencyServiceAllowed() {
+ if (mBarringInfo == null) {
+ return true;
+ }
+ final BarringInfo.BarringServiceInfo bsi =
+ mBarringInfo.getBarringServiceInfo(BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY);
+ return !bsi.isBarred();
+ }
+}
diff --git a/src/com/android/services/telephony/domainselection/ImsStateTracker.java b/src/com/android/services/telephony/domainselection/ImsStateTracker.java
new file mode 100644
index 0000000..fc3f811
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/ImsStateTracker.java
@@ -0,0 +1,878 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
+import android.telephony.BarringInfo;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsRegistrationAttributes;
+import android.telephony.ims.ImsStateCallback;
+import android.telephony.ims.ImsStateCallback.DisconnectedReason;
+import android.telephony.ims.RegistrationManager;
+import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
+import android.util.LocalLog;
+import android.util.Log;
+
+import com.android.internal.annotations.Keep;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.PrintWriter;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * A class for tracking the IMS related information like IMS registration state, MMTEL capabilities.
+ * And, it also tracks the {@link ServiceState} and {@link BarringInfo} to identify the current
+ * network state to which the device is attached.
+ */
+@Keep
+public class ImsStateTracker {
+ /**
+ * A listener used to be notified of the {@link ServiceState} change.
+ */
+ public interface ServiceStateListener {
+ /**
+ * Called when the {@link ServiceState} is updated.
+ */
+ void onServiceStateUpdated(ServiceState serviceState);
+ }
+
+ /**
+ * A listener used to be notified of the {@link BarringInfo} change.
+ */
+ public interface BarringInfoListener {
+ /**
+ * Called when the {@link BarringInfo} is updated.
+ */
+ void onBarringInfoUpdated(BarringInfo barringInfo);
+ }
+
+ /**
+ * A listener used to be notified of the change for MMTEL connection state, IMS registration
+ * state, and MMTEL capabilities.
+ */
+ public interface ImsStateListener {
+ /**
+ * Called when MMTEL feature connection state is changed.
+ */
+ void onImsMmTelFeatureAvailableChanged();
+
+ /**
+ * Called when IMS registration state is changed.
+ */
+ void onImsRegistrationStateChanged();
+
+ /**
+ * Called when MMTEL capability is changed - IMS is registered
+ * and the service is currently available over IMS.
+ */
+ void onImsMmTelCapabilitiesChanged();
+ }
+
+ private static final String TAG = ImsStateTracker.class.getSimpleName();
+ /**
+ * When MMTEL feature connection is unavailable temporarily,
+ * the IMS state will be set to unavailable after waiting for this time.
+ */
+ @VisibleForTesting
+ protected static final long MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS = 1000; // 1 seconds
+
+ // Persistent Logging
+ private final LocalLog mEventLog = new LocalLog(30);
+ private final Context mContext;
+ private final int mSlotId;
+ private final Handler mHandler;
+ private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+ /** For tracking the ServiceState and its related listeners. */
+ private ServiceState mServiceState;
+ private final Set<ServiceStateListener> mServiceStateListeners = new ArraySet<>(2);
+
+ /** For tracking the BarringInfo and its related listeners. */
+ private BarringInfo mBarringInfo;
+ private final Set<BarringInfoListener> mBarringInfoListeners = new ArraySet<>(2);
+
+ /** For tracking IMS states and callbacks. */
+ private final Set<ImsStateListener> mImsStateListeners = new ArraySet<>(5);
+ private ImsMmTelManager mMmTelManager;
+ private ImsStateCallback mImsStateCallback;
+ private RegistrationManager.RegistrationCallback mImsRegistrationCallback;
+ private ImsMmTelManager.CapabilityCallback mMmTelCapabilityCallback;
+ /** The availability of MmTelFeature. */
+ private Boolean mMmTelFeatureAvailable;
+ /** The IMS registration state and the network type that performed IMS registration. */
+ private Boolean mImsRegistered;
+ private @RadioAccessNetworkType int mImsAccessNetworkType = AccessNetworkType.UNKNOWN;
+ private Boolean mImsRegisteredOverCrossSim;
+ /** The MMTEL capabilities - Voice, Video, SMS, and Ut. */
+ private MmTelCapabilities mMmTelCapabilities;
+ private final Runnable mMmTelFeatureUnavailableRunnable = new Runnable() {
+ @Override
+ public void run() {
+ setImsStateAsUnavailable();
+ notifyImsMmTelFeatureAvailableChanged();
+ }
+ };
+
+ public ImsStateTracker(@NonNull Context context, int slotId, @NonNull Looper looper) {
+ mContext = context;
+ mSlotId = slotId;
+ mHandler = new Handler(looper);
+ }
+
+ /**
+ * Destroys this tracker.
+ */
+ public void destroy() {
+ stopListeningForImsState();
+ mHandler.removeCallbacksAndMessages(null);
+ }
+
+ /**
+ * Returns the slot index for this tracker.
+ */
+ public int getSlotId() {
+ return mSlotId;
+ }
+
+ /**
+ * Returns the current subscription index for this tracker.
+ */
+ public int getSubId() {
+ return mSubId;
+ }
+
+ /**
+ * Returns the Handler instance of this tracker.
+ */
+ @VisibleForTesting
+ public @NonNull Handler getHandler() {
+ return mHandler;
+ }
+
+ /**
+ * Starts monitoring the IMS states with the specified subscription.
+ * This method will be called whenever the subscription index for this tracker is changed.
+ * If the subscription index for this tracker is same as previously set, it will be ignored.
+ *
+ * @param subId The subscription index to be started.
+ */
+ public void start(int subId) {
+ if (mSubId == subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
+ setImsStateAsUnavailable();
+ return;
+ } else if (mImsStateCallback != null) {
+ // If start() is called with the same subscription index and the ImsStateCallback
+ // was already registered, we don't need to unregister and register this callback
+ // again. So, this request should be ignored if the subscription index is same.
+ logd("start: ignored for same subscription(" + mSubId + ")");
+ return;
+ }
+ } else {
+ logi("start: subscription changed from " + mSubId + " to " + subId);
+ mSubId = subId;
+ }
+
+ stopListeningForImsState();
+ startListeningForImsState();
+ }
+
+ /**
+ * Updates the service state of the network to which the device is currently attached.
+ * This method should be run on the same thread as the Handler.
+ *
+ * @param serviceState The {@link ServiceState} to be updated.
+ */
+ public void updateServiceState(ServiceState serviceState) {
+ mServiceState = serviceState;
+
+ for (ServiceStateListener listener : mServiceStateListeners) {
+ listener.onServiceStateUpdated(serviceState);
+ }
+ }
+
+ /**
+ * Adds a listener to be notified of the {@link ServiceState} change.
+ * The newly added listener is notified if the current {@link ServiceState} is present.
+ *
+ * @param listener The listener to be added.
+ */
+ public void addServiceStateListener(@NonNull ServiceStateListener listener) {
+ mServiceStateListeners.add(listener);
+
+ final ServiceState serviceState = mServiceState;
+ if (serviceState != null) {
+ mHandler.post(() -> notifyServiceStateUpdated(listener, serviceState));
+ }
+ }
+
+ /**
+ * Removes a listener to be notified of the {@link ServiceState} change.
+ *
+ * @param listener The listener to be removed.
+ */
+ public void removeServiceStateListener(@NonNull ServiceStateListener listener) {
+ mServiceStateListeners.remove(listener);
+ }
+
+ /**
+ * Notifies the specified listener of a change to {@link ServiceState}.
+ *
+ * @param listener The listener to be notified.
+ * @param serviceState The {@link ServiceState} to be reported.
+ */
+ private void notifyServiceStateUpdated(ServiceStateListener listener,
+ ServiceState serviceState) {
+ if (!mServiceStateListeners.contains(listener)) {
+ return;
+ }
+ listener.onServiceStateUpdated(serviceState);
+ }
+
+ /**
+ * Updates the barring information received from the network to which the device is currently
+ * attached.
+ * This method should be run on the same thread as the Handler.
+ *
+ * @param barringInfo The {@link BarringInfo} to be updated.
+ */
+ public void updateBarringInfo(BarringInfo barringInfo) {
+ mBarringInfo = barringInfo;
+
+ for (BarringInfoListener listener : mBarringInfoListeners) {
+ listener.onBarringInfoUpdated(barringInfo);
+ }
+ }
+
+ /**
+ * Adds a listener to be notified of the {@link BarringInfo} change.
+ * The newly added listener is notified if the current {@link BarringInfo} is present.
+ *
+ * @param listener The listener to be added.
+ */
+ public void addBarringInfoListener(@NonNull BarringInfoListener listener) {
+ mBarringInfoListeners.add(listener);
+
+ final BarringInfo barringInfo = mBarringInfo;
+ if (barringInfo != null) {
+ mHandler.post(() -> notifyBarringInfoUpdated(listener, barringInfo));
+ }
+ }
+
+ /**
+ * Removes a listener to be notified of the {@link BarringInfo} change.
+ *
+ * @param listener The listener to be removed.
+ */
+ public void removeBarringInfoListener(@NonNull BarringInfoListener listener) {
+ mBarringInfoListeners.remove(listener);
+ }
+
+ /**
+ * Notifies the specified listener of a change to {@link BarringInfo}.
+ *
+ * @param listener The listener to be notified.
+ * @param barringInfo The {@link BarringInfo} to be reported.
+ */
+ private void notifyBarringInfoUpdated(BarringInfoListener listener, BarringInfo barringInfo) {
+ if (!mBarringInfoListeners.contains(listener)) {
+ return;
+ }
+ listener.onBarringInfoUpdated(barringInfo);
+ }
+
+ /**
+ * Adds a listener to be notified of the IMS state change.
+ * If each state was already received from the IMS service, the newly added listener
+ * is notified once.
+ *
+ * @param listener The listener to be added.
+ */
+ public void addImsStateListener(@NonNull ImsStateListener listener) {
+ mImsStateListeners.add(listener);
+ mHandler.post(() -> notifyImsStateChangeIfValid(listener));
+ }
+
+ /**
+ * Removes a listener to be notified of the IMS state change.
+ *
+ * @param listener The listener to be removed.
+ */
+ public void removeImsStateListener(@NonNull ImsStateListener listener) {
+ mImsStateListeners.remove(listener);
+ }
+
+ /**
+ * Returns {@code true} if all IMS states are ready, {@code false} otherwise.
+ */
+ @VisibleForTesting
+ public boolean isImsStateReady() {
+ return mMmTelFeatureAvailable != null
+ && mImsRegistered != null
+ && mMmTelCapabilities != null;
+ }
+
+ /**
+ * Returns {@code true} if MMTEL feature connection is available, {@code false} otherwise.
+ */
+ public boolean isMmTelFeatureAvailable() {
+ return mMmTelFeatureAvailable != null && mMmTelFeatureAvailable;
+ }
+
+ /**
+ * Returns {@code true} if IMS is registered, {@code false} otherwise.
+ */
+ public boolean isImsRegistered() {
+ return mImsRegistered != null && mImsRegistered;
+ }
+
+ /**
+ * Returns {@code true} if IMS is registered over Wi-Fi (IWLAN), {@code false} otherwise.
+ */
+ public boolean isImsRegisteredOverWlan() {
+ return mImsAccessNetworkType == AccessNetworkType.IWLAN;
+ }
+
+ /**
+ * Returns {@code true} if IMS is registered over the mobile data of another subscription.
+ */
+ public boolean isImsRegisteredOverCrossSim() {
+ return mImsRegisteredOverCrossSim != null && mImsRegisteredOverCrossSim;
+ }
+
+ /**
+ * Returns {@code true} if IMS voice call is capable, {@code false} otherwise.
+ */
+ public boolean isImsVoiceCapable() {
+ return mMmTelCapabilities != null
+ && mMmTelCapabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VOICE);
+ }
+
+ /**
+ * Returns {@code true} if IMS video call is capable, {@code false} otherwise.
+ */
+ public boolean isImsVideoCapable() {
+ return mMmTelCapabilities != null
+ && mMmTelCapabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VIDEO);
+ }
+
+ /**
+ * Returns {@code true} if IMS SMS is capable, {@code false} otherwise.
+ */
+ public boolean isImsSmsCapable() {
+ return mMmTelCapabilities != null
+ && mMmTelCapabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_SMS);
+ }
+
+ /**
+ * Returns {@code true} if IMS UT is capable, {@code false} otherwise.
+ */
+ public boolean isImsUtCapable() {
+ return mMmTelCapabilities != null
+ && mMmTelCapabilities.isCapable(MmTelCapabilities.CAPABILITY_TYPE_UT);
+ }
+
+ /**
+ * Returns the access network type to which IMS is registered.
+ */
+ public @RadioAccessNetworkType int getImsAccessNetworkType() {
+ return mImsAccessNetworkType;
+ }
+
+ /**
+ * Sets the IMS states to the initial values.
+ */
+ private void initImsState() {
+ mMmTelFeatureAvailable = null;
+ mImsRegistered = null;
+ mImsAccessNetworkType = AccessNetworkType.UNKNOWN;
+ mImsRegisteredOverCrossSim = null;
+ mMmTelCapabilities = null;
+ }
+
+ /**
+ * Sets the IMS states to unavailable to notify the readiness of the IMS state
+ * when the subscription is not valid.
+ */
+ private void setImsStateAsUnavailable() {
+ logd("setImsStateAsUnavailable");
+ setMmTelFeatureAvailable(false);
+ setImsRegistered(false);
+ setImsAccessNetworkType(AccessNetworkType.UNKNOWN);
+ setImsRegisteredOverCrossSim(false);
+ setMmTelCapabilities(new MmTelCapabilities());
+ }
+
+ private void setMmTelFeatureAvailable(boolean available) {
+ if (!Objects.equals(mMmTelFeatureAvailable, Boolean.valueOf(available))) {
+ logi("setMmTelFeatureAvailable: " + mMmTelFeatureAvailable + " >> " + available);
+ mMmTelFeatureAvailable = Boolean.valueOf(available);
+ }
+ }
+
+ private void setImsRegistered(boolean registered) {
+ if (!Objects.equals(mImsRegistered, Boolean.valueOf(registered))) {
+ logi("setImsRegistered: " + mImsRegistered + " >> " + registered);
+ mImsRegistered = Boolean.valueOf(registered);
+ }
+ }
+
+ private void setImsAccessNetworkType(int accessNetworkType) {
+ if (mImsAccessNetworkType != accessNetworkType) {
+ logi("setImsAccessNetworkType: " + accessNetworkTypeToString(mImsAccessNetworkType)
+ + " >> " + accessNetworkTypeToString(accessNetworkType));
+ mImsAccessNetworkType = accessNetworkType;
+ }
+ }
+
+ private void setMmTelCapabilities(@NonNull MmTelCapabilities capabilities) {
+ if (!Objects.equals(mMmTelCapabilities, capabilities)) {
+ logi("MMTEL capabilities: " + mMmTelCapabilities + " >> " + capabilities);
+ mMmTelCapabilities = capabilities;
+ }
+ }
+
+ private void setImsRegisteredOverCrossSim(boolean crossSim) {
+ if (!Objects.equals(mImsRegisteredOverCrossSim, Boolean.valueOf(crossSim))) {
+ logi("setImsRegisteredOverCrossSim: " + mImsRegisteredOverCrossSim + " >> " + crossSim);
+ mImsRegisteredOverCrossSim = Boolean.valueOf(crossSim);
+ }
+ }
+
+ /**
+ * Notifies the specified listener of the current IMS state if it's valid.
+ *
+ * @param listener The {@link ImsStateListener} to be notified.
+ */
+ private void notifyImsStateChangeIfValid(@NonNull ImsStateListener listener) {
+ if (!mImsStateListeners.contains(listener)) {
+ return;
+ }
+
+ if (mMmTelFeatureAvailable != null) {
+ listener.onImsMmTelFeatureAvailableChanged();
+ }
+
+ if (mImsRegistered != null) {
+ listener.onImsRegistrationStateChanged();
+ }
+
+ if (mMmTelCapabilities != null) {
+ listener.onImsMmTelCapabilitiesChanged();
+ }
+ }
+
+ /**
+ * Notifies the application that MMTEL feature connection state is changed.
+ */
+ private void notifyImsMmTelFeatureAvailableChanged() {
+ for (ImsStateListener l : mImsStateListeners) {
+ l.onImsMmTelFeatureAvailableChanged();
+ }
+ }
+
+ /**
+ * Notifies the application that IMS registration state is changed.
+ */
+ private void notifyImsRegistrationStateChanged() {
+ logi("ImsState: " + imsStateToString());
+ for (ImsStateListener l : mImsStateListeners) {
+ l.onImsRegistrationStateChanged();
+ }
+ }
+
+ /**
+ * Notifies the application that MMTEL capabilities is changed.
+ */
+ private void notifyImsMmTelCapabilitiesChanged() {
+ logi("ImsState: " + imsStateToString());
+ for (ImsStateListener l : mImsStateListeners) {
+ l.onImsMmTelCapabilitiesChanged();
+ }
+ }
+
+ /**
+ * Called when MMTEL feature connection state is available.
+ */
+ private void onMmTelFeatureAvailable() {
+ logd("onMmTelFeatureAvailable");
+ mHandler.removeCallbacks(mMmTelFeatureUnavailableRunnable);
+ setMmTelFeatureAvailable(true);
+ registerImsRegistrationCallback();
+ registerMmTelCapabilityCallback();
+ notifyImsMmTelFeatureAvailableChanged();
+ }
+
+ /**
+ * Called when MMTEL feature connection state is unavailable.
+ */
+ private void onMmTelFeatureUnavailable(@DisconnectedReason int reason) {
+ logd("onMmTelFeatureUnavailable: reason=" + disconnectedCauseToString(reason));
+
+ if (reason == ImsStateCallback.REASON_UNKNOWN_TEMPORARY_ERROR
+ || reason == ImsStateCallback.REASON_IMS_SERVICE_NOT_READY) {
+ // Wait for onAvailable for some times and
+ // if it's not available, the IMS state will be set to unavailable.
+ initImsState();
+ setMmTelFeatureAvailable(false);
+ mHandler.postDelayed(mMmTelFeatureUnavailableRunnable,
+ MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS);
+ } else if (reason == ImsStateCallback.REASON_UNKNOWN_PERMANENT_ERROR
+ || reason == ImsStateCallback.REASON_NO_IMS_SERVICE_CONFIGURED) {
+ // Permanently blocked for this subscription.
+ setImsStateAsUnavailable();
+ notifyImsMmTelFeatureAvailableChanged();
+ } else if (reason == ImsStateCallback.REASON_IMS_SERVICE_DISCONNECTED) {
+ // Wait for onAvailable for some times and
+ // if it's not available, the IMS state will be set to unavailable.
+ initImsState();
+ setMmTelFeatureAvailable(false);
+ unregisterImsRegistrationCallback();
+ unregisterMmTelCapabilityCallback();
+ mHandler.postDelayed(mMmTelFeatureUnavailableRunnable,
+ MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS);
+ } else if (reason == ImsStateCallback.REASON_SUBSCRIPTION_INACTIVE) {
+ // The {@link TelephonyDomainSelectionService} will call ImsStateTracker#start
+ // when the subscription changes to register new callbacks.
+ setImsStateAsUnavailable();
+ unregisterImsRegistrationCallback();
+ unregisterMmTelCapabilityCallback();
+ // ImsStateCallback has already been removed after calling onUnavailable.
+ mImsStateCallback = null;
+ notifyImsMmTelFeatureAvailableChanged();
+ } else {
+ logw("onMmTelFeatureUnavailable: unexpected reason=" + reason);
+ }
+ }
+
+ /**
+ * Called when IMS is registered to the IMS network.
+ */
+ private void onImsRegistered(@NonNull ImsRegistrationAttributes attributes) {
+ logd("onImsRegistered: " + attributes);
+
+ setImsRegistered(true);
+ setImsAccessNetworkType(
+ imsRegTechToAccessNetworkType(attributes.getRegistrationTechnology()));
+ setImsRegisteredOverCrossSim(attributes.getRegistrationTechnology()
+ == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM);
+ notifyImsRegistrationStateChanged();
+ }
+
+ /**
+ * Called when IMS is unregistered from the IMS network.
+ */
+ private void onImsUnregistered(@NonNull ImsReasonInfo info) {
+ logd("onImsUnregistered: " + info);
+ setImsRegistered(false);
+ setImsAccessNetworkType(AccessNetworkType.UNKNOWN);
+ setImsRegisteredOverCrossSim(false);
+ setMmTelCapabilities(new MmTelCapabilities());
+ notifyImsRegistrationStateChanged();
+ }
+
+ /**
+ * Called when MMTEL capability is changed - IMS is registered
+ * and the service is currently available over IMS.
+ */
+ private void onMmTelCapabilitiesChanged(@NonNull MmTelCapabilities capabilities) {
+ logd("onMmTelCapabilitiesChanged: " + capabilities);
+ setMmTelCapabilities(capabilities);
+ notifyImsMmTelCapabilitiesChanged();
+ }
+
+ /**
+ * Starts listening to monitor the IMS states -
+ * connection state, IMS registration state, and MMTEL capabilities.
+ */
+ private void startListeningForImsState() {
+ if (!SubscriptionManager.isValidSubscriptionId(getSubId())) {
+ setImsStateAsUnavailable();
+ return;
+ }
+
+ ImsManager imsMngr = mContext.getSystemService(ImsManager.class);
+ mMmTelManager = imsMngr.getImsMmTelManager(getSubId());
+ initImsState();
+ registerImsStateCallback();
+ }
+
+ /**
+ * Stops listening to monitor the IMS states -
+ * connection state, IMS registration state, and MMTEL capabilities.
+ */
+ private void stopListeningForImsState() {
+ mHandler.removeCallbacks(mMmTelFeatureUnavailableRunnable);
+
+ if (mMmTelManager != null) {
+ unregisterMmTelCapabilityCallback();
+ unregisterImsRegistrationCallback();
+ unregisterImsStateCallback();
+ mMmTelManager = null;
+ }
+ }
+
+ private void registerImsStateCallback() {
+ if (mImsStateCallback != null) {
+ loge("ImsStateCallback is already registered for sub-" + getSubId());
+ return;
+ }
+ /**
+ * Listens to the IMS connection state change.
+ */
+ mImsStateCallback = new ImsStateCallback() {
+ @Override
+ public void onUnavailable(@DisconnectedReason int reason) {
+ onMmTelFeatureUnavailable(reason);
+ }
+
+ @Override
+ public void onAvailable() {
+ onMmTelFeatureAvailable();
+ }
+
+ @Override
+ public void onError() {
+ // This case will not be happened because this domain selection service
+ // is running on the Telephony service.
+ }
+ };
+
+ try {
+ mMmTelManager.registerImsStateCallback(mHandler::post, mImsStateCallback);
+ } catch (ImsException e) {
+ loge("Exception when registering ImsStateCallback: " + e);
+ mImsStateCallback = null;
+ }
+ }
+
+ private void unregisterImsStateCallback() {
+ if (mImsStateCallback != null) {
+ try {
+ mMmTelManager.unregisterImsStateCallback(mImsStateCallback);
+ } catch (Exception ignored) {
+ // Ignore the runtime exception while unregistering callback.
+ logd("Exception when unregistering ImsStateCallback: " + ignored);
+ }
+ mImsStateCallback = null;
+ }
+ }
+
+ private void registerImsRegistrationCallback() {
+ if (mImsRegistrationCallback != null) {
+ logd("RegistrationCallback is already registered for sub-" + getSubId());
+ return;
+ }
+ /**
+ * Listens to the IMS registration state change.
+ */
+ mImsRegistrationCallback = new RegistrationManager.RegistrationCallback() {
+ @Override
+ public void onRegistered(@NonNull ImsRegistrationAttributes attributes) {
+ onImsRegistered(attributes);
+ }
+
+ @Override
+ public void onUnregistered(@NonNull ImsReasonInfo info) {
+ onImsUnregistered(info);
+ }
+ };
+
+ try {
+ mMmTelManager.registerImsRegistrationCallback(mHandler::post, mImsRegistrationCallback);
+ } catch (ImsException e) {
+ loge("Exception when registering RegistrationCallback: " + e);
+ mImsRegistrationCallback = null;
+ }
+ }
+
+ private void unregisterImsRegistrationCallback() {
+ if (mImsRegistrationCallback != null) {
+ try {
+ mMmTelManager.unregisterImsRegistrationCallback(mImsRegistrationCallback);
+ } catch (Exception ignored) {
+ // Ignore the runtime exception while unregistering callback.
+ logd("Exception when unregistering RegistrationCallback: " + ignored);
+ }
+ mImsRegistrationCallback = null;
+ }
+ }
+
+ private void registerMmTelCapabilityCallback() {
+ if (mMmTelCapabilityCallback != null) {
+ logd("CapabilityCallback is already registered for sub-" + getSubId());
+ return;
+ }
+ /**
+ * Listens to the MmTel feature capabilities change.
+ */
+ mMmTelCapabilityCallback = new ImsMmTelManager.CapabilityCallback() {
+ @Override
+ public void onCapabilitiesStatusChanged(@NonNull MmTelCapabilities capabilities) {
+ onMmTelCapabilitiesChanged(capabilities);
+ }
+ };
+
+ try {
+ mMmTelManager.registerMmTelCapabilityCallback(mHandler::post, mMmTelCapabilityCallback);
+ } catch (ImsException e) {
+ loge("Exception when registering CapabilityCallback: " + e);
+ mMmTelCapabilityCallback = null;
+ }
+ }
+
+ private void unregisterMmTelCapabilityCallback() {
+ if (mMmTelCapabilityCallback != null) {
+ try {
+ mMmTelManager.unregisterMmTelCapabilityCallback(mMmTelCapabilityCallback);
+ } catch (Exception ignored) {
+ // Ignore the runtime exception while unregistering callback.
+ logd("Exception when unregistering CapabilityCallback: " + ignored);
+ }
+ mMmTelCapabilityCallback = null;
+ }
+ }
+
+ /** Returns a string representation of IMS states. */
+ public String imsStateToString() {
+ StringBuilder sb = new StringBuilder("{ ");
+ sb.append("MMTEL: featureAvailable=").append(booleanToString(mMmTelFeatureAvailable));
+ sb.append(", registered=").append(booleanToString(mImsRegistered));
+ sb.append(", accessNetworkType=").append(accessNetworkTypeToString(mImsAccessNetworkType));
+ sb.append(", capabilities=").append(mmTelCapabilitiesToString(mMmTelCapabilities));
+ sb.append(" }");
+ return sb.toString();
+ }
+
+ protected static String accessNetworkTypeToString(
+ @RadioAccessNetworkType int accessNetworkType) {
+ switch (accessNetworkType) {
+ case AccessNetworkType.UNKNOWN: return "UNKNOWN";
+ case AccessNetworkType.GERAN: return "GERAN";
+ case AccessNetworkType.UTRAN: return "UTRAN";
+ case AccessNetworkType.EUTRAN: return "EUTRAN";
+ case AccessNetworkType.CDMA2000: return "CDMA2000";
+ case AccessNetworkType.IWLAN: return "IWLAN";
+ case AccessNetworkType.NGRAN: return "NGRAN";
+ default: return Integer.toString(accessNetworkType);
+ }
+ }
+
+ /** Converts the IMS registration technology to the access network type. */
+ private static @RadioAccessNetworkType int imsRegTechToAccessNetworkType(
+ @ImsRegistrationImplBase.ImsRegistrationTech int imsRegTech) {
+ switch (imsRegTech) {
+ case ImsRegistrationImplBase.REGISTRATION_TECH_LTE:
+ return AccessNetworkType.EUTRAN;
+ case ImsRegistrationImplBase.REGISTRATION_TECH_NR:
+ return AccessNetworkType.NGRAN;
+ case ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN:
+ case ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM:
+ return AccessNetworkType.IWLAN;
+ default:
+ return AccessNetworkType.UNKNOWN;
+ }
+ }
+
+ private static String booleanToString(Boolean b) {
+ return b == null ? "null" : b.toString();
+ }
+
+ private static String mmTelCapabilitiesToString(MmTelCapabilities c) {
+ if (c == null) {
+ return "null";
+ }
+ StringBuilder sb = new StringBuilder("[");
+ sb.append("voice=").append(c.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VOICE));
+ sb.append(", video=").append(c.isCapable(MmTelCapabilities.CAPABILITY_TYPE_VIDEO));
+ sb.append(", ut=").append(c.isCapable(MmTelCapabilities.CAPABILITY_TYPE_UT));
+ sb.append(", sms=").append(c.isCapable(MmTelCapabilities.CAPABILITY_TYPE_SMS));
+ sb.append("]");
+ return sb.toString();
+ }
+
+ private static String disconnectedCauseToString(@DisconnectedReason int reason) {
+ switch (reason) {
+ case ImsStateCallback.REASON_UNKNOWN_TEMPORARY_ERROR:
+ return "UNKNOWN_TEMPORARY_ERROR";
+ case ImsStateCallback.REASON_UNKNOWN_PERMANENT_ERROR:
+ return "UNKNOWN_PERMANENT_ERROR";
+ case ImsStateCallback.REASON_IMS_SERVICE_DISCONNECTED:
+ return "IMS_SERVICE_DISCONNECTED";
+ case ImsStateCallback.REASON_NO_IMS_SERVICE_CONFIGURED:
+ return "NO_IMS_SERVICE_CONFIGURED";
+ case ImsStateCallback.REASON_SUBSCRIPTION_INACTIVE:
+ return "SUBSCRIPTION_INACTIVE";
+ case ImsStateCallback.REASON_IMS_SERVICE_NOT_READY:
+ return "IMS_SERVICE_NOT_READY";
+ default:
+ return Integer.toString(reason);
+ }
+ }
+
+ /**
+ * Dumps this instance into a readable format for dumpsys usage.
+ */
+ public void dump(@NonNull PrintWriter pw) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.println("ImsStateTracker:");
+ ipw.increaseIndent();
+ ipw.println("SlotId: " + getSlotId());
+ ipw.println("SubId: " + getSubId());
+ ipw.println("ServiceState: " + mServiceState);
+ ipw.println("BarringInfo: " + mBarringInfo);
+ ipw.println("ImsState: " + imsStateToString());
+ ipw.println("Event Log:");
+ ipw.increaseIndent();
+ mEventLog.dump(ipw);
+ ipw.decreaseIndent();
+ ipw.decreaseIndent();
+ }
+
+ private void logd(String s) {
+ Log.d(TAG, "[" + getSlotId() + "|" + getSubId() + "] " + s);
+ }
+
+ private void logi(String s) {
+ Log.i(TAG, "[" + getSlotId() + "|" + getSubId() + "] " + s);
+ mEventLog.log("[" + getSlotId() + "|" + getSubId() + "] " + s);
+ }
+
+ private void loge(String s) {
+ Log.e(TAG, "[" + getSlotId() + "|" + getSubId() + "] " + s);
+ mEventLog.log("[" + getSlotId() + "|" + getSubId() + "] " + s);
+ }
+
+ private void logw(String s) {
+ Log.w(TAG, "[" + getSlotId() + "|" + getSubId() + "] " + s);
+ mEventLog.log("[" + getSlotId() + "|" + getSubId() + "] " + s);
+ }
+}
diff --git a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
new file mode 100644
index 0000000..f176d90
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
@@ -0,0 +1,396 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.telecom.TelecomManager;
+import android.telephony.Annotation.DisconnectCauses;
+import android.telephony.CarrierConfigManager;
+import android.telephony.DisconnectCause;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TransportSelectorCallback;
+import android.telephony.ims.ImsReasonInfo;
+
+import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
+
+/**
+ * Implements domain selector for outgoing non-emergency calls.
+ */
+public class NormalCallDomainSelector extends DomainSelectorBase implements
+ ImsStateTracker.ImsStateListener, ImsStateTracker.ServiceStateListener {
+
+ private static final String LOG_TAG = "NCDS";
+
+ private boolean mStopDomainSelection = true;
+ private ServiceState mServiceState;
+ private boolean mImsRegStateReceived;
+ private boolean mMmTelCapabilitiesReceived;
+ private boolean mReselectDomain;
+
+ public NormalCallDomainSelector(Context context, int slotId, int subId, @NonNull Looper looper,
+ @NonNull ImsStateTracker imsStateTracker,
+ @NonNull DestroyListener destroyListener) {
+ super(context, slotId, subId, looper, imsStateTracker, destroyListener, LOG_TAG);
+
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ logd("Subscribing to state callbacks. Subid:" + subId);
+ mImsStateTracker.addServiceStateListener(this);
+ mImsStateTracker.addImsStateListener(this);
+ } else {
+ loge("Invalid Subscription. Subid:" + subId);
+ }
+ }
+
+ @Override
+ public void selectDomain(SelectionAttributes attributes, TransportSelectorCallback callback) {
+ mSelectionAttributes = attributes;
+ mTransportSelectorCallback = callback;
+ mStopDomainSelection = false;
+
+ if (callback == null) {
+ loge("Invalid params: TransportSelectorCallback is null");
+ return;
+ }
+
+ if (attributes == null) {
+ loge("Invalid params: SelectionAttributes are null");
+ notifySelectionTerminated(DisconnectCause.OUTGOING_FAILURE);
+ return;
+ }
+
+ int subId = attributes.getSubId();
+ boolean validSubscriptionId = SubscriptionManager.isValidSubscriptionId(subId);
+ if (attributes.getSelectorType() != SELECTOR_TYPE_CALLING || attributes.isEmergency()
+ || !validSubscriptionId) {
+ loge("Domain Selection stopped. SelectorType:" + attributes.getSelectorType()
+ + ", isEmergency:" + attributes.isEmergency()
+ + ", ValidSubscriptionId:" + validSubscriptionId);
+
+ notifySelectionTerminated(DisconnectCause.OUTGOING_FAILURE);
+ return;
+ }
+
+ if (subId == getSubId()) {
+ logd("NormalCallDomainSelection triggered. Sub-id:" + subId);
+ post(() -> selectDomain());
+ } else {
+ loge("Subscription-ids doesn't match. This instance is associated with sub-id:"
+ + getSubId() + ", requested sub-id:" + subId);
+ // TODO: Throw anamoly here. This condition should never occur.
+ }
+ }
+
+ @Override
+ public void reselectDomain(SelectionAttributes attributes) {
+ logd("reselectDomain called");
+ mReselectDomain = true;
+ selectDomain(attributes, mTransportSelectorCallback);
+ }
+
+ @Override
+ public synchronized void finishSelection() {
+ logd("finishSelection");
+ mStopDomainSelection = true;
+ mImsStateTracker.removeServiceStateListener(this);
+ mImsStateTracker.removeImsStateListener(this);
+ mSelectionAttributes = null;
+ mTransportSelectorCallback = null;
+ }
+
+ /**
+ * Cancel an ongoing selection operation. It is up to the DomainSelectionService
+ * to clean up all ongoing operations with the framework.
+ */
+ @Override
+ public void cancelSelection() {
+ logd("cancelSelection");
+ mStopDomainSelection = true;
+ mReselectDomain = false;
+ if (mTransportSelectorCallback != null) {
+ mTransportSelectorCallback.onSelectionTerminated(DisconnectCause.OUTGOING_CANCELED);
+ }
+ finishSelection();
+ }
+
+ @Override
+ public void onImsRegistrationStateChanged() {
+ logd("onImsRegistrationStateChanged. IsImsRegistered: "
+ + mImsStateTracker.isImsRegistered());
+ mImsRegStateReceived = true;
+ selectDomain();
+ }
+
+ @Override
+ public void onImsMmTelCapabilitiesChanged() {
+ logd("onImsMmTelCapabilitiesChanged. ImsVoiceCap: " + mImsStateTracker.isImsVoiceCapable()
+ + " ImsVideoCap: " + mImsStateTracker.isImsVideoCapable());
+ mMmTelCapabilitiesReceived = true;
+ selectDomain();
+ }
+
+ @Override
+ public void onImsMmTelFeatureAvailableChanged() {
+ logd("onImsMmTelFeatureAvailableChanged");
+ selectDomain();
+ }
+
+ @Override
+ public void onServiceStateUpdated(ServiceState serviceState) {
+ logd("onServiceStateUpdated");
+ mServiceState = serviceState;
+ selectDomain();
+ }
+
+ private void notifyPsSelected() {
+ logd("notifyPsSelected");
+ mStopDomainSelection = true;
+ if (mImsStateTracker.isImsRegisteredOverWlan()) {
+ logd("WLAN selected");
+ mTransportSelectorCallback.onWlanSelected(false);
+ } else {
+ if (mWwanSelectorCallback == null) {
+ mTransportSelectorCallback.onWwanSelected((callback) -> {
+ mWwanSelectorCallback = callback;
+ notifyPsSelectedInternal();
+ });
+ } else {
+ notifyPsSelectedInternal();
+ }
+ }
+ }
+
+ private void notifyPsSelectedInternal() {
+ if (mWwanSelectorCallback != null) {
+ logd("notifyPsSelected - onWwanSelected");
+ mWwanSelectorCallback.onDomainSelected(NetworkRegistrationInfo.DOMAIN_PS, false);
+ } else {
+ loge("wwanSelectorCallback is null");
+ mTransportSelectorCallback.onSelectionTerminated(DisconnectCause.OUTGOING_FAILURE);
+ }
+ }
+
+ private void notifyCsSelected() {
+ logd("notifyCsSelected");
+ mStopDomainSelection = true;
+ if (mWwanSelectorCallback == null) {
+ mTransportSelectorCallback.onWwanSelected((callback) -> {
+ mWwanSelectorCallback = callback;
+ notifyCsSelectedInternal();
+ });
+ } else {
+ notifyCsSelectedInternal();
+ }
+ }
+
+ private void notifyCsSelectedInternal() {
+ if (mWwanSelectorCallback != null) {
+ logd("wwanSelectorCallback -> onDomainSelected(DOMAIN_CS)");
+ mWwanSelectorCallback.onDomainSelected(NetworkRegistrationInfo.DOMAIN_CS, false);
+ } else {
+ loge("wwanSelectorCallback is null");
+ mTransportSelectorCallback.onSelectionTerminated(DisconnectCause.OUTGOING_FAILURE);
+ }
+ }
+
+ private void notifySelectionTerminated(@DisconnectCauses int cause) {
+ mStopDomainSelection = true;
+ if (mTransportSelectorCallback != null) {
+ mTransportSelectorCallback.onSelectionTerminated(cause);
+ finishSelection();
+ }
+ }
+
+ private boolean isOutOfService() {
+ return (mServiceState.getState() == ServiceState.STATE_OUT_OF_SERVICE
+ || mServiceState.getState() == ServiceState.STATE_POWER_OFF
+ || mServiceState.getState() == ServiceState.STATE_EMERGENCY_ONLY);
+ }
+
+ private boolean isWpsCallSupportedByIms() {
+ CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class);
+
+ PersistableBundle config = null;
+ if (configManager != null) {
+ config = configManager.getConfigForSubId(mSelectionAttributes.getSubId());
+ }
+
+ return (config != null)
+ ? config.getBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL) : false;
+ }
+
+ private void handleWpsCall() {
+ if (isWpsCallSupportedByIms()) {
+ logd("WPS call placed over PS");
+ notifyPsSelected();
+ } else {
+ if (isOutOfService()) {
+ loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+ notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+ } else {
+ logd("WPS call placed over CS");
+ notifyCsSelected();
+ }
+ }
+ }
+
+ private boolean isTtySupportedByIms() {
+ CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class);
+
+ PersistableBundle config = null;
+ if (configManager != null) {
+ config = configManager.getConfigForSubId(mSelectionAttributes.getSubId());
+ }
+
+ return (config != null)
+ && config.getBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL);
+ }
+
+ private boolean isTtyModeEnabled() {
+ TelecomManager tm = mContext.getSystemService(TelecomManager.class);
+ if (tm == null) {
+ loge("isTtyModeEnabled: telecom not available");
+ return false;
+ }
+ return tm.getCurrentTtyMode() != TelecomManager.TTY_MODE_OFF;
+ }
+
+ private synchronized void selectDomain() {
+ if (mStopDomainSelection || mSelectionAttributes == null
+ || mTransportSelectorCallback == null) {
+ logd("Domain Selection is stopped.");
+ return;
+ }
+
+ if (mServiceState == null) {
+ logd("Waiting for ServiceState callback.");
+ return;
+ }
+
+ // Check if this is a re-dial scenario
+ // IMS -> CS
+ ImsReasonInfo imsReasonInfo = mSelectionAttributes.getPsDisconnectCause();
+ if (mReselectDomain && imsReasonInfo != null) {
+ logd("PsDisconnectCause:" + imsReasonInfo.mCode);
+ mReselectDomain = false;
+ if (imsReasonInfo.mCode == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED) {
+ if (isOutOfService()) {
+ loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+ notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+ } else {
+ logd("Redialing over CS");
+ notifyCsSelected();
+ }
+ return;
+ } else {
+ logd("Redialing cancelled.");
+ // Not a valid redial
+ notifySelectionTerminated(DisconnectCause.NOT_VALID);
+ return;
+ }
+ }
+
+ // CS -> IMS
+ // TODO: @PreciseDisconnectCauses doesn't contain cause code related to redial on IMS.
+ if (mReselectDomain /*mSelectionAttributes.getCsDisconnectCause() == IMS_REDIAL_CODE*/) {
+ logd("Redialing cancelled.");
+ // Not a valid redial
+ notifySelectionTerminated(DisconnectCause.NOT_VALID);
+ return;
+ }
+
+ if (!mImsStateTracker.isMmTelFeatureAvailable()) {
+ logd("MmTelFeatureAvailable unavailable");
+ if (isOutOfService()) {
+ loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+ notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+ } else {
+ notifyCsSelected();
+ }
+ return;
+ }
+
+ if (!mImsRegStateReceived || !mMmTelCapabilitiesReceived) {
+ loge("Waiting for ImsState and MmTelCapabilities callbacks");
+ return;
+ }
+
+ // Check IMS registration state.
+ if (!mImsStateTracker.isImsRegistered()) {
+ logd("IMS is NOT registered");
+ if (isOutOfService()) {
+ loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+ notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+ } else {
+ notifyCsSelected();
+ }
+ return;
+ }
+
+ // Check TTY
+ if (isTtyModeEnabled() && !isTtySupportedByIms()) {
+ if (isOutOfService()) {
+ loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+ notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+ } else {
+ notifyCsSelected();
+ }
+ return;
+ }
+
+ // Handle video call.
+ if (mSelectionAttributes.isVideoCall()) {
+ logd("It's a video call");
+ if (mImsStateTracker.isImsVideoCapable()) {
+ logd("IMS is video capable");
+ notifyPsSelected();
+ } else {
+ logd("IMS is not video capable. Ending the call");
+ notifySelectionTerminated(DisconnectCause.OUTGOING_FAILURE);
+ }
+ return;
+ }
+
+ // Handle voice call.
+ if (mImsStateTracker.isImsVoiceCapable()) {
+ logd("IMS is voice capable");
+ // TODO(b/266175810) Remove this dependency.
+ if (NormalCallDomainSelectionConnection
+ .isWpsCall(mSelectionAttributes.getNumber())) {
+ handleWpsCall();
+ } else {
+ notifyPsSelected();
+ }
+ } else {
+ logd("IMS is not voice capable");
+ // Voice call CS fallback
+ if (isOutOfService()) {
+ loge("Cannot place call in current ServiceState: " + mServiceState.getState());
+ notifySelectionTerminated(DisconnectCause.OUT_OF_SERVICE);
+ } else {
+ notifyCsSelected();
+ }
+ }
+ }
+}
diff --git a/src/com/android/services/telephony/domainselection/SmsDomainSelector.java b/src/com/android/services/telephony/domainselection/SmsDomainSelector.java
new file mode 100644
index 0000000..6930b13
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/SmsDomainSelector.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Looper;
+import android.os.Message;
+import android.telephony.DisconnectCause;
+import android.telephony.DomainSelectionService;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.TransportSelectorCallback;
+
+/**
+ * Implements SMS domain selector for sending MO SMS.
+ */
+public class SmsDomainSelector extends DomainSelectorBase implements
+ ImsStateTracker.ImsStateListener {
+ protected static final int EVENT_SELECT_DOMAIN = 101;
+
+ protected boolean mDestroyed = false;
+ private boolean mDomainSelectionRequested = false;
+
+ public SmsDomainSelector(Context context, int slotId, int subId, @NonNull Looper looper,
+ @NonNull ImsStateTracker imsStateTracker, @NonNull DestroyListener listener) {
+ this(context, slotId, subId, looper, imsStateTracker, listener, "DomainSelector-SMS");
+ }
+
+ protected SmsDomainSelector(Context context, int slotId, int subId, @NonNull Looper looper,
+ @NonNull ImsStateTracker imsStateTracker, @NonNull DestroyListener listener,
+ String logTag) {
+ super(context, slotId, subId, looper, imsStateTracker, listener, logTag);
+ }
+
+ @Override
+ public void destroy() {
+ if (mDestroyed) {
+ return;
+ }
+ logd("destroy");
+ mDestroyed = true;
+ mImsStateTracker.removeImsStateListener(this);
+ super.destroy();
+ }
+
+ @Override
+ public void handleMessage(@NonNull Message msg) {
+ switch (msg.what) {
+ case EVENT_SELECT_DOMAIN:
+ selectDomain();
+ break;
+ default:
+ super.handleMessage(msg);
+ break;
+ }
+ }
+
+ @Override
+ public void cancelSelection() {
+ logi("cancelSelection");
+ finishSelection();
+ }
+
+ @Override
+ public void reselectDomain(@NonNull SelectionAttributes attr) {
+ if (isDomainSelectionRequested()) {
+ // The domain selection is already requested,
+ // so we don't need to request it again before completing the previous task.
+ logi("Domain selection is already running.");
+ return;
+ }
+
+ logi("reselectDomain");
+ mSelectionAttributes = attr;
+ setDomainSelectionRequested(true);
+ obtainMessage(EVENT_SELECT_DOMAIN).sendToTarget();
+ }
+
+ @Override
+ public void finishSelection() {
+ logi("finishSelection");
+ setDomainSelectionRequested(false);
+ mSelectionAttributes = null;
+ mTransportSelectorCallback = null;
+ mWwanSelectorCallback = null;
+ destroy();
+ }
+
+ @Override
+ public void selectDomain(SelectionAttributes attr, TransportSelectorCallback callback) {
+ if (isDomainSelectionRequested()) {
+ // The domain selection is already requested,
+ // so we don't need to request it again before completing the previous task.
+ logi("Domain selection is already running.");
+ return;
+ }
+ mSelectionAttributes = attr;
+ mTransportSelectorCallback = callback;
+ setDomainSelectionRequested(true);
+ mImsStateTracker.addImsStateListener(this);
+ obtainMessage(EVENT_SELECT_DOMAIN).sendToTarget();
+ }
+
+ @Override
+ public void onImsMmTelFeatureAvailableChanged() {
+ sendMessageForDomainSelection();
+ }
+
+ @Override
+ public void onImsRegistrationStateChanged() {
+ sendMessageForDomainSelection();
+ }
+
+ @Override
+ public void onImsMmTelCapabilitiesChanged() {
+ sendMessageForDomainSelection();
+ }
+
+ protected boolean isSmsOverImsAvailable() {
+ return mImsStateTracker.isImsSmsCapable()
+ && mImsStateTracker.isImsRegistered()
+ && mImsStateTracker.isMmTelFeatureAvailable();
+ }
+
+ protected void selectDomain() {
+ if (!isDomainSelectionRequested()) {
+ logi("Domain selection is not requested!");
+ return;
+ }
+
+ logi("selectDomain: " + mImsStateTracker.imsStateToString());
+
+ if (isSmsOverImsAvailable()) {
+ if (mImsStateTracker.isImsRegisteredOverWlan()) {
+ notifyWlanSelected();
+ return;
+ }
+ notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_PS);
+ } else {
+ notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_CS);
+ }
+ }
+
+ protected void sendMessageForDomainSelection() {
+ // If the event is already queued to this handler,
+ // it will be removed first to avoid the duplicate operation.
+ removeMessages(EVENT_SELECT_DOMAIN);
+ // Since the IMS state may have already been posted,
+ // proceed with the domain selection after processing all pending messages.
+ obtainMessage(EVENT_SELECT_DOMAIN).sendToTarget();
+ }
+
+ protected boolean isDomainSelectionRequested() {
+ return mDomainSelectionRequested;
+ }
+
+ protected void setDomainSelectionRequested(boolean requested) {
+ if (mDomainSelectionRequested != requested) {
+ logd("DomainSelectionRequested: " + mDomainSelectionRequested + " >> " + requested);
+ mDomainSelectionRequested = requested;
+ }
+ }
+
+ protected void notifyWlanSelected() {
+ logi("DomainSelected: WLAN");
+ mTransportSelectorCallback.onWlanSelected(false);
+ setDomainSelectionRequested(false);
+ }
+
+ protected void notifyWwanSelected(@NetworkRegistrationInfo.Domain int domain) {
+ if (mWwanSelectorCallback == null) {
+ mTransportSelectorCallback.onWwanSelected((callback) -> {
+ mWwanSelectorCallback = callback;
+ notifyWwanSelectedInternal(domain);
+ });
+ } else {
+ notifyWwanSelectedInternal(domain);
+ }
+
+ setDomainSelectionRequested(false);
+ }
+
+ protected void notifyWwanSelectedInternal(@NetworkRegistrationInfo.Domain int domain) {
+ logi("DomainSelected: WWAN/" + DomainSelectionService.getDomainName(domain));
+
+ if (mWwanSelectorCallback != null) {
+ mWwanSelectorCallback.onDomainSelected(domain, false);
+ } else {
+ mTransportSelectorCallback.onSelectionTerminated(DisconnectCause.LOCAL);
+ }
+ }
+}
diff --git a/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java b/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java
new file mode 100644
index 0000000..3a8fc86
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java
@@ -0,0 +1,527 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.telephony.BarringInfo;
+import android.telephony.DisconnectCause;
+import android.telephony.DomainSelectionService;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
+import android.telephony.TelephonyManager;
+import android.telephony.TransportSelectorCallback;
+import android.util.IndentingPrintWriter;
+import android.util.LocalLog;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Implements the telephony domain selection for various telephony features.
+ */
+public class TelephonyDomainSelectionService extends DomainSelectionService {
+ /**
+ * Testing interface for injecting mock ImsStateTracker.
+ */
+ @VisibleForTesting
+ public interface ImsStateTrackerFactory {
+ /**
+ * @return The {@link ImsStateTracker} created for the specified slot.
+ */
+ ImsStateTracker create(Context context, int slotId, @NonNull Looper looper);
+ }
+
+ /**
+ * Testing interface for injecting mock DomainSelector.
+ */
+ @VisibleForTesting
+ public interface DomainSelectorFactory {
+ /**
+ * @return The {@link DomainSelectorBase} created using the specified arguments.
+ */
+ DomainSelectorBase create(Context context, int slotId, int subId,
+ @SelectorType int selectorType, boolean isEmergency, @NonNull Looper looper,
+ @NonNull ImsStateTracker imsStateTracker,
+ @NonNull DomainSelectorBase.DestroyListener listener,
+ @NonNull CrossSimRedialingController crossSimRedialingController);
+ }
+
+ private static final class DefaultDomainSelectorFactory implements DomainSelectorFactory {
+ @Override
+ public DomainSelectorBase create(Context context, int slotId, int subId,
+ @SelectorType int selectorType, boolean isEmergency, @NonNull Looper looper,
+ @NonNull ImsStateTracker imsStateTracker,
+ @NonNull DomainSelectorBase.DestroyListener listener,
+ @NonNull CrossSimRedialingController crossSimRedialingController) {
+ DomainSelectorBase selector = null;
+
+ logi("create-DomainSelector: slotId=" + slotId + ", subId=" + subId
+ + ", selectorType=" + selectorTypeToString(selectorType)
+ + ", emergency=" + isEmergency);
+
+ switch (selectorType) {
+ case SELECTOR_TYPE_CALLING:
+ if (isEmergency) {
+ selector = new EmergencyCallDomainSelector(context, slotId, subId, looper,
+ imsStateTracker, listener, crossSimRedialingController);
+ } else {
+ selector = new NormalCallDomainSelector(context, slotId, subId, looper,
+ imsStateTracker, listener);
+ }
+ break;
+ case SELECTOR_TYPE_SMS:
+ if (isEmergency) {
+ selector = new EmergencySmsDomainSelector(context, slotId, subId, looper,
+ imsStateTracker, listener);
+ } else {
+ selector = new SmsDomainSelector(context, slotId, subId, looper,
+ imsStateTracker, listener);
+ }
+ break;
+ default:
+ // Not reachable.
+ break;
+ }
+
+ return selector;
+ }
+ };
+
+ /**
+ * A container class to manage the domain selector per a slot and selector type.
+ * If the domain selector is not null and reusable, the same domain selector will be used
+ * for the specific slot.
+ */
+ private static final class DomainSelectorContainer {
+ private final int mSlotId;
+ private final @SelectorType int mSelectorType;
+ private final boolean mIsEmergency;
+ private final @NonNull DomainSelectorBase mSelector;
+
+ DomainSelectorContainer(int slotId, @SelectorType int selectorType, boolean isEmergency,
+ @NonNull DomainSelectorBase selector) {
+ mSlotId = slotId;
+ mSelectorType = selectorType;
+ mIsEmergency = isEmergency;
+ mSelector = selector;
+ }
+
+ public int getSlotId() {
+ return mSlotId;
+ }
+
+ public @SelectorType int getSelectorType() {
+ return mSelectorType;
+ }
+
+ public DomainSelectorBase getDomainSelector() {
+ return mSelector;
+ }
+
+ public boolean isEmergency() {
+ return mIsEmergency;
+ }
+
+ @Override
+ public String toString() {
+ return new StringBuilder()
+ .append("{ ")
+ .append("slotId=").append(mSlotId)
+ .append(", selectorType=").append(selectorTypeToString(mSelectorType))
+ .append(", isEmergency=").append(mIsEmergency)
+ .append(", selector=").append(mSelector)
+ .append(" }").toString();
+ }
+ }
+
+ private final DomainSelectorBase.DestroyListener mDestroyListener =
+ new DomainSelectorBase.DestroyListener() {
+ @Override
+ public void onDomainSelectorDestroyed(DomainSelectorBase selector) {
+ logd("DomainSelector destroyed: " + selector);
+ removeDomainSelector(selector);
+ }
+ };
+
+ /**
+ * A class to listen for the subscription change for starting {@link ImsStateTracker}
+ * to monitor the IMS states.
+ */
+ private final OnSubscriptionsChangedListener mSubscriptionsChangedListener =
+ new OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ handleSubscriptionsChanged();
+ }
+ };
+
+ private static final String TAG = TelephonyDomainSelectionService.class.getSimpleName();
+
+ // Persistent Logging
+ private static final LocalLog sEventLog = new LocalLog(20);
+ private final Context mContext;
+ // Map of slotId -> ImsStateTracker
+ private final SparseArray<ImsStateTracker> mImsStateTrackers = new SparseArray<>(2);
+ private final List<DomainSelectorContainer> mDomainSelectorContainers = new ArrayList<>();
+ private final ImsStateTrackerFactory mImsStateTrackerFactory;
+ private final DomainSelectorFactory mDomainSelectorFactory;
+ private Handler mServiceHandler;
+ private CrossSimRedialingController mCrossSimRedialingController;
+
+ public TelephonyDomainSelectionService(Context context) {
+ this(context, ImsStateTracker::new, new DefaultDomainSelectorFactory());
+ }
+
+ @VisibleForTesting
+ public TelephonyDomainSelectionService(Context context,
+ @NonNull ImsStateTrackerFactory imsStateTrackerFactory,
+ @NonNull DomainSelectorFactory domainSelectorFactory) {
+ mContext = context;
+ mImsStateTrackerFactory = imsStateTrackerFactory;
+ mDomainSelectorFactory = domainSelectorFactory;
+
+ // Create a worker thread for this domain selection service.
+ getExecutor();
+
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ int activeModemCount = (tm != null) ? tm.getActiveModemCount() : 1;
+ for (int i = 0; i < activeModemCount; ++i) {
+ mImsStateTrackers.put(i, mImsStateTrackerFactory.create(mContext, i, getLooper()));
+ }
+
+ SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
+ if (sm != null) {
+ sm.addOnSubscriptionsChangedListener(getExecutor(), mSubscriptionsChangedListener);
+ } else {
+ loge("Adding OnSubscriptionChangedListener failed");
+ }
+
+ mCrossSimRedialingController = new CrossSimRedialingController(context, getLooper());
+
+ logi("TelephonyDomainSelectionService created");
+ }
+
+ @Override
+ public void onDestroy() {
+ logd("onDestroy");
+
+ List<DomainSelectorContainer> domainSelectorContainers;
+
+ synchronized (mDomainSelectorContainers) {
+ domainSelectorContainers = new ArrayList<>(mDomainSelectorContainers);
+ mDomainSelectorContainers.clear();
+ }
+
+ for (DomainSelectorContainer dsc : domainSelectorContainers) {
+ DomainSelectorBase selector = dsc.getDomainSelector();
+ if (selector != null) {
+ selector.destroy();
+ }
+ }
+ domainSelectorContainers.clear();
+
+ synchronized (mImsStateTrackers) {
+ for (int i = 0; i < mImsStateTrackers.size(); ++i) {
+ ImsStateTracker ist = mImsStateTrackers.get(i);
+ if (ist != null) {
+ ist.destroy();
+ }
+ }
+ mImsStateTrackers.clear();
+ }
+
+ SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
+ if (sm != null) {
+ sm.removeOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
+ }
+
+ if (mCrossSimRedialingController != null) {
+ mCrossSimRedialingController.destroy();
+ mCrossSimRedialingController = null;
+ }
+
+ if (mServiceHandler != null) {
+ mServiceHandler.getLooper().quit();
+ mServiceHandler = null;
+ }
+ }
+
+ /**
+ * Selects a domain for the given attributes and callback.
+ *
+ * @param attr required to determine the domain.
+ * @param callback the callback instance being registered.
+ */
+ @Override
+ public void onDomainSelection(@NonNull SelectionAttributes attr,
+ @NonNull TransportSelectorCallback callback) {
+ final int slotId = attr.getSlotId();
+ final int subId = attr.getSubId();
+ final int selectorType = attr.getSelectorType();
+ final boolean isEmergency = attr.isEmergency();
+ ImsStateTracker ist = getImsStateTracker(slotId);
+ DomainSelectorBase selector = mDomainSelectorFactory.create(mContext, slotId, subId,
+ selectorType, isEmergency, getLooper(), ist, mDestroyListener,
+ mCrossSimRedialingController);
+
+ if (selector != null) {
+ // Ensures that ImsStateTracker is started before selecting the domain if not started
+ // for the specified subscription index.
+ ist.start(subId);
+ addDomainSelector(slotId, selectorType, isEmergency, selector);
+ } else {
+ loge("No proper domain selector: " + selectorTypeToString(selectorType));
+ callback.onSelectionTerminated(DisconnectCause.ERROR_UNSPECIFIED);
+ return;
+ }
+
+ // Notify the caller that the domain selector is created.
+ callback.onCreated(selector);
+
+ // Performs the domain selection.
+ selector.selectDomain(attr, callback);
+ }
+
+ /**
+ * Called when the {@link ServiceState} needs to be updated for the specified slot and
+ * subcription index.
+ *
+ * @param slotId for which the service state changed.
+ * @param subId The current subscription for a specified slot.
+ * @param serviceState The {@link ServiceState} to be updated.
+ */
+ @Override
+ public void onServiceStateUpdated(int slotId, int subId, @NonNull ServiceState serviceState) {
+ ImsStateTracker ist = getImsStateTracker(slotId);
+ if (ist != null) {
+ ist.updateServiceState(serviceState);
+ }
+ }
+
+ /**
+ * Called when the {@link BarringInfo} needs to be updated for the specified slot and
+ * subscription index.
+ *
+ * @param slotId The slot the BarringInfo is updated for.
+ * @param subId The current subscription for a specified slot.
+ * @param barringInfo The {@link BarringInfo} to be updated.
+ */
+ @Override
+ public void onBarringInfoUpdated(int slotId, int subId, @NonNull BarringInfo barringInfo) {
+ ImsStateTracker ist = getImsStateTracker(slotId);
+ if (ist != null) {
+ ist.updateBarringInfo(barringInfo);
+ }
+ }
+
+ /**
+ * Returns an Executor used to execute methods called remotely by the framework.
+ */
+ @SuppressLint("OnNameExpected")
+ @Override
+ public @NonNull Executor getExecutor() {
+ if (mServiceHandler == null) {
+ HandlerThread handlerThread = new HandlerThread(TAG);
+ handlerThread.start();
+ mServiceHandler = new Handler(handlerThread.getLooper());
+ }
+
+ return mServiceHandler::post;
+ }
+
+ /**
+ * Returns a Looper instance.
+ */
+ @VisibleForTesting
+ public Looper getLooper() {
+ getExecutor();
+ return mServiceHandler.getLooper();
+ }
+
+ /**
+ * Handles the subscriptions change.
+ */
+ private void handleSubscriptionsChanged() {
+ SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
+ List<SubscriptionInfo> subsInfoList =
+ (sm != null) ? sm.getActiveSubscriptionInfoList() : null;
+
+ if (subsInfoList == null || subsInfoList.isEmpty()) {
+ logd("handleSubscriptionsChanged: No valid SubscriptionInfo");
+ return;
+ }
+
+ for (int i = 0; i < subsInfoList.size(); ++i) {
+ SubscriptionInfo subsInfo = subsInfoList.get(i);
+ int slotId = subsInfo.getSimSlotIndex();
+
+ if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ logd("handleSubscriptionsChanged: slotId=" + slotId);
+ ImsStateTracker ist = getImsStateTracker(slotId);
+ ist.start(subsInfo.getSubscriptionId());
+ }
+ }
+ }
+
+ /**
+ * Adds the {@link DomainSelectorBase} to the list of domain selector container.
+ */
+ private void addDomainSelector(int slotId, @SelectorType int selectorType,
+ boolean isEmergency, @NonNull DomainSelectorBase selector) {
+ synchronized (mDomainSelectorContainers) {
+ // If the domain selector already exists, remove the previous one first.
+ for (int i = 0; i < mDomainSelectorContainers.size(); ++i) {
+ DomainSelectorContainer dsc = mDomainSelectorContainers.get(i);
+
+ if (dsc.getSlotId() == slotId
+ && dsc.getSelectorType() == selectorType
+ && dsc.isEmergency() == isEmergency) {
+ mDomainSelectorContainers.remove(i);
+ DomainSelectorBase oldSelector = dsc.getDomainSelector();
+ if (oldSelector != null) {
+ logw("DomainSelector destroyed by new domain selection request: " + dsc);
+ oldSelector.destroy();
+ }
+ break;
+ }
+ }
+
+ DomainSelectorContainer dsc =
+ new DomainSelectorContainer(slotId, selectorType, isEmergency, selector);
+ mDomainSelectorContainers.add(dsc);
+
+ logi("DomainSelector added: " + dsc + ", count=" + mDomainSelectorContainers.size());
+ }
+ }
+
+ /**
+ * Removes the domain selector container that matches with the specified
+ * {@link DomainSelectorBase}.
+ */
+ private void removeDomainSelector(@NonNull DomainSelectorBase selector) {
+ synchronized (mDomainSelectorContainers) {
+ for (int i = 0; i < mDomainSelectorContainers.size(); ++i) {
+ DomainSelectorContainer dsc = mDomainSelectorContainers.get(i);
+
+ if (dsc.getDomainSelector() == selector) {
+ mDomainSelectorContainers.remove(i);
+ logi("DomainSelector removed: " + dsc
+ + ", count=" + mDomainSelectorContainers.size());
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the {@link ImsStateTracker} instance for the specified slot.
+ * If the {@link ImsStateTracker} does not exist for the slot, it creates new instance
+ * and returns.
+ */
+ private ImsStateTracker getImsStateTracker(int slotId) {
+ synchronized (mImsStateTrackers) {
+ ImsStateTracker ist = mImsStateTrackers.get(slotId);
+
+ if (ist == null) {
+ ist = mImsStateTrackerFactory.create(mContext, slotId, getLooper());
+ mImsStateTrackers.put(slotId, ist);
+ }
+
+ return ist;
+ }
+ }
+
+ private static String selectorTypeToString(@SelectorType int selectorType) {
+ switch (selectorType) {
+ case SELECTOR_TYPE_CALLING: return "CALLING";
+ case SELECTOR_TYPE_SMS: return "SMS";
+ case SELECTOR_TYPE_UT: return "UT";
+ default: return Integer.toString(selectorType);
+ }
+ }
+
+ private static void logd(String s) {
+ Log.d(TAG, s);
+ }
+
+ private static void logi(String s) {
+ Log.i(TAG, s);
+ sEventLog.log(s);
+ }
+
+ private static void loge(String s) {
+ Log.e(TAG, s);
+ sEventLog.log(s);
+ }
+
+ private static void logw(String s) {
+ Log.w(TAG, s);
+ sEventLog.log(s);
+ }
+
+ /**
+ * Dumps this instance into a readable format for dumpsys usage.
+ */
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
+ ipw.println("TelephonyDomainSelectionService:");
+ ipw.increaseIndent();
+ ipw.println("ImsStateTrackers:");
+ synchronized (mImsStateTrackers) {
+ for (int i = 0; i < mImsStateTrackers.size(); ++i) {
+ ImsStateTracker ist = mImsStateTrackers.valueAt(i);
+ ist.dump(ipw);
+ }
+ }
+ ipw.decreaseIndent();
+ ipw.increaseIndent();
+ synchronized (mDomainSelectorContainers) {
+ for (int i = 0; i < mDomainSelectorContainers.size(); ++i) {
+ DomainSelectorContainer dsc = mDomainSelectorContainers.get(i);
+ ipw.println("DomainSelector: " + dsc.toString());
+ ipw.increaseIndent();
+ DomainSelectorBase selector = dsc.getDomainSelector();
+ if (selector != null) {
+ selector.dump(ipw);
+ }
+ ipw.decreaseIndent();
+ }
+ }
+ ipw.decreaseIndent();
+ ipw.increaseIndent();
+ ipw.println("Event Log:");
+ ipw.increaseIndent();
+ sEventLog.dump(ipw);
+ ipw.decreaseIndent();
+ ipw.decreaseIndent();
+ ipw.println("________________________________");
+ }
+}
diff --git a/src/com/android/services/telephony/rcs/MessageTransportWrapper.java b/src/com/android/services/telephony/rcs/MessageTransportWrapper.java
index 45f7d95..d992883 100644
--- a/src/com/android/services/telephony/rcs/MessageTransportWrapper.java
+++ b/src/com/android/services/telephony/rcs/MessageTransportWrapper.java
@@ -481,6 +481,16 @@
}
}
+ /**
+ * This is a listener to handle SipDialog state of delegate
+ * @param listener {@link SipDialogsStateListener}
+ * @param isNeedNotify It indicates whether the current dialogs state should be notified.
+ */
+ public void setSipDialogsListener(SipDialogsStateListener listener,
+ boolean isNeedNotify) {
+ mSipSessionTracker.setSipDialogsListener(listener, isNeedNotify);
+ }
+
private void logi(String log) {
Log.i(SipTransportController.LOG_TAG, TAG + "[" + mSubId + "] " + log);
mLocalLog.log("[I] " + log);
diff --git a/src/com/android/services/telephony/rcs/RcsFeatureController.java b/src/com/android/services/telephony/rcs/RcsFeatureController.java
index 0e1cb4b..a2f435c 100644
--- a/src/com/android/services/telephony/rcs/RcsFeatureController.java
+++ b/src/com/android/services/telephony/rcs/RcsFeatureController.java
@@ -17,10 +17,13 @@
package com.android.services.telephony.rcs;
import android.annotation.AnyThread;
+import android.annotation.NonNull;
import android.content.Context;
import android.net.Uri;
+import android.telephony.SubscriptionManager;
import android.telephony.ims.ImsException;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsRegistrationAttributes;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -165,7 +168,7 @@
private ImsRegistrationCallbackHelper.ImsRegistrationUpdate mRcsRegistrationUpdate = new
ImsRegistrationCallbackHelper.ImsRegistrationUpdate() {
@Override
- public void handleImsRegistered(int imsRadioTech) {
+ public void handleImsRegistered(@NonNull ImsRegistrationAttributes attributes) {
}
@Override
@@ -173,7 +176,8 @@
}
@Override
- public void handleImsUnregistered(ImsReasonInfo imsReasonInfo) {
+ public void handleImsUnregistered(ImsReasonInfo imsReasonInfo,
+ int suggestedAction, int imsRadioTech) {
}
@Override
@@ -402,6 +406,17 @@
callback.accept(mImsRcsRegistrationHelper.getImsRegistrationState());
}
+ /**
+ * @return the subscription ID that is currently associated with this RCS feature.
+ */
+ public int getAssociatedSubId() {
+ RcsFeatureManager manager = getFeatureManager();
+ if (manager != null) {
+ return manager.getSubId();
+ }
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
private void updateCapabilities() {
RcsFeatureManager manager = getFeatureManager();
if (manager != null) {
diff --git a/src/com/android/services/telephony/rcs/SipDelegateController.java b/src/com/android/services/telephony/rcs/SipDelegateController.java
index 860a6d9..f7fc359 100644
--- a/src/com/android/services/telephony/rcs/SipDelegateController.java
+++ b/src/com/android/services/telephony/rcs/SipDelegateController.java
@@ -391,6 +391,16 @@
}
/**
+ * This is a listener to handle SipDialog state of delegate
+ * @param listener {@link SipDialogsStateListener}
+ * @param isNeedNotify It indicates whether the current dialogs state should be notified.
+ */
+ public void setSipDialogsListener(SipDialogsStateListener listener,
+ boolean isNeedNotify) {
+ mMessageTransportWrapper.setSipDialogsListener(listener, isNeedNotify);
+ }
+
+ /**
* Write the current state of this controller in String format using the PrintWriter provided
* for dumpsys.
*/
diff --git a/src/com/android/services/telephony/rcs/SipDialogsStateListener.java b/src/com/android/services/telephony/rcs/SipDialogsStateListener.java
new file mode 100644
index 0000000..bbd3bd1
--- /dev/null
+++ b/src/com/android/services/telephony/rcs/SipDialogsStateListener.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.rcs;
+
+import android.telephony.ims.SipDialogState;
+
+import java.util.List;
+
+/**
+ * The listener interface for notifying the state of sip dialogs to SipDialogsStateHandle.
+ * refer to {@link SipTransportController}
+ */
+public interface SipDialogsStateListener {
+ /**
+ * To map dialog state information of available delegates
+ * @param key This is an ID of SipSessionTracker for distinguishing whose delegate is
+ * during dialog mapping.
+ * @param dialogStates This is dialog state information of delegate
+ */
+ void reMappingSipDelegateState(String key, List<SipDialogState> dialogStates);
+
+ /**
+ * Notify SipDialogState information with
+ * {@link com.android.internal.telephony.ISipDialogStateCallback}
+ */
+ void notifySipDialogState();
+}
diff --git a/src/com/android/services/telephony/rcs/SipSessionTracker.java b/src/com/android/services/telephony/rcs/SipSessionTracker.java
index 68e3065..2d48a9f 100644
--- a/src/com/android/services/telephony/rcs/SipSessionTracker.java
+++ b/src/com/android/services/telephony/rcs/SipSessionTracker.java
@@ -16,6 +16,7 @@
package com.android.services.telephony.rcs;
+import android.telephony.ims.SipDialogState;
import android.telephony.ims.SipMessage;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -33,6 +34,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
+import java.util.UUID;
import java.util.stream.Collectors;
/**
@@ -69,10 +71,13 @@
private final RcsStats mRcsStats;
int mSubId;
+ private SipDialogsStateListener mSipDialogsListener;
+ private String mDelegateKey;
public SipSessionTracker(int subId, RcsStats rcsStats) {
mSubId = subId;
mRcsStats = rcsStats;
+ mDelegateKey = String.valueOf(UUID.randomUUID());
}
/**
@@ -152,6 +157,7 @@
logi("Dialog closed: " + d);
}
mTrackedDialogs.removeAll(dialogsToCleanup);
+ notifySipDialogState();
}
/**
@@ -213,6 +219,7 @@
}
mTrackedDialogs.clear();
mPendingAck.clear();
+ notifySipDialogState();
}
/**
@@ -308,6 +315,7 @@
d.close();
logi("Dialog closed: " + d);
}
+ notifySipDialogState();
};
}
@@ -365,16 +373,47 @@
if (statusCode >= 300) {
mRcsStats.onSipTransportSessionClosed(mSubId, m.getCallIdParameter(), statusCode, true);
d.close();
+ notifySipDialogState();
return;
}
if (toTag == null) logw("updateSipDialogState: No to tag for message: " + m);
if (statusCode >= 200) {
mRcsStats.confirmedSipTransportSession(m.getCallIdParameter(), statusCode);
d.confirm(toTag);
+ notifySipDialogState();
return;
}
// 1XX responses still require updates to dialogs.
d.earlyResponse(toTag);
+ notifySipDialogState();
+ }
+
+ /**
+ * This is a listener to handle SipDialog state of delegate
+ * @param listener {@link SipDialogsStateListener}
+ * @param isNeedNotify It indicates whether the current dialogs state should be notified.
+ */
+ public void setSipDialogsListener(SipDialogsStateListener listener,
+ boolean isNeedNotify) {
+ mSipDialogsListener = listener;
+ if (listener == null) {
+ return;
+ }
+ if (isNeedNotify) {
+ notifySipDialogState();
+ }
+ }
+
+ private void notifySipDialogState() {
+ if (mSipDialogsListener == null) {
+ return;
+ }
+ List<SipDialogState> dialogStates = new ArrayList<>();
+ for (SipDialog d : mTrackedDialogs) {
+ SipDialogState dialog = new SipDialogState.Builder(d.getState()).build();
+ dialogStates.add(dialog);
+ }
+ mSipDialogsListener.reMappingSipDelegateState(mDelegateKey, dialogStates);
}
private void logi(String log) {
diff --git a/src/com/android/services/telephony/rcs/SipTransportController.java b/src/com/android/services/telephony/rcs/SipTransportController.java
index 0aa3aa0..2f090d5 100644
--- a/src/com/android/services/telephony/rcs/SipTransportController.java
+++ b/src/com/android/services/telephony/rcs/SipTransportController.java
@@ -29,6 +29,7 @@
import android.telephony.ims.ImsException;
import android.telephony.ims.ImsService;
import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipDialogState;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.ISipDelegate;
import android.telephony.ims.aidl.ISipDelegateConnectionStateCallback;
@@ -46,6 +47,8 @@
import com.android.ims.RcsFeatureManager;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.ISipDialogStateCallback;
+import com.android.internal.telephony.util.RemoteCallbackListExt;
import com.android.internal.util.IndentingPrintWriter;
import com.android.phone.RcsProvisioningMonitor;
@@ -54,8 +57,11 @@
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Locale;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
@@ -238,6 +244,65 @@
}
/**
+ * This is to handle with dialogs of all available delegates that have dialogs.
+ */
+ private final class SipDialogsStateHandle implements SipDialogsStateListener {
+
+ private Executor mExecutor = Runnable::run;
+ Map<String, List<SipDialogState>> mMapDialogState = new HashMap<>();
+
+ /**
+ * This will be called using the {@link SipDialogsStateListener}
+ * @param key This is the ID of the SipSessionTracker for handling the dialogs of
+ * each created delegates.
+ * @param dialogStates This is a list of dialog states tracked in SipSessionTracker.
+ */
+ @Override
+ public void reMappingSipDelegateState(String key,
+ List<SipDialogState> dialogStates) {
+ mExecutor.execute(()->processReMappingSipDelegateState(key, dialogStates));
+ }
+
+ /**
+ * Notify SipDialogState information with
+ * {@link com.android.internal.telephony.ISipDialogStateCallback}
+ */
+ @Override
+ public void notifySipDialogState() {
+ mExecutor.execute(()->processNotifySipDialogState());
+ }
+
+ private void processReMappingSipDelegateState(String key,
+ List<SipDialogState> dialogStates) {
+ if (dialogStates.isEmpty()) {
+ mMapDialogState.remove(key);
+ } else {
+ mMapDialogState.put(key, dialogStates);
+ }
+ notifySipDialogState();
+ }
+
+ private void processNotifySipDialogState() {
+ List<SipDialogState> finalDialogStates = new ArrayList<>();
+ for (List<SipDialogState> d : mMapDialogState.values()) {
+ finalDialogStates.addAll(d);
+ }
+
+ if (mSipDialogStateCallbacks.getRegisteredCallbackCount() == 0) {
+ return;
+ }
+ mSipDialogStateCallbacks.broadcastAction((c) -> {
+ try {
+ c.onActiveSipDialogsChanged(finalDialogStates);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG,
+ "onActiveSipDialogsChanged() - Skipping callback." + e);
+ }
+ });
+ }
+ }
+
+ /**
* Allow the ability for tests to easily mock out the SipDelegateController for testing.
*/
@VisibleForTesting
@@ -265,6 +330,12 @@
private final List<SipDelegateController> mDelegatePendingCreate = new ArrayList<>();
// SipDelegateControllers that are pending to be destroyed.
private final List<DestroyRequest> mDelegatePendingDestroy = new ArrayList<>();
+ // SipDialogStateCallback that are adding to use callback.
+ private final RemoteCallbackListExt<ISipDialogStateCallback> mSipDialogStateCallbacks =
+ new RemoteCallbackListExt<>();
+ // To listen the state information if the dialog status is changed from the SipSessionTracker.
+ private final SipDialogsStateListener mSipDialogsListener = new SipDialogsStateHandle();
+
// Cache of Binders to remote IMS applications for tracking their potential death
private final TrackedAppBinders mActiveAppBinders = new TrackedAppBinders();
@@ -457,6 +528,10 @@
logi("createSipDelegateInternal: request= " + request + ", packageName= " + packageName
+ ", controller created: " + c);
addPendingCreateAndEvaluate(c);
+ // If SipDialogStateCallback is registered, listener will be set.
+ if (mSipDialogStateCallbacks.getRegisteredCallbackCount() > 0) {
+ c.setSipDialogsListener(mSipDialogsListener, false);
+ }
}
private void destroySipDelegateInternal(int subId, ISipDelegate connection, int reason) {
@@ -917,7 +992,7 @@
it.remove();
deniedTags.add(new FeatureTagState(tag,
SipDelegateManager.DENIED_REASON_IN_USE_BY_ANOTHER_DELEGATE));
- } else if (!mFeatureTagsAllowed.contains(tag.trim().toLowerCase())) {
+ } else if (!mFeatureTagsAllowed.contains(tag.trim().toLowerCase(Locale.ROOT))) {
logi(tag + " is not allowed per config.");
it.remove();
deniedTags.add(new FeatureTagState(tag,
@@ -1032,7 +1107,7 @@
CarrierConfigManager.Ims.KEY_RCS_FEATURE_TAG_ALLOWED_STRING_ARRAY);
if (tagConfigs != null && tagConfigs.length > 0) {
for (String tag : tagConfigs) {
- mFeatureTagsAllowed.add(tag.trim().toLowerCase());
+ mFeatureTagsAllowed.add(tag.trim().toLowerCase(Locale.ROOT));
}
}
}
@@ -1056,6 +1131,56 @@
}
}
+ /**
+ * Adds a callback that gets called when SipDialog status has changed.
+ * @param subId The subId associated with the request.
+ * @param cb A {@link android.telephony.ims.SipDialogStateCallback} that will notify the caller
+ * when Dialog status has changed.
+ */
+ public void addCallbackForSipDialogState(int subId, ISipDialogStateCallback cb) {
+ if (subId != mSubId) {
+ logw("addCallbackForSipDialogState the subId is not supported");
+ return;
+ }
+ // callback register and no delegate : register this callback / notify (empty state)
+ // callback register and delegates : register this callback / release listener / notify
+ mSipDialogStateCallbacks.register(cb);
+ if (!mDelegatePriorityQueue.isEmpty()) {
+ for (SipDelegateController dc : mDelegatePriorityQueue) {
+ dc.setSipDialogsListener(mSipDialogsListener, true);
+ }
+ } else {
+ mSipDialogsListener.notifySipDialogState();
+ }
+ }
+
+ /**
+ * Unregister previously registered callback
+ * @param subId The subId associated with the request.
+ * @param cb A {@link android.telephony.ims.SipDialogStateCallback} that will be unregistering.
+ */
+ public void removeCallbackForSipDialogState(int subId, ISipDialogStateCallback cb) {
+ if (subId != mSubId) {
+ logw("addCallbackForSipDialogState the subId is not supported");
+ return;
+ }
+ if (cb == null) {
+ throw new IllegalArgumentException("callback is null");
+ }
+
+ // remove callback register and no delegate : only unregister this callback
+ // remove callback register and delegates :
+ // unregister this callback and setListener(null)
+ mSipDialogStateCallbacks.unregister(cb);
+ if (mSipDialogStateCallbacks.getRegisteredCallbackCount() == 0) {
+ if (!mDelegatePriorityQueue.isEmpty()) {
+ for (SipDelegateController dc : mDelegatePriorityQueue) {
+ dc.setSipDialogsListener(null, false);
+ }
+ }
+ }
+ }
+
@Override
public void dump(PrintWriter printWriter) {
IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
diff --git a/src/com/android/services/telephony/rcs/TelephonyRcsService.java b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
index dfcea74..f6ba40b 100644
--- a/src/com/android/services/telephony/rcs/TelephonyRcsService.java
+++ b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
@@ -25,6 +25,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.util.Log;
@@ -244,6 +245,22 @@
}
/**
+ * Verifies the subId supplied is the active subId for the slotId specified.
+ * If we have not processed a CARRIER_CONFIG_CHANGED indication for this subscription yet,
+ * either the subscription is not active or we have not finished setting up the feature yet.
+ * @param slotId The slotId we are verifying
+ * @param subId The subId we are verifying
+ * @return true if the subId is the active subId we are tracking for the slotId specified.
+ */
+ public boolean verifyActiveSubId(int slotId, int subId) {
+ synchronized (mLock) {
+ int currId = mSlotToAssociatedSubIds.get(slotId,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ return subId == currId;
+ }
+ }
+
+ /**
* ACTION_CARRIER_CONFIG_CHANGED was received by this service for a specific slot.
* @param slotId The slotId associated with the event.
* @param subId The subId associated with the event. May cause the subId associated with the
@@ -335,36 +352,31 @@
private boolean doesSubscriptionSupportPresence(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
- CarrierConfigManager carrierConfigManager =
- mContext.getSystemService(CarrierConfigManager.class);
- if (carrierConfigManager == null) return false;
- boolean supportsUce = carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL);
- supportsUce |= carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL);
+ boolean supportsUce = getConfig(subId,
+ CarrierConfigManager.Ims.KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false /*default*/);
+ supportsUce |= getConfig(subId,
+ CarrierConfigManager.KEY_USE_RCS_SIP_OPTIONS_BOOL, false /*default*/);
return supportsUce;
}
private boolean doesSubscriptionSupportSingleRegistration(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
- CarrierConfigManager carrierConfigManager =
- mContext.getSystemService(CarrierConfigManager.class);
- if (carrierConfigManager == null) return false;
- return carrierConfigManager.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL);
+ return getConfig(subId, CarrierConfigManager.Ims.KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL,
+ false /*defaultValue*/);
}
private int getSubscriptionFromSlot(int slotId) {
- SubscriptionManager manager = mContext.getSystemService(SubscriptionManager.class);
- if (manager == null) {
- Log.w(LOG_TAG, "Couldn't find SubscriptionManager for slotId=" + slotId);
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- }
- int[] subIds = manager.getSubscriptionIds(slotId);
- if (subIds != null && subIds.length > 0) {
- return subIds[0];
- }
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ return SubscriptionManager.getSubscriptionId(slotId);
+ }
+
+ /**
+ * @return the boolean result corresponding to a boolean {@link CarrierConfigManager} key.
+ */
+ private boolean getConfig(int subId, String key, boolean defaultValue) {
+ CarrierConfigManager c = mContext.getSystemService(CarrierConfigManager.class);
+ if (c == null) return defaultValue;
+ PersistableBundle b = c.getConfigForSubId(subId, key);
+ return b != null ? b.getBoolean(key, defaultValue) : defaultValue;
}
/**
diff --git a/src/com/android/services/telephony/rcs/TransportSipMessageValidator.java b/src/com/android/services/telephony/rcs/TransportSipMessageValidator.java
index 3b1b26d..b15992e 100644
--- a/src/com/android/services/telephony/rcs/TransportSipMessageValidator.java
+++ b/src/com/android/services/telephony/rcs/TransportSipMessageValidator.java
@@ -577,6 +577,16 @@
}
}
+ /**
+ * This is a listener to handle SipDialog state of delegate
+ * @param listener {@link SipDialogsStateListener}
+ * @param isNeedNotify It indicates whether the current dialogs state should be notified.
+ */
+ public void setSipDialogsListener(SipDialogsStateListener listener,
+ boolean isNeedNotify) {
+ mSipSessionTracker.setSipDialogsListener(listener, isNeedNotify);
+ }
+
private void logi(String log) {
Log.i(SipTransportController.LOG_TAG, LOG_TAG + "[" + mSubId + "] " + log);
mLocalLog.log("[I] " + log);
diff --git a/src/com/android/services/telephony/rcs/validator/OutgoingTransportStateValidator.java b/src/com/android/services/telephony/rcs/validator/OutgoingTransportStateValidator.java
index 72d22f8..d532ea9 100644
--- a/src/com/android/services/telephony/rcs/validator/OutgoingTransportStateValidator.java
+++ b/src/com/android/services/telephony/rcs/validator/OutgoingTransportStateValidator.java
@@ -29,6 +29,7 @@
import java.util.Arrays;
import java.util.Collections;
+import java.util.Locale;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -166,7 +167,7 @@
}
// Only need to validate requests that start dialogs.
boolean startsDialog = Arrays.stream(SipSessionTracker.SIP_REQUEST_DIALOG_START_METHODS)
- .anyMatch(req -> req.equals(segments[0].trim().toLowerCase()));
+ .anyMatch(req -> req.equals(segments[0].trim().toLowerCase(Locale.ROOT)));
// If part of an existing dialog, then no need to validate.
boolean needsFeatureValidation = startsDialog && !getAllowedCallIds()
.contains(m.getCallIdParameter());
diff --git a/src/com/android/services/telephony/rcs/validator/RestrictedOutgoingSipRequestValidator.java b/src/com/android/services/telephony/rcs/validator/RestrictedOutgoingSipRequestValidator.java
index 2c2632f..afb86a0 100644
--- a/src/com/android/services/telephony/rcs/validator/RestrictedOutgoingSipRequestValidator.java
+++ b/src/com/android/services/telephony/rcs/validator/RestrictedOutgoingSipRequestValidator.java
@@ -22,6 +22,7 @@
import com.android.internal.telephony.SipMessageParsingUtils;
import java.util.Arrays;
+import java.util.Locale;
/**
* Validate that any outgoing SIP request message does not contain methods that are only generated
@@ -47,7 +48,7 @@
"malformed start line: " + message.getStartLine());
}
if (Arrays.stream(IMS_SERVICE_HANDLED_REQUEST_METHODS).anyMatch(
- s -> segments[0].toLowerCase().contains(s))) {
+ s -> segments[0].toLowerCase(Locale.ROOT).contains(s))) {
return new ValidationResult(
SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_START_LINE,
"restricted method: " + segments[0]);
diff --git a/src/com/android/services/telephony/rcs/validator/RestrictedOutgoingSubscribeValidator.java b/src/com/android/services/telephony/rcs/validator/RestrictedOutgoingSubscribeValidator.java
index 41074ed..de6bfe7 100644
--- a/src/com/android/services/telephony/rcs/validator/RestrictedOutgoingSubscribeValidator.java
+++ b/src/com/android/services/telephony/rcs/validator/RestrictedOutgoingSubscribeValidator.java
@@ -24,6 +24,7 @@
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
import java.util.stream.Collectors;
/**
@@ -60,7 +61,8 @@
return ValidationResult.SUCCESS;
}
boolean isRestricted = eventHeaders.stream().map(e -> e.second)
- .anyMatch(e -> Arrays.asList(RESTRICTED_EVENTS).contains(e.trim().toLowerCase()));
+ .anyMatch(e -> Arrays.asList(RESTRICTED_EVENTS).contains(e.trim().toLowerCase(
+ Locale.ROOT)));
return isRestricted ? new ValidationResult(
SipDelegateManager.MESSAGE_FAILURE_REASON_INVALID_HEADER_FIELDS,
diff --git a/testapps/GbaTestApp/res/values-en-rCA/strings.xml b/testapps/GbaTestApp/res/values-en-rCA/strings.xml
index 6c4a199..0d5c727 100644
--- a/testapps/GbaTestApp/res/values-en-rCA/strings.xml
+++ b/testapps/GbaTestApp/res/values-en-rCA/strings.xml
@@ -3,12 +3,12 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
<string name="label_settings" msgid="8030871890526865502">"Settings"</string>
- <string name="label_carrier" msgid="1470455313066422804">"Operator config"</string>
- <string name="label_service" msgid="2668963955237345578">"Service config"</string>
- <string name="label_test" msgid="8425079572898571918">"Test config"</string>
+ <string name="label_carrier" msgid="1470455313066422804">"Carrier Config"</string>
+ <string name="label_service" msgid="2668963955237345578">"Service Config"</string>
+ <string name="label_test" msgid="8425079572898571918">"Test Config"</string>
<string name="button_name_running" msgid="4557363091224858010">"Running"</string>
<string name="button_name_exit" msgid="8025683733431538975">"Exit"</string>
- <string name="label_test_result" msgid="892984695972956196">"Test result"</string>
+ <string name="label_test_result" msgid="892984695972956196">"Test Result"</string>
<string name="button_name_clear" msgid="436313515327318537">"Reset"</string>
<string name="button_name_done" msgid="6030406534322497491">"Done"</string>
<string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
@@ -16,16 +16,16 @@
<string name="title_activity_test_config" msgid="7585204485536359713">"TestConfigActivity"</string>
<string name="service_package_name" msgid="7204809439090483315">"Package name of GBA service"</string>
<string name="service_release_time" msgid="532937496122890892">"How long to release service after calling"</string>
- <string name="request_app_type" msgid="3975978141673475612">"UICC app type"</string>
+ <string name="request_app_type" msgid="3975978141673475612">"UICC App Type"</string>
<string name="request_naf_url" msgid="4487793541217737042">"Network application function (NAF) URL"</string>
- <string name="request_force_bootstrapping" msgid="206043602616214325">"Force bootstrapping?"</string>
- <string name="request_org" msgid="8416693445448308975">"Organisation code"</string>
- <string name="request_security_protocol" msgid="1444164827561010482">"UA security protocol ID"</string>
- <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS cipher suite ID"</string>
- <string name="response_success" msgid="2469204471244527663">"GBA auth success?"</string>
- <string name="response_fail_reason" msgid="3401426967253202496">"Fail reason ID"</string>
- <string name="response_key" msgid="8839847772051686309">"GBA key (CK + IK)"</string>
- <string name="response_btid" msgid="2550216722679350756">"Bootstrapping transaction identifier (B-TID)"</string>
+ <string name="request_force_bootstrapping" msgid="206043602616214325">"Force Bootstrapping?"</string>
+ <string name="request_org" msgid="8416693445448308975">"Organization Code"</string>
+ <string name="request_security_protocol" msgid="1444164827561010482">"UA Security Protocol ID"</string>
+ <string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Cipher Suite ID"</string>
+ <string name="response_success" msgid="2469204471244527663">"GBA Auth Success?"</string>
+ <string name="response_fail_reason" msgid="3401426967253202496">"Fail Reason ID"</string>
+ <string name="response_key" msgid="8839847772051686309">"GBA Key (CK + IK)"</string>
+ <string name="response_btid" msgid="2550216722679350756">"Bootstrapping Transaction Identifier (B-TID)"</string>
<string name="sample_naf" msgid="255371174145881001">"[email protected]"</string>
<string name="sample_btid" msgid="6967620309576384966">"(B-TID)"</string>
<string name="sample_key" msgid="3337589659405527482">"6629fae49393a05397450978507c4ef1"</string>
diff --git a/testapps/GbaTestApp/res/values-ky/strings.xml b/testapps/GbaTestApp/res/values-ky/strings.xml
index bf5cd30..00383d5 100644
--- a/testapps/GbaTestApp/res/values-ky/strings.xml
+++ b/testapps/GbaTestApp/res/values-ky/strings.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="2922839697457005451">"GbaTestApp"</string>
- <string name="label_settings" msgid="8030871890526865502">"Жөндөөлөр"</string>
+ <string name="label_settings" msgid="8030871890526865502">"Параметрлер"</string>
<string name="label_carrier" msgid="1470455313066422804">"Байланыш операторунун конфигурациясы"</string>
<string name="label_service" msgid="2668963955237345578">"Кызматтын конфигурациясы"</string>
<string name="label_test" msgid="8425079572898571918">"Сыноо конфигурациясы"</string>
diff --git a/testapps/GbaTestApp/res/values-ro/strings.xml b/testapps/GbaTestApp/res/values-ro/strings.xml
index d7f9e7b..dd44364 100644
--- a/testapps/GbaTestApp/res/values-ro/strings.xml
+++ b/testapps/GbaTestApp/res/values-ro/strings.xml
@@ -7,9 +7,9 @@
<string name="label_service" msgid="2668963955237345578">"Configurația serviciului"</string>
<string name="label_test" msgid="8425079572898571918">"Configurație de testare"</string>
<string name="button_name_running" msgid="4557363091224858010">"Rulează"</string>
- <string name="button_name_exit" msgid="8025683733431538975">"Ieșiți"</string>
+ <string name="button_name_exit" msgid="8025683733431538975">"Ieși"</string>
<string name="label_test_result" msgid="892984695972956196">"Rezultatul testului"</string>
- <string name="button_name_clear" msgid="436313515327318537">"Resetați"</string>
+ <string name="button_name_clear" msgid="436313515327318537">"Resetează"</string>
<string name="button_name_done" msgid="6030406534322497491">"Terminat"</string>
<string name="title_activity_carrier_config" msgid="7807803900475957717">"CarrierConfigActivity"</string>
<string name="title_activity_service_config" msgid="5394662739555577279">"ServiceConfigActivity"</string>
@@ -18,7 +18,7 @@
<string name="service_release_time" msgid="532937496122890892">"Durata până la lansarea serviciului după apel"</string>
<string name="request_app_type" msgid="3975978141673475612">"Tipul aplicației UICC"</string>
<string name="request_naf_url" msgid="4487793541217737042">"Adresa URL pentru funcția aplicației pentru rețea (NAF)"</string>
- <string name="request_force_bootstrapping" msgid="206043602616214325">"Forțați inițializarea?"</string>
+ <string name="request_force_bootstrapping" msgid="206043602616214325">"Forțezi inițializarea?"</string>
<string name="request_org" msgid="8416693445448308975">"Cod organizațional"</string>
<string name="request_security_protocol" msgid="1444164827561010482">"ID-ul protocolului de securitate pentru Google Analytics universal"</string>
<string name="request_tls_cipher_suite" msgid="6659854717595308404">"ID-ul suitei TLS Cipher"</string>
diff --git a/testapps/GbaTestApp/res/values-te/strings.xml b/testapps/GbaTestApp/res/values-te/strings.xml
index 72bd28b..28b0489 100644
--- a/testapps/GbaTestApp/res/values-te/strings.xml
+++ b/testapps/GbaTestApp/res/values-te/strings.xml
@@ -7,7 +7,7 @@
<string name="label_service" msgid="2668963955237345578">"సర్వీస్ కాన్ఫిగరేషన్"</string>
<string name="label_test" msgid="8425079572898571918">"పరీక్ష కాన్ఫిగరేషన్"</string>
<string name="button_name_running" msgid="4557363091224858010">"రన్ అవుతోంది"</string>
- <string name="button_name_exit" msgid="8025683733431538975">"నిష్క్రమించు"</string>
+ <string name="button_name_exit" msgid="8025683733431538975">"నిష్క్రమించండి"</string>
<string name="label_test_result" msgid="892984695972956196">"పరీక్ష ఫలితం"</string>
<string name="button_name_clear" msgid="436313515327318537">"రీసెట్ చేయండి"</string>
<string name="button_name_done" msgid="6030406534322497491">"పూర్తయింది"</string>
diff --git a/testapps/TelephonyManagerTestApp/src/com/android/phone/testapps/telephonymanagertestapp/TelephonyManagerTestApp.java b/testapps/TelephonyManagerTestApp/src/com/android/phone/testapps/telephonymanagertestapp/TelephonyManagerTestApp.java
index 760c3bd..815c7e8 100644
--- a/testapps/TelephonyManagerTestApp/src/com/android/phone/testapps/telephonymanagertestapp/TelephonyManagerTestApp.java
+++ b/testapps/TelephonyManagerTestApp/src/com/android/phone/testapps/telephonymanagertestapp/TelephonyManagerTestApp.java
@@ -35,6 +35,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
/**
* Main activity.
@@ -158,7 +159,8 @@
mFilteredMethods.addAll(mMethods);
} else {
for (Method method : mMethods) {
- if (method.getName().toLowerCase().contains(text.toLowerCase())) {
+ if (method.getName().toLowerCase(Locale.ROOT)
+ .contains(text.toLowerCase(Locale.ROOT))) {
mFilteredMethods.add(method);
}
}
diff --git a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/util/NumberUtils.java b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/util/NumberUtils.java
index 14d3b9c..4a47718 100644
--- a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/util/NumberUtils.java
+++ b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/util/NumberUtils.java
@@ -24,6 +24,8 @@
import com.android.i18n.phonenumbers.PhoneNumberUtil;
import com.android.i18n.phonenumbers.Phonenumber;
+import java.util.Locale;
+
public class NumberUtils {
/**
@@ -33,7 +35,7 @@
*/
public static String formatNumber(Context context, String number) {
TelephonyManager manager = context.getSystemService(TelephonyManager.class);
- String simCountryIso = manager.getSimCountryIso().toUpperCase();
+ String simCountryIso = manager.getSimCountryIso().toUpperCase(Locale.ROOT);
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
try {
Phonenumber.PhoneNumber phoneNumber = util.parse(number, simCountryIso);
diff --git a/testapps/TestServerApp/app/src/main/res/values-am/strings.xml b/testapps/TestServerApp/app/src/main/res/values-am/strings.xml
new file mode 100644
index 0000000..8ec544c
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-am/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"ቅንብሮች"</string>
+ <string name="server_running" msgid="2780193626090379172">"አገልጋይ እያሄደ ነው..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"አገልጋይን አቁም"</string>
+ <string name="server_down" msgid="1030249207496490556">"አገልጋይ አይሰራም"</string>
+ <string name="start_server" msgid="3878573341408591975">"አገልጋይን አስጀምር"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"ተሰናክሏል"</item>
+ <item msgid="3193389681837907872">"ነቅቷል"</item>
+ <item msgid="3124590179479393815">"ተኳሃኝ አይደለም"</item>
+ <item msgid="1606753456265236910">"በማቅረብ ላይ"</item>
+ <item msgid="3930807209231347454">"ተካትቷል"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"አልቀረበም"</item>
+ <item msgid="7598231293776486217">"ቀርቧል"</item>
+ <item msgid="3720547957514534185">"አያስፈልግም"</item>
+ <item msgid="1264673582354896949">"በሂደት ላይ"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ar/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ar/strings.xml
new file mode 100644
index 0000000..c901917
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ar/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"الإعدادات"</string>
+ <string name="server_running" msgid="2780193626090379172">"الخادم قيد التشغيل…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"إيقاف الخادم"</string>
+ <string name="server_down" msgid="1030249207496490556">"الخادم معطّل"</string>
+ <string name="start_server" msgid="3878573341408591975">"بدء الخادم"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"غير مفعَّلة"</item>
+ <item msgid="3193389681837907872">"مفعّلة"</item>
+ <item msgid="3124590179479393815">"غير متوافق"</item>
+ <item msgid="1606753456265236910">"جارٍ توفير المتطلبات اللازمة"</item>
+ <item msgid="3930807209231347454">"متاحة"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"لم يتم توفير المتطلبات اللازمة"</item>
+ <item msgid="7598231293776486217">"توفير المتطلبات اللازمة"</item>
+ <item msgid="3720547957514534185">"غير مطلوب"</item>
+ <item msgid="1264673582354896949">"قيد التقدم"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-as/strings.xml b/testapps/TestServerApp/app/src/main/res/values-as/strings.xml
new file mode 100644
index 0000000..46ee915
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-as/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"ছেটিং"</string>
+ <string name="server_running" msgid="2780193626090379172">"ছাৰ্ভাৰটো চলি আছে..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"ছাৰ্ভাৰ বন্ধ কৰক"</string>
+ <string name="server_down" msgid="1030249207496490556">"ছাৰ্ভাৰটো কাৰ্যক্ষম হৈ থকা নাই"</string>
+ <string name="start_server" msgid="3878573341408591975">"ছাৰ্ভাৰ আৰম্ভ কৰক"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"অক্ষম কৰা আছে"</item>
+ <item msgid="3193389681837907872">"সক্ষম কৰা আছে"</item>
+ <item msgid="3124590179479393815">"অমিল"</item>
+ <item msgid="1606753456265236910">"প্ৰ’ভিজনিং"</item>
+ <item msgid="3930807209231347454">"অন্তৰ্ভুক্ত কৰা হ’ল"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"প্ৰ’ভিজন কৰা নাই"</item>
+ <item msgid="7598231293776486217">"প্ৰ’ভিজন কৰা হৈছে"</item>
+ <item msgid="3720547957514534185">"প্ৰয়োজনীয় নহয়"</item>
+ <item msgid="1264673582354896949">"চলি আছে"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-az/strings.xml b/testapps/TestServerApp/app/src/main/res/values-az/strings.xml
new file mode 100644
index 0000000..c7bdb24
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-az/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Ayarlar"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server işləyir..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Serveri dayandırın"</string>
+ <string name="server_down" msgid="1030249207496490556">"Server işləmir"</string>
+ <string name="start_server" msgid="3878573341408591975">"Serveri başladın"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Deaktiv"</item>
+ <item msgid="3193389681837907872">"Aktiv"</item>
+ <item msgid="3124590179479393815">"Uyğun deyil"</item>
+ <item msgid="1606753456265236910">"Təmin edilir"</item>
+ <item msgid="3930807209231347454">"Daxildir"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Təmin edilmir"</item>
+ <item msgid="7598231293776486217">"Təmin edilib"</item>
+ <item msgid="3720547957514534185">"Tələb olunmur"</item>
+ <item msgid="1264673582354896949">"Davam edir"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-b+sr+Latn/strings.xml b/testapps/TestServerApp/app/src/main/res/values-b+sr+Latn/strings.xml
new file mode 100644
index 0000000..62aeff1
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-b+sr+Latn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Podešavanja"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server je pokrenut…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Zaustavi server"</string>
+ <string name="server_down" msgid="1030249207496490556">"Server je pao"</string>
+ <string name="start_server" msgid="3878573341408591975">"Pokreni server"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Onemogućeno"</item>
+ <item msgid="3193389681837907872">"Omogućeno"</item>
+ <item msgid="3124590179479393815">"Nekompatibilno"</item>
+ <item msgid="1606753456265236910">"Dodeljuje se"</item>
+ <item msgid="3930807209231347454">"Uvršteno"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Nije dodeljeno"</item>
+ <item msgid="7598231293776486217">"Dodeljeno"</item>
+ <item msgid="3720547957514534185">"Nije obavezno"</item>
+ <item msgid="1264673582354896949">"U toku"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-be/strings.xml b/testapps/TestServerApp/app/src/main/res/values-be/strings.xml
new file mode 100644
index 0000000..5f1f581
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-be/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Налады"</string>
+ <string name="server_running" msgid="2780193626090379172">"Сервер працуе..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Спыніць сервер"</string>
+ <string name="server_down" msgid="1030249207496490556">"Сервер не працуе"</string>
+ <string name="start_server" msgid="3878573341408591975">"Запусціць сервер"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Адключана"</item>
+ <item msgid="3193389681837907872">"Уключана"</item>
+ <item msgid="3124590179479393815">"Адсутнічае сумяшчальнасць"</item>
+ <item msgid="1606753456265236910">"Ініцыялізацыя"</item>
+ <item msgid="3930807209231347454">"Уключана"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Не ініцыялізавана"</item>
+ <item msgid="7598231293776486217">"Ініцыялізавана"</item>
+ <item msgid="3720547957514534185">"Не патрабуецца"</item>
+ <item msgid="1264673582354896949">"Выконваецца"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-bg/strings.xml b/testapps/TestServerApp/app/src/main/res/values-bg/strings.xml
new file mode 100644
index 0000000..542d0f7
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-bg/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Настройки"</string>
+ <string name="server_running" msgid="2780193626090379172">"Сървърът работи..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Спиране на сървъра"</string>
+ <string name="server_down" msgid="1030249207496490556">"Сървърът не работи"</string>
+ <string name="start_server" msgid="3878573341408591975">"Стартиране на сървъра"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Деактивирано"</item>
+ <item msgid="3193389681837907872">"Активирано"</item>
+ <item msgid="3124590179479393815">"Несъвместимо"</item>
+ <item msgid="1606753456265236910">"Обезпечава се"</item>
+ <item msgid="3930807209231347454">"Включено"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Не е обезпечено"</item>
+ <item msgid="7598231293776486217">"Обезпечено"</item>
+ <item msgid="3720547957514534185">"Не е задължително"</item>
+ <item msgid="1264673582354896949">"В ход"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-bn/strings.xml b/testapps/TestServerApp/app/src/main/res/values-bn/strings.xml
new file mode 100644
index 0000000..7244308
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-bn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"সেটিংস"</string>
+ <string name="server_running" msgid="2780193626090379172">"সার্ভার রান করছে..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"সার্ভার বন্ধ করুন"</string>
+ <string name="server_down" msgid="1030249207496490556">"সার্ভার কাজ করছে না"</string>
+ <string name="start_server" msgid="3878573341408591975">"সার্ভার চালু করুন"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"বন্ধ আছে"</item>
+ <item msgid="3193389681837907872">"চালু আছে"</item>
+ <item msgid="3124590179479393815">"মানানসই নয়"</item>
+ <item msgid="1606753456265236910">"প্রস্তুতি চলছে"</item>
+ <item msgid="3930807209231347454">"অন্তর্ভুক্ত আছে"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"প্রস্তুত নেই"</item>
+ <item msgid="7598231293776486217">"প্রস্তুত আছে"</item>
+ <item msgid="3720547957514534185">"প্রয়োজন নেই"</item>
+ <item msgid="1264673582354896949">"কাজ চলছে"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-cs/strings.xml b/testapps/TestServerApp/app/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000..c8dfd8d
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-cs/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Nastavení"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server běží…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Zastavit server"</string>
+ <string name="server_down" msgid="1030249207496490556">"Server je nedostupný"</string>
+ <string name="start_server" msgid="3878573341408591975">"Spustit server"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Vypnuto"</item>
+ <item msgid="3193389681837907872">"Zapnuto"</item>
+ <item msgid="3124590179479393815">"Nekompatibilní"</item>
+ <item msgid="1606753456265236910">"Zajišťování"</item>
+ <item msgid="3930807209231347454">"Zahrnuto"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Nezajištěno"</item>
+ <item msgid="7598231293776486217">"Zajištěno"</item>
+ <item msgid="3720547957514534185">"Nepovinné"</item>
+ <item msgid="1264673582354896949">"Probíhá"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-da/strings.xml b/testapps/TestServerApp/app/src/main/res/values-da/strings.xml
new file mode 100644
index 0000000..1d8e029
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-da/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"Testserverapp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Indstillinger"</string>
+ <string name="server_running" msgid="2780193626090379172">"Serveren kører…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Stop server"</string>
+ <string name="server_down" msgid="1030249207496490556">"Serveren er nede"</string>
+ <string name="start_server" msgid="3878573341408591975">"Start server"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Deaktiveret"</item>
+ <item msgid="3193389681837907872">"Aktiveret"</item>
+ <item msgid="3124590179479393815">"Ikke kompatibel"</item>
+ <item msgid="1606753456265236910">"Provisionerer"</item>
+ <item msgid="3930807209231347454">"Inkluderet"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Ikke provisioneret"</item>
+ <item msgid="7598231293776486217">"Provisioneret"</item>
+ <item msgid="3720547957514534185">"Ikke påkrævet"</item>
+ <item msgid="1264673582354896949">"I gang"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-de/strings.xml b/testapps/TestServerApp/app/src/main/res/values-de/strings.xml
new file mode 100644
index 0000000..4adc332
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-de/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Einstellungen"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server ist in Betrieb…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Server anhalten"</string>
+ <string name="server_down" msgid="1030249207496490556">"Server ist ausgefallen"</string>
+ <string name="start_server" msgid="3878573341408591975">"Server starten"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Deaktiviert"</item>
+ <item msgid="3193389681837907872">"Aktiviert"</item>
+ <item msgid="3124590179479393815">"Nicht kompatibel"</item>
+ <item msgid="1606753456265236910">"Nutzerverwaltung"</item>
+ <item msgid="3930807209231347454">"Enthalten"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Noch nicht von einem Nutzer verwaltet"</item>
+ <item msgid="7598231293776486217">"Von einem Nutzer verwaltet"</item>
+ <item msgid="3720547957514534185">"Nicht erforderlich"</item>
+ <item msgid="1264673582354896949">"In Bearbeitung"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-el/strings.xml b/testapps/TestServerApp/app/src/main/res/values-el/strings.xml
new file mode 100644
index 0000000..540500d
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-el/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Ρυθμίσεις"</string>
+ <string name="server_running" msgid="2780193626090379172">"Ο διακομιστής λειτουργεί…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Διακοπή διακομιστή"</string>
+ <string name="server_down" msgid="1030249207496490556">"Ο διακομιστής είναι εκτός λειτουργίας"</string>
+ <string name="start_server" msgid="3878573341408591975">"Έναρξη διακομιστή"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Ανενεργό"</item>
+ <item msgid="3193389681837907872">"Ενεργό"</item>
+ <item msgid="3124590179479393815">"Μη συμβατό"</item>
+ <item msgid="1606753456265236910">"Παροχή"</item>
+ <item msgid="3930807209231347454">"Περιλαμβάνεται"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Χωρίς παροχή"</item>
+ <item msgid="7598231293776486217">"Παρέχεται"</item>
+ <item msgid="3720547957514534185">"Δεν απαιτείται"</item>
+ <item msgid="1264673582354896949">"Σε εξέλιξη"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-es-rUS/strings.xml b/testapps/TestServerApp/app/src/main/res/values-es-rUS/strings.xml
new file mode 100644
index 0000000..50c9ff2
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-es-rUS/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Configuración"</string>
+ <string name="server_running" msgid="2780193626090379172">"El servidor se está ejecutando…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Detener el servidor"</string>
+ <string name="server_down" msgid="1030249207496490556">"El servidor se encuentra inactivo"</string>
+ <string name="start_server" msgid="3878573341408591975">"Iniciar el servidor"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Inhabilitado"</item>
+ <item msgid="3193389681837907872">"Habilitado"</item>
+ <item msgid="3124590179479393815">"Incompatible"</item>
+ <item msgid="1606753456265236910">"Aprovisionando"</item>
+ <item msgid="3930807209231347454">"Incluido"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"No aprovisionado"</item>
+ <item msgid="7598231293776486217">"Aprovisionado"</item>
+ <item msgid="3720547957514534185">"No se necesita"</item>
+ <item msgid="1264673582354896949">"En curso"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-es/strings.xml b/testapps/TestServerApp/app/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000..002fca7
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-es/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Ajustes"</string>
+ <string name="server_running" msgid="2780193626090379172">"El servidor se está ejecutando..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Detener servidor"</string>
+ <string name="server_down" msgid="1030249207496490556">"El servidor no está operativo"</string>
+ <string name="start_server" msgid="3878573341408591975">"Iniciar servidor"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Inhabilitado"</item>
+ <item msgid="3193389681837907872">"Habilitado"</item>
+ <item msgid="3124590179479393815">"No compatible"</item>
+ <item msgid="1606753456265236910">"En aprovisionamiento"</item>
+ <item msgid="3930807209231347454">"Incluido"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"No aprovisionado"</item>
+ <item msgid="7598231293776486217">"Aprovisionado"</item>
+ <item msgid="3720547957514534185">"No se requiere"</item>
+ <item msgid="1264673582354896949">"En curso"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-et/strings.xml b/testapps/TestServerApp/app/src/main/res/values-et/strings.xml
new file mode 100644
index 0000000..49c3209
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-et/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Seaded"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server töötab ..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Peata server"</string>
+ <string name="server_down" msgid="1030249207496490556">"Serveris on katkestus"</string>
+ <string name="start_server" msgid="3878573341408591975">"Käivita server"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Keelatud"</item>
+ <item msgid="3193389681837907872">"Lubatud"</item>
+ <item msgid="3124590179479393815">"Ühildumatu"</item>
+ <item msgid="1606753456265236910">"Ettevalmistamine"</item>
+ <item msgid="3930807209231347454">"Kaasas"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Ettevalmistamata"</item>
+ <item msgid="7598231293776486217">"Ettevalmistatud"</item>
+ <item msgid="3720547957514534185">"Pole nõutav"</item>
+ <item msgid="1264673582354896949">"Töötluses"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-eu/strings.xml b/testapps/TestServerApp/app/src/main/res/values-eu/strings.xml
new file mode 100644
index 0000000..70f5423
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-eu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Ezarpenak"</string>
+ <string name="server_running" msgid="2780193626090379172">"Zerbitzaria abian da…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Gelditu zerbitzaria"</string>
+ <string name="server_down" msgid="1030249207496490556">"Zerbitzaria ez dabil"</string>
+ <string name="start_server" msgid="3878573341408591975">"Abiarazi zerbitzaria"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Desgaituta"</item>
+ <item msgid="3193389681837907872">"Gaituta"</item>
+ <item msgid="3124590179479393815">"Bateraezina"</item>
+ <item msgid="1606753456265236910">"Hornitzen"</item>
+ <item msgid="3930807209231347454">"Barne"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Hornitu gabe"</item>
+ <item msgid="7598231293776486217">"Hornituta"</item>
+ <item msgid="3720547957514534185">"Ez da beharrezkoa"</item>
+ <item msgid="1264673582354896949">"Abian"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-fi/strings.xml b/testapps/TestServerApp/app/src/main/res/values-fi/strings.xml
new file mode 100644
index 0000000..9117e0c
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-fi/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Asetukset"</string>
+ <string name="server_running" msgid="2780193626090379172">"Palvelin on käytössä..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Keskeytä palvelin"</string>
+ <string name="server_down" msgid="1030249207496490556">"Palvelin on poissa käytöstä"</string>
+ <string name="start_server" msgid="3878573341408591975">"Käynnistä palvelin"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Ei käytössä"</item>
+ <item msgid="3193389681837907872">"Käytössä"</item>
+ <item msgid="3124590179479393815">"Yhteensopimaton"</item>
+ <item msgid="1606753456265236910">"Käsitellään"</item>
+ <item msgid="3930807209231347454">"Sisältyy"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Ei käsitelty"</item>
+ <item msgid="7598231293776486217">"Käsitelty"</item>
+ <item msgid="3720547957514534185">"Valinnainen"</item>
+ <item msgid="1264673582354896949">"Käynnissä"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-fr-rCA/strings.xml b/testapps/TestServerApp/app/src/main/res/values-fr-rCA/strings.xml
new file mode 100644
index 0000000..97fd06a
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-fr-rCA/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Paramètres"</string>
+ <string name="server_running" msgid="2780193626090379172">"Le serveur est en cours d\'exécution…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Arrêter le serveur"</string>
+ <string name="server_down" msgid="1030249207496490556">"Le serveur est en panne"</string>
+ <string name="start_server" msgid="3878573341408591975">"Démarrer le serveur"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Désactivé"</item>
+ <item msgid="3193389681837907872">"Activé"</item>
+ <item msgid="3124590179479393815">"Incompatible"</item>
+ <item msgid="1606753456265236910">"Approvisionnement en cours…"</item>
+ <item msgid="3930807209231347454">"Inclus"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Non approvisionné"</item>
+ <item msgid="7598231293776486217">"Approvisionné"</item>
+ <item msgid="3720547957514534185">"Facultatif"</item>
+ <item msgid="1264673582354896949">"En cours de traitement"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-fr/strings.xml b/testapps/TestServerApp/app/src/main/res/values-fr/strings.xml
new file mode 100644
index 0000000..be70c79
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-fr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Paramètres"</string>
+ <string name="server_running" msgid="2780193626090379172">"Serveur en cours d\'exécution…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Arrêter le serveur"</string>
+ <string name="server_down" msgid="1030249207496490556">"Serveur en panne"</string>
+ <string name="start_server" msgid="3878573341408591975">"Démarrer le serveur"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Désactivé"</item>
+ <item msgid="3193389681837907872">"Activé"</item>
+ <item msgid="3124590179479393815">"Incompatible"</item>
+ <item msgid="1606753456265236910">"Provisionnement…"</item>
+ <item msgid="3930807209231347454">"Inclus"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Non provisionné"</item>
+ <item msgid="7598231293776486217">"Provisionné"</item>
+ <item msgid="3720547957514534185">"Facultatif"</item>
+ <item msgid="1264673582354896949">"En cours"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-gl/strings.xml b/testapps/TestServerApp/app/src/main/res/values-gl/strings.xml
new file mode 100644
index 0000000..9de1ceb
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-gl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Configuración"</string>
+ <string name="server_running" msgid="2780193626090379172">"O servidor está executándose…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Deter servidor"</string>
+ <string name="server_down" msgid="1030249207496490556">"O servidor non está operativo"</string>
+ <string name="start_server" msgid="3878573341408591975">"Iniciar servidor"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Desactivado"</item>
+ <item msgid="3193389681837907872">"Activado"</item>
+ <item msgid="3124590179479393815">"Incompatible"</item>
+ <item msgid="1606753456265236910">"En aprovisionamento"</item>
+ <item msgid="3930807209231347454">"Incluído"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Non aprovisionado"</item>
+ <item msgid="7598231293776486217">"Aprovisionado"</item>
+ <item msgid="3720547957514534185">"Non obrigatorio"</item>
+ <item msgid="1264673582354896949">"En curso"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-gu/strings.xml b/testapps/TestServerApp/app/src/main/res/values-gu/strings.xml
new file mode 100644
index 0000000..d2fc1d0
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-gu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"સેટિંગ"</string>
+ <string name="server_running" msgid="2780193626090379172">"સર્વર ચાલુ છે..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"સર્વર રોકો"</string>
+ <string name="server_down" msgid="1030249207496490556">"સર્વર ડાઉન છે"</string>
+ <string name="start_server" msgid="3878573341408591975">"સર્વર શરૂ કરો"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"બંધ છે"</item>
+ <item msgid="3193389681837907872">"ચાલુ છે"</item>
+ <item msgid="3124590179479393815">"અસંગત છે"</item>
+ <item msgid="1606753456265236910">"જોગવાઈ કરી રહ્યું છે"</item>
+ <item msgid="3930807209231347454">"શામેલ છે"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"કોઈ જોગવાઈ કરેલી નથી"</item>
+ <item msgid="7598231293776486217">"જોગવાઈ કરેલી છે"</item>
+ <item msgid="3720547957514534185">"આવશ્યક નથી"</item>
+ <item msgid="1264673582354896949">"પ્રક્રિયા ચાલુ છે"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-hi/strings.xml b/testapps/TestServerApp/app/src/main/res/values-hi/strings.xml
new file mode 100644
index 0000000..d5be924
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-hi/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"सेटिंग"</string>
+ <string name="server_running" msgid="2780193626090379172">"सर्वर काम कर रहा है..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"सर्वर बंद करें"</string>
+ <string name="server_down" msgid="1030249207496490556">"सर्वर काम नहीं कर रहा है"</string>
+ <string name="start_server" msgid="3878573341408591975">"सर्वर चालू करें"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"बंद है"</item>
+ <item msgid="3193389681837907872">"चालू है"</item>
+ <item msgid="3124590179479393815">"काम नहीं करता"</item>
+ <item msgid="1606753456265236910">"प्रावधान"</item>
+ <item msgid="3930807209231347454">"पहले से मौजूद है"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"प्रावधान नहीं किया गया है"</item>
+ <item msgid="7598231293776486217">"प्रावधान किया गया है"</item>
+ <item msgid="3720547957514534185">"ज़रूरी नहीं है"</item>
+ <item msgid="1264673582354896949">"प्रावधान किया जा रहा है"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-hr/strings.xml b/testapps/TestServerApp/app/src/main/res/values-hr/strings.xml
new file mode 100644
index 0000000..492f2cc
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-hr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Postavke"</string>
+ <string name="server_running" msgid="2780193626090379172">"Poslužitelj je aktivan..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Zaustavljanje poslužitelja"</string>
+ <string name="server_down" msgid="1030249207496490556">"Poslužitelj nije aktivan"</string>
+ <string name="start_server" msgid="3878573341408591975">"Pokretanje poslužitelja"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Onemogućeno"</item>
+ <item msgid="3193389681837907872">"Omogućeno"</item>
+ <item msgid="3124590179479393815">"Nije kompatibilno"</item>
+ <item msgid="1606753456265236910">"Omogućivanje"</item>
+ <item msgid="3930807209231347454">"Uključeno"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Nije omogućeno"</item>
+ <item msgid="7598231293776486217">"Omogućeno"</item>
+ <item msgid="3720547957514534185">"Nije obavezno"</item>
+ <item msgid="1264673582354896949">"U tijeku"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-hu/strings.xml b/testapps/TestServerApp/app/src/main/res/values-hu/strings.xml
new file mode 100644
index 0000000..286fae3
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-hu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Beállítások"</string>
+ <string name="server_running" msgid="2780193626090379172">"A szerver fut..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Szerver leállítása"</string>
+ <string name="server_down" msgid="1030249207496490556">"A szerver leállt"</string>
+ <string name="start_server" msgid="3878573341408591975">"Szerver indítása"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Kikapcsolva"</item>
+ <item msgid="3193389681837907872">"Engedélyezve"</item>
+ <item msgid="3124590179479393815">"Nem kompatibilis"</item>
+ <item msgid="1606753456265236910">"Kiépítés"</item>
+ <item msgid="3930807209231347454">"Tartalmazza"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Nincs kiépítve"</item>
+ <item msgid="7598231293776486217">"Kiépítve"</item>
+ <item msgid="3720547957514534185">"Nem kötelező"</item>
+ <item msgid="1264673582354896949">"Folyamatban"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-hy/strings.xml b/testapps/TestServerApp/app/src/main/res/values-hy/strings.xml
new file mode 100644
index 0000000..03a382b
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-hy/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Կարգավորումներ"</string>
+ <string name="server_running" msgid="2780193626090379172">"Սերվերն աշխատում է..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Կանգնեցնել սերվերը"</string>
+ <string name="server_down" msgid="1030249207496490556">"Սերվերն անջատված է"</string>
+ <string name="start_server" msgid="3878573341408591975">"Գործարկել սերվերը"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Անջատված է"</item>
+ <item msgid="3193389681837907872">"Միացված է"</item>
+ <item msgid="3124590179479393815">"Անհամատեղելիություն"</item>
+ <item msgid="1606753456265236910">"Նախապատրաստում"</item>
+ <item msgid="3930807209231347454">"Ներառված է"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Նախապատրաստված չէ"</item>
+ <item msgid="7598231293776486217">"Նախապատրաստված է"</item>
+ <item msgid="3720547957514534185">"Ոչ պարտադիր"</item>
+ <item msgid="1264673582354896949">"Ընթացքում է"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-in/strings.xml b/testapps/TestServerApp/app/src/main/res/values-in/strings.xml
new file mode 100644
index 0000000..b918582
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-in/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Setelan"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server sedang berjalan..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Hentikan Server"</string>
+ <string name="server_down" msgid="1030249207496490556">"Server tidak berfungsi"</string>
+ <string name="start_server" msgid="3878573341408591975">"Mulai Server"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Nonaktif"</item>
+ <item msgid="3193389681837907872">"Aktif"</item>
+ <item msgid="3124590179479393815">"Tidak kompatibel"</item>
+ <item msgid="1606753456265236910">"Penyediaan"</item>
+ <item msgid="3930807209231347454">"Disertakan"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Tidak Disediakan"</item>
+ <item msgid="7598231293776486217">"Disediakan"</item>
+ <item msgid="3720547957514534185">"Tidak Wajib"</item>
+ <item msgid="1264673582354896949">"Dalam Proses"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-is/strings.xml b/testapps/TestServerApp/app/src/main/res/values-is/strings.xml
new file mode 100644
index 0000000..610755a
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-is/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Stillingar"</string>
+ <string name="server_running" msgid="2780193626090379172">"Þjónn er í gangi..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Stöðva þjón"</string>
+ <string name="server_down" msgid="1030249207496490556">"Þjónn liggur niðri"</string>
+ <string name="start_server" msgid="3878573341408591975">"Ræsa þjón"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Slökkt"</item>
+ <item msgid="3193389681837907872">"Kveikt"</item>
+ <item msgid="3124590179479393815">"Ósamhæft"</item>
+ <item msgid="1606753456265236910">"Úthlutun"</item>
+ <item msgid="3930807209231347454">"Innifalið"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Ekki úthlutað"</item>
+ <item msgid="7598231293776486217">"Úthlutað"</item>
+ <item msgid="3720547957514534185">"Ekki áskilið"</item>
+ <item msgid="1264673582354896949">"Í vinnslu"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-it/strings.xml b/testapps/TestServerApp/app/src/main/res/values-it/strings.xml
new file mode 100644
index 0000000..6f4f3b1
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-it/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Settings"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server is running..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Stop Server"</string>
+ <string name="server_down" msgid="1030249207496490556">"Server is down"</string>
+ <string name="start_server" msgid="3878573341408591975">"Start Server"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Disabled"</item>
+ <item msgid="3193389681837907872">"Enabled"</item>
+ <item msgid="3124590179479393815">"Incompatible"</item>
+ <item msgid="1606753456265236910">"Provisioning"</item>
+ <item msgid="3930807209231347454">"Included"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Not Provisioned"</item>
+ <item msgid="7598231293776486217">"Provisioned"</item>
+ <item msgid="3720547957514534185">"Not Required"</item>
+ <item msgid="1264673582354896949">"In Progress"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ja/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ja/strings.xml
new file mode 100644
index 0000000..1b962e4
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ja/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"設定"</string>
+ <string name="server_running" msgid="2780193626090379172">"サーバーが実行中です..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"サーバーを停止"</string>
+ <string name="server_down" msgid="1030249207496490556">"サーバーがダウンしています"</string>
+ <string name="start_server" msgid="3878573341408591975">"サーバーを起動"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"無効"</item>
+ <item msgid="3193389681837907872">"有効"</item>
+ <item msgid="3124590179479393815">"非対応"</item>
+ <item msgid="1606753456265236910">"プロビジョニング"</item>
+ <item msgid="3930807209231347454">"必須"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"未プロビジョニング"</item>
+ <item msgid="7598231293776486217">"プロビジョニング済み"</item>
+ <item msgid="3720547957514534185">"任意"</item>
+ <item msgid="1264673582354896949">"処理中"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-kk/strings.xml b/testapps/TestServerApp/app/src/main/res/values-kk/strings.xml
new file mode 100644
index 0000000..8a93c31
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-kk/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Параметрлер"</string>
+ <string name="server_running" msgid="2780193626090379172">"Сервер істеп тұр…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Серверді тоқтату"</string>
+ <string name="server_down" msgid="1030249207496490556">"Сервер істемей тұр"</string>
+ <string name="start_server" msgid="3878573341408591975">"Серверді іске қосу"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Өшірулі"</item>
+ <item msgid="3193389681837907872">"Қосулы"</item>
+ <item msgid="3124590179479393815">"Үйлеспейді"</item>
+ <item msgid="1606753456265236910">"Дайындау"</item>
+ <item msgid="3930807209231347454">"Қамтылды"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Дайындалмады"</item>
+ <item msgid="7598231293776486217">"Дайындалды"</item>
+ <item msgid="3720547957514534185">"Міндетті емес"</item>
+ <item msgid="1264673582354896949">"Орындалып жатыр"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-kn/strings.xml b/testapps/TestServerApp/app/src/main/res/values-kn/strings.xml
new file mode 100644
index 0000000..227d44b
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-kn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string>
+ <string name="server_running" msgid="2780193626090379172">"ಸರ್ವರ್ ರನ್ ಆಗುತ್ತಿದೆ..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"ಸರ್ವರ್ ನಿಲ್ಲಿಸಿ"</string>
+ <string name="server_down" msgid="1030249207496490556">"ಸರ್ವರ್ ಡೌನ್ ಆಗಿದೆ"</string>
+ <string name="start_server" msgid="3878573341408591975">"ಸರ್ವರ್ ಪ್ರಾರಂಭಿಸಿ"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
+ <item msgid="3193389681837907872">"ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</item>
+ <item msgid="3124590179479393815">"ಹೊಂದಾಣಿಕೆಯಾಗುವುದಿಲ್ಲ"</item>
+ <item msgid="1606753456265236910">"ಒದಗಿಸಲಾಗುತ್ತಿದೆ"</item>
+ <item msgid="3930807209231347454">"ಒಳಗೊಂಡಿದೆ"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"ಒದಗಿಸಲಾಗಿಲ್ಲ"</item>
+ <item msgid="7598231293776486217">"ಒದಗಿಸಲಾಗಿದೆ"</item>
+ <item msgid="3720547957514534185">"ಅಗತ್ಯವಿಲ್ಲ"</item>
+ <item msgid="1264673582354896949">"ಪ್ರಗತಿಯಲ್ಲಿದೆ"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ko/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ko/strings.xml
new file mode 100644
index 0000000..ca9b15a
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ko/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"설정"</string>
+ <string name="server_running" msgid="2780193626090379172">"서버 실행 중…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"서버를 중지하시겠습니까?"</string>
+ <string name="server_down" msgid="1030249207496490556">"서버가 다운됨"</string>
+ <string name="start_server" msgid="3878573341408591975">"서버를 시작하시겠습니까?"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"사용 안함"</item>
+ <item msgid="3193389681837907872">"사용 설정됨"</item>
+ <item msgid="3124590179479393815">"호환되지 않음"</item>
+ <item msgid="1606753456265236910">"프로비저닝"</item>
+ <item msgid="3930807209231347454">"포함됨"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"프로비저닝되지 않음"</item>
+ <item msgid="7598231293776486217">"프로비저닝됨"</item>
+ <item msgid="3720547957514534185">"필요 없음"</item>
+ <item msgid="1264673582354896949">"진행 중"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ky/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ky/strings.xml
new file mode 100644
index 0000000..3d6c36f
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ky/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Параметрлер"</string>
+ <string name="server_running" msgid="2780193626090379172">"Сервер иштеп жатат..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Серверди токтотуу"</string>
+ <string name="server_down" msgid="1030249207496490556">"Сервер иштебей калды"</string>
+ <string name="start_server" msgid="3878573341408591975">"Серверди иштетип баштоо"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Өчүрүлдү"</item>
+ <item msgid="3193389681837907872">"Иштетилди"</item>
+ <item msgid="3124590179479393815">"Ылайык келбейт"</item>
+ <item msgid="1606753456265236910">"Камсыз кылууда"</item>
+ <item msgid="3930807209231347454">"Камтылган"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Камсыздалган эмес"</item>
+ <item msgid="7598231293776486217">"Камсыздалган"</item>
+ <item msgid="3720547957514534185">"Талап кылынбайт"</item>
+ <item msgid="1264673582354896949">"Аткарылууда"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-lt/strings.xml b/testapps/TestServerApp/app/src/main/res/values-lt/strings.xml
new file mode 100644
index 0000000..a7e79e9
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-lt/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Nustatymai"</string>
+ <string name="server_running" msgid="2780193626090379172">"Serveris veikia..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Sustabdyti serverį"</string>
+ <string name="server_down" msgid="1030249207496490556">"Serveris neveikia"</string>
+ <string name="start_server" msgid="3878573341408591975">"Paleisti serverį"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Išjungta"</item>
+ <item msgid="3193389681837907872">"Įgalinta"</item>
+ <item msgid="3124590179479393815">"Nesuderinama"</item>
+ <item msgid="1606753456265236910">"Parengiama"</item>
+ <item msgid="3930807209231347454">"Įtraukta"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Neparengta"</item>
+ <item msgid="7598231293776486217">"Parengta"</item>
+ <item msgid="3720547957514534185">"Nebūtina"</item>
+ <item msgid="1264673582354896949">"Vykdoma"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-lv/strings.xml b/testapps/TestServerApp/app/src/main/res/values-lv/strings.xml
new file mode 100644
index 0000000..a7bff51
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-lv/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"ServeraLietotneTestēšanai"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Iestatījumi"</string>
+ <string name="server_running" msgid="2780193626090379172">"Serveris darbojas…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Apturēt servera darbību"</string>
+ <string name="server_down" msgid="1030249207496490556">"Serveris nedarbojas"</string>
+ <string name="start_server" msgid="3878573341408591975">"Palaist serveri"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Atspējots"</item>
+ <item msgid="3193389681837907872">"Iespējots"</item>
+ <item msgid="3124590179479393815">"Nav saderīgs"</item>
+ <item msgid="1606753456265236910">"Notiek nodrošināšana"</item>
+ <item msgid="3930807209231347454">"Iekļauts"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Nav nodrošināts"</item>
+ <item msgid="7598231293776486217">"Nodrošināts"</item>
+ <item msgid="3720547957514534185">"Nav nepieciešams"</item>
+ <item msgid="1264673582354896949">"Notiek apstrāde"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-mk/strings.xml b/testapps/TestServerApp/app/src/main/res/values-mk/strings.xml
new file mode 100644
index 0000000..44a255c
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-mk/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Поставки"</string>
+ <string name="server_running" msgid="2780193626090379172">"Серверот се извршува…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Сопри го серверот"</string>
+ <string name="server_down" msgid="1030249207496490556">"Серверот е паднат"</string>
+ <string name="start_server" msgid="3878573341408591975">"Стартувај го серверот"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Оневозможено"</item>
+ <item msgid="3193389681837907872">"Овозможено"</item>
+ <item msgid="3124590179479393815">"Некомпатибилно"</item>
+ <item msgid="1606753456265236910">"Се обезбедува"</item>
+ <item msgid="3930807209231347454">"Опфатено"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Необезбедено"</item>
+ <item msgid="7598231293776486217">"Обезбедено"</item>
+ <item msgid="3720547957514534185">"Незадолжително"</item>
+ <item msgid="1264673582354896949">"Во тек"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ml/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ml/strings.xml
new file mode 100644
index 0000000..32b305a
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ml/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"ക്രമീകരണം"</string>
+ <string name="server_running" msgid="2780193626090379172">"സെർവർ പ്രവർത്തിക്കുന്നുണ്ട്..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"സെർവർ നിർത്തുക"</string>
+ <string name="server_down" msgid="1030249207496490556">"സെർവർ ലഭ്യമല്ല"</string>
+ <string name="start_server" msgid="3878573341408591975">"സെർവർ ആരംഭിക്കുക"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"പ്രവർത്തനരഹിതമാക്കി"</item>
+ <item msgid="3193389681837907872">"പ്രവർത്തനക്ഷമമാക്കി"</item>
+ <item msgid="3124590179479393815">"അനുയോജ്യമല്ല"</item>
+ <item msgid="1606753456265236910">"പ്രൊവിഷനിംഗ്"</item>
+ <item msgid="3930807209231347454">"ഉൾപ്പെടുത്തി"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"പ്രൊവിഷൻ ചെയ്തിട്ടില്ല"</item>
+ <item msgid="7598231293776486217">"പ്രൊവിഷൻ ചെയ്തു"</item>
+ <item msgid="3720547957514534185">"ആവശ്യമില്ല"</item>
+ <item msgid="1264673582354896949">"പുരോഗമിക്കുന്നു"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-mn/strings.xml b/testapps/TestServerApp/app/src/main/res/values-mn/strings.xml
new file mode 100644
index 0000000..6c131e2
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-mn/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Тохиргоо"</string>
+ <string name="server_running" msgid="2780193626090379172">"Сервер ажиллаж байна..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Серверийг зогсоох"</string>
+ <string name="server_down" msgid="1030249207496490556">"Сервер унтарсан байна"</string>
+ <string name="start_server" msgid="3878573341408591975">"Серверийг эхлүүлэх"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Идэвхгүй болгосон"</item>
+ <item msgid="3193389681837907872">"Идэвхжүүлсэн"</item>
+ <item msgid="3124590179479393815">"Тохирохгүй"</item>
+ <item msgid="1606753456265236910">"Бэлтгэж байна"</item>
+ <item msgid="3930807209231347454">"Багтсан"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Бэлтгээгүй"</item>
+ <item msgid="7598231293776486217">"Бэлтгэсэн"</item>
+ <item msgid="3720547957514534185">"Заавал биш"</item>
+ <item msgid="1264673582354896949">"Үргэлжилж байна"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-mr/strings.xml b/testapps/TestServerApp/app/src/main/res/values-mr/strings.xml
new file mode 100644
index 0000000..74a0f56
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-mr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"सेटिंग्ज"</string>
+ <string name="server_running" msgid="2780193626090379172">"सर्व्हर रन होत आहे..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"सर्व्हर थांबवा"</string>
+ <string name="server_down" msgid="1030249207496490556">"सर्व्हर बंद आहे"</string>
+ <string name="start_server" msgid="3878573341408591975">"सर्व्हर सुरू करा"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"बंद आहे"</item>
+ <item msgid="3193389681837907872">"सुरू आहे"</item>
+ <item msgid="3124590179479393815">"कंपॅटिबल नाही"</item>
+ <item msgid="1606753456265236910">"तरतूद"</item>
+ <item msgid="3930807209231347454">"समावेश आहे"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"तरतूद केलेली नाही"</item>
+ <item msgid="7598231293776486217">"तरतूद केली आहे"</item>
+ <item msgid="3720547957514534185">"आवश्यक नाही"</item>
+ <item msgid="1264673582354896949">"प्रगतीपथावर आहे"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-my/strings.xml b/testapps/TestServerApp/app/src/main/res/values-my/strings.xml
new file mode 100644
index 0000000..9a0dcdf
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-my/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"ဆက်တင်များ"</string>
+ <string name="server_running" msgid="2780193626090379172">"ဆာဗာ လုပ်ဆောင်နေသည်…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"ဆာဗာ ရပ်ရန်"</string>
+ <string name="server_down" msgid="1030249207496490556">"ဆာဗာကျနေသည်"</string>
+ <string name="start_server" msgid="3878573341408591975">"ဆာဗာ စတင်ရန်"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"ပိတ်ထားသည်"</item>
+ <item msgid="3193389681837907872">"ဖွင့်ထားသည်"</item>
+ <item msgid="3124590179479393815">"တွဲဖက်မသုံးနိုင်ပါ"</item>
+ <item msgid="1606753456265236910">"ပံ့ပိုးပေးခြင်း"</item>
+ <item msgid="3930807209231347454">"ပါဝင်သည်"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"ပံ့ပိုးမထားပါ"</item>
+ <item msgid="7598231293776486217">"ပံ့ပိုးပေးထားသည်"</item>
+ <item msgid="3720547957514534185">"မလိုအပ်ပါ"</item>
+ <item msgid="1264673582354896949">"ဆောင်ရွက်နေဆဲ"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-nb/strings.xml b/testapps/TestServerApp/app/src/main/res/values-nb/strings.xml
new file mode 100644
index 0000000..d28a197
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-nb/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Innstillinger"</string>
+ <string name="server_running" msgid="2780193626090379172">"Tjeneren kjører …"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Stopp tjeneren"</string>
+ <string name="server_down" msgid="1030249207496490556">"Tjeneren er nede"</string>
+ <string name="start_server" msgid="3878573341408591975">"Start tjeneren"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Slått av"</item>
+ <item msgid="3193389681837907872">"Slått på"</item>
+ <item msgid="3124590179479393815">"Inkompatibel"</item>
+ <item msgid="1606753456265236910">"Klargjøring"</item>
+ <item msgid="3930807209231347454">"Inkludert"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Ikke klargjort"</item>
+ <item msgid="7598231293776486217">"Klargjort"</item>
+ <item msgid="3720547957514534185">"Ikke obligatorisk"</item>
+ <item msgid="1264673582354896949">"Under behandling"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ne/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ne/strings.xml
new file mode 100644
index 0000000..fe1f119
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ne/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"सेटिङ"</string>
+ <string name="server_running" msgid="2780193626090379172">"सर्भर चल्दै छ..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"सर्भर बन्द गर्नुहोस्"</string>
+ <string name="server_down" msgid="1030249207496490556">"सर्भर डाउन छ"</string>
+ <string name="start_server" msgid="3878573341408591975">"सर्भर प्रयोग गर्न थाल्नुहोस्"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"अफ गरिएको छ"</item>
+ <item msgid="3193389681837907872">"अन गरिएको छ"</item>
+ <item msgid="3124590179479393815">"नमिल्दो"</item>
+ <item msgid="1606753456265236910">"प्रावधान मिलाइँदै छ"</item>
+ <item msgid="3930807209231347454">"समावेश गरिएको छ"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"प्रावधान मिलाइएको छैन"</item>
+ <item msgid="7598231293776486217">"प्रावधान मिलाइएको छ"</item>
+ <item msgid="3720547957514534185">"आवश्यक छैन"</item>
+ <item msgid="1264673582354896949">"प्रक्रियामा छ"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-nl/strings.xml b/testapps/TestServerApp/app/src/main/res/values-nl/strings.xml
new file mode 100644
index 0000000..847dfca
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-nl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Instellingen"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server actief..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Server stoppen"</string>
+ <string name="server_down" msgid="1030249207496490556">"Server offline"</string>
+ <string name="start_server" msgid="3878573341408591975">"Server starten"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Uit"</item>
+ <item msgid="3193389681837907872">"Aan"</item>
+ <item msgid="3124590179479393815">"Niet geschikt"</item>
+ <item msgid="1606753456265236910">"Registratie"</item>
+ <item msgid="3930807209231347454">"Opgenomen"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Niet geregistreerd"</item>
+ <item msgid="7598231293776486217">"Geregistreerd"</item>
+ <item msgid="3720547957514534185">"Niet vereist"</item>
+ <item msgid="1264673582354896949">"In behandeling"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-pa/strings.xml b/testapps/TestServerApp/app/src/main/res/values-pa/strings.xml
new file mode 100644
index 0000000..f4509fc
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-pa/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"ਸੈਟਿੰਗਾਂ"</string>
+ <string name="server_running" msgid="2780193626090379172">"ਸਰਵਰ ਚੱਲ ਰਿਹਾ ਹੈ..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"ਸਰਵਰ ਬੰਦ ਕਰੋ"</string>
+ <string name="server_down" msgid="1030249207496490556">"ਸਰਵਰ ਨਹੀਂ ਚੱਲ ਰਿਹਾ"</string>
+ <string name="start_server" msgid="3878573341408591975">"ਸਰਵਰ ਚਾਲੂ ਕਰੋ"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"ਬੰਦ"</item>
+ <item msgid="3193389681837907872">"ਚਾਲੂ"</item>
+ <item msgid="3124590179479393815">"ਗੈਰ-ਅਨੁਰੂਪ"</item>
+ <item msgid="1606753456265236910">"ਪ੍ਰਬੰਧਿਤ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</item>
+ <item msgid="3930807209231347454">"ਸ਼ਾਮਲ"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"ਪ੍ਰਬੰਧਿਤ ਨਹੀਂ ਹੈ"</item>
+ <item msgid="7598231293776486217">"ਪ੍ਰਬੰਧਿਤ ਹੈ"</item>
+ <item msgid="3720547957514534185">"ਲੋੜੀਂਦਾ ਨਹੀਂ"</item>
+ <item msgid="1264673582354896949">"ਜਾਰੀ ਹੈ"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-pl/strings.xml b/testapps/TestServerApp/app/src/main/res/values-pl/strings.xml
new file mode 100644
index 0000000..4a13003
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-pl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Ustawienia"</string>
+ <string name="server_running" msgid="2780193626090379172">"Serwer działa…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"ZatrzymaJ serwer"</string>
+ <string name="server_down" msgid="1030249207496490556">"Serwer nie działa"</string>
+ <string name="start_server" msgid="3878573341408591975">"Uruchom serwer"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Wyłączono"</item>
+ <item msgid="3193389681837907872">"Włączono"</item>
+ <item msgid="3124590179479393815">"Brak zgodności"</item>
+ <item msgid="1606753456265236910">"Obsługa administracyjna"</item>
+ <item msgid="3930807209231347454">"Dostępne"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Nieobsługiwane"</item>
+ <item msgid="7598231293776486217">"Obsługiwane"</item>
+ <item msgid="3720547957514534185">"Niewymagane"</item>
+ <item msgid="1264673582354896949">"W toku"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-pt-rPT/strings.xml b/testapps/TestServerApp/app/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000..e61c84d
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Definições"</string>
+ <string name="server_running" msgid="2780193626090379172">"O servidor está em execução…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Parar servidor"</string>
+ <string name="server_down" msgid="1030249207496490556">"O servidor está indisponível"</string>
+ <string name="start_server" msgid="3878573341408591975">"Iniciar servidor"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Desativado"</item>
+ <item msgid="3193389681837907872">"Ativado"</item>
+ <item msgid="3124590179479393815">"Incompatível"</item>
+ <item msgid="1606753456265236910">"A aprovisionar"</item>
+ <item msgid="3930807209231347454">"Incluído"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Não aprovisionado"</item>
+ <item msgid="7598231293776486217">"Aprovisionado"</item>
+ <item msgid="3720547957514534185">"Não obrigatório"</item>
+ <item msgid="1264673582354896949">"Em curso"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-pt/strings.xml b/testapps/TestServerApp/app/src/main/res/values-pt/strings.xml
new file mode 100644
index 0000000..1d2310d
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-pt/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Configurações"</string>
+ <string name="server_running" msgid="2780193626090379172">"O servidor está em execução..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Interromper servidor"</string>
+ <string name="server_down" msgid="1030249207496490556">"O servidor está fora do ar."</string>
+ <string name="start_server" msgid="3878573341408591975">"Iniciar servidor"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Desativado"</item>
+ <item msgid="3193389681837907872">"Ativado"</item>
+ <item msgid="3124590179479393815">"Incompatível"</item>
+ <item msgid="1606753456265236910">"Provisionando"</item>
+ <item msgid="3930807209231347454">"Incluso"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Não provisionado"</item>
+ <item msgid="7598231293776486217">"Provisionado"</item>
+ <item msgid="3720547957514534185">"Não obrigatório"</item>
+ <item msgid="1264673582354896949">"Em andamento"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ro/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ro/strings.xml
new file mode 100644
index 0000000..a84085a
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ro/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Setări"</string>
+ <string name="server_running" msgid="2780193626090379172">"Serverul rulează..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Oprește serverul"</string>
+ <string name="server_down" msgid="1030249207496490556">"Serverul nu funcționează"</string>
+ <string name="start_server" msgid="3878573341408591975">"Pornește serverul"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Dezactivat"</item>
+ <item msgid="3193389681837907872">"Activat"</item>
+ <item msgid="3124590179479393815">"Incompatibil"</item>
+ <item msgid="1606753456265236910">"Configurarea accesului pentru utilizatori"</item>
+ <item msgid="3930807209231347454">"Inclus"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Nu a fost configurat accesul"</item>
+ <item msgid="7598231293776486217">"A fost configurat accesul"</item>
+ <item msgid="3720547957514534185">"Nu este obligatoriu"</item>
+ <item msgid="1264673582354896949">"În desfășurare"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ru/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ru/strings.xml
new file mode 100644
index 0000000..1242f96
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ru/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Настройки"</string>
+ <string name="server_running" msgid="2780193626090379172">"Сервер работает…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Остановить сервер"</string>
+ <string name="server_down" msgid="1030249207496490556">"Сервер не работает"</string>
+ <string name="start_server" msgid="3878573341408591975">"Запустить сервер"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Неактивно"</item>
+ <item msgid="3193389681837907872">"Активно"</item>
+ <item msgid="3124590179479393815">"Несовместимо"</item>
+ <item msgid="1606753456265236910">"Инициализация"</item>
+ <item msgid="3930807209231347454">"Включено"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Не подготовлено"</item>
+ <item msgid="7598231293776486217">"Подготовлено"</item>
+ <item msgid="3720547957514534185">"Необязательно"</item>
+ <item msgid="1264673582354896949">"На рассмотрении"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-si/strings.xml b/testapps/TestServerApp/app/src/main/res/values-si/strings.xml
new file mode 100644
index 0000000..47dba95
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-si/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"සැකසීම්"</string>
+ <string name="server_running" msgid="2780193626090379172">"සේවාදායකය ධාවනය වේ..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"සේවාදායකය නවත්වන්න"</string>
+ <string name="server_down" msgid="1030249207496490556">"සේවාදායකය බිඳ වැටී ඇත"</string>
+ <string name="start_server" msgid="3878573341408591975">"සේවාදායකය අරඹන්න"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"අබලයි"</item>
+ <item msgid="3193389681837907872">"සබලයි"</item>
+ <item msgid="3124590179479393815">"නොගැළපෙන"</item>
+ <item msgid="1606753456265236910">"ප්රතිපාදනය කරමින්"</item>
+ <item msgid="3930807209231347454">"ඇතුළත් වේ"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"ප්රතිපාදනය කර නැත"</item>
+ <item msgid="7598231293776486217">"ප්රතිපාදන ලත්"</item>
+ <item msgid="3720547957514534185">"අවශ්ය නැත"</item>
+ <item msgid="1264673582354896949">"ප්රගතියේ පවතී"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-sk/strings.xml b/testapps/TestServerApp/app/src/main/res/values-sk/strings.xml
new file mode 100644
index 0000000..ca4bd55
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-sk/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Nastavenia"</string>
+ <string name="server_running" msgid="2780193626090379172">"Server je spustený…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Zastaviť server"</string>
+ <string name="server_down" msgid="1030249207496490556">"Server je nedostupný"</string>
+ <string name="start_server" msgid="3878573341408591975">"Spustiť server"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Vypnuté"</item>
+ <item msgid="3193389681837907872">"Zapnuté"</item>
+ <item msgid="3124590179479393815">"Nekompatibilné"</item>
+ <item msgid="1606753456265236910">"Poskytovanie"</item>
+ <item msgid="3930807209231347454">"Zahrnuté"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Neposkytuje sa"</item>
+ <item msgid="7598231293776486217">"Poskytuje sa"</item>
+ <item msgid="3720547957514534185">"Nepovinné"</item>
+ <item msgid="1264673582354896949">"Spracúva sa"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-sl/strings.xml b/testapps/TestServerApp/app/src/main/res/values-sl/strings.xml
new file mode 100644
index 0000000..570e6e2
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-sl/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Nastavitve"</string>
+ <string name="server_running" msgid="2780193626090379172">"Strežnik se izvaja ..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Ustavi strežnik"</string>
+ <string name="server_down" msgid="1030249207496490556">"Strežnik ne deluje"</string>
+ <string name="start_server" msgid="3878573341408591975">"Zaženi strežnik"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Onemogočeno"</item>
+ <item msgid="3193389681837907872">"Omogočeno"</item>
+ <item msgid="3124590179479393815">"Nezdružljivo"</item>
+ <item msgid="1606753456265236910">"Omogočanje uporabe"</item>
+ <item msgid="3930807209231347454">"Vključeno"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Uporaba ni omogočena"</item>
+ <item msgid="7598231293776486217">"Omogočeno"</item>
+ <item msgid="3720547957514534185">"Ni zahtevano"</item>
+ <item msgid="1264673582354896949">"Poteka"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-sq/strings.xml b/testapps/TestServerApp/app/src/main/res/values-sq/strings.xml
new file mode 100644
index 0000000..fbcd4da
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-sq/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Cilësimet"</string>
+ <string name="server_running" msgid="2780193626090379172">"Serveri është në ekzekutim..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Ndalo serverin"</string>
+ <string name="server_down" msgid="1030249207496490556">"Serveri nuk po funksionon"</string>
+ <string name="start_server" msgid="3878573341408591975">"Nis serverin"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Çaktivizuar"</item>
+ <item msgid="3193389681837907872">"Aktivizuar"</item>
+ <item msgid="3124590179479393815">"I papërputhshëm"</item>
+ <item msgid="1606753456265236910">"Po përgatitet"</item>
+ <item msgid="3930807209231347454">"Përfshirë"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Nuk është përgatitur"</item>
+ <item msgid="7598231293776486217">"Përgatitur"</item>
+ <item msgid="3720547957514534185">"Nuk kërkohet"</item>
+ <item msgid="1264673582354896949">"Në vazhdim"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-sr/strings.xml b/testapps/TestServerApp/app/src/main/res/values-sr/strings.xml
new file mode 100644
index 0000000..e8fc322
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-sr/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Подешавања"</string>
+ <string name="server_running" msgid="2780193626090379172">"Сервер је покренут…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Заустави сервер"</string>
+ <string name="server_down" msgid="1030249207496490556">"Сервер је пао"</string>
+ <string name="start_server" msgid="3878573341408591975">"Покрени сервер"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Онемогућено"</item>
+ <item msgid="3193389681837907872">"Омогућено"</item>
+ <item msgid="3124590179479393815">"Некомпатибилно"</item>
+ <item msgid="1606753456265236910">"Додељује се"</item>
+ <item msgid="3930807209231347454">"Уврштено"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Није додељено"</item>
+ <item msgid="7598231293776486217">"Додељено"</item>
+ <item msgid="3720547957514534185">"Није обавезно"</item>
+ <item msgid="1264673582354896949">"У току"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-sv/strings.xml b/testapps/TestServerApp/app/src/main/res/values-sv/strings.xml
new file mode 100644
index 0000000..8470695
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-sv/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Inställningar"</string>
+ <string name="server_running" msgid="2780193626090379172">"Servern körs …"</string>
+ <string name="stop_server" msgid="6192029827529013598">"Stoppa servern"</string>
+ <string name="server_down" msgid="1030249207496490556">"Servern ligger nere"</string>
+ <string name="start_server" msgid="3878573341408591975">"Starta servern"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Inaktiverad"</item>
+ <item msgid="3193389681837907872">"Aktiverad"</item>
+ <item msgid="3124590179479393815">"Ej kompatibel"</item>
+ <item msgid="1606753456265236910">"Certifikaten installeras"</item>
+ <item msgid="3930807209231347454">"Inkluderat"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Ej administrerad"</item>
+ <item msgid="7598231293776486217">"Administrerad"</item>
+ <item msgid="3720547957514534185">"Ej obligatorisk"</item>
+ <item msgid="1264673582354896949">"Pågår"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-sw/strings.xml b/testapps/TestServerApp/app/src/main/res/values-sw/strings.xml
new file mode 100644
index 0000000..c1155b8
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-sw/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Mipangilio"</string>
+ <string name="server_running" msgid="2780193626090379172">"Seva inatekeleza..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Sitisha Seva"</string>
+ <string name="server_down" msgid="1030249207496490556">"Seva iko chini"</string>
+ <string name="start_server" msgid="3878573341408591975">"Washa Seva"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Imezimwa"</item>
+ <item msgid="3193389681837907872">"Imewashwa"</item>
+ <item msgid="3124590179479393815">"Haioani"</item>
+ <item msgid="1606753456265236910">"Inaandaa"</item>
+ <item msgid="3930807209231347454">"Imejumuishwa"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Haijatolewa"</item>
+ <item msgid="7598231293776486217">"Imetolewa"</item>
+ <item msgid="3720547957514534185">"Haihitajiki"</item>
+ <item msgid="1264673582354896949">"Inaendelea"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ta/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ta/strings.xml
new file mode 100644
index 0000000..adad427
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ta/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"அமைப்புகள்"</string>
+ <string name="server_running" msgid="2780193626090379172">"சேவையகம் இயக்கத்தில் உள்ளது..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"சேவையகத்தை நிறுத்து"</string>
+ <string name="server_down" msgid="1030249207496490556">"சேவையகம் இயங்கவில்லை"</string>
+ <string name="start_server" msgid="3878573341408591975">"சேவையகத்தைத் தொடங்கு"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"முடக்கப்பட்டது"</item>
+ <item msgid="3193389681837907872">"இயக்கப்பட்டது"</item>
+ <item msgid="3124590179479393815">"இணக்கமற்றது"</item>
+ <item msgid="1606753456265236910">"அமைக்கிறது"</item>
+ <item msgid="3930807209231347454">"சேர்க்கப்பட்டது"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"அமைக்கப்படவில்லை"</item>
+ <item msgid="7598231293776486217">"அமைக்கப்பட்டது"</item>
+ <item msgid="3720547957514534185">"அவசியமில்லை"</item>
+ <item msgid="1264673582354896949">"செயலிலுள்ளது"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-te/strings.xml b/testapps/TestServerApp/app/src/main/res/values-te/strings.xml
new file mode 100644
index 0000000..39cc2fe
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-te/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"టెస్ట్సర్వర్యాప్"</string>
+ <string name="action_settings" msgid="1335152369747372374">"సెట్టింగ్లు"</string>
+ <string name="server_running" msgid="2780193626090379172">"సర్వర్ రన్ అవుతోంది..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"సర్వర్ను ఆపివేయండి"</string>
+ <string name="server_down" msgid="1030249207496490556">"సర్వర్ డౌన్ అయింది"</string>
+ <string name="start_server" msgid="3878573341408591975">"సర్వర్ను ప్రారంభించండి"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"డిజేబుల్ చేయబడింది"</item>
+ <item msgid="3193389681837907872">"ఎనేబుల్ చేయబడింది"</item>
+ <item msgid="3124590179479393815">"అనుకూలంగా లేదు"</item>
+ <item msgid="1606753456265236910">"కేటాయిస్తోంది"</item>
+ <item msgid="3930807209231347454">"చేర్చబడింది"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"కేటాయించలేదు"</item>
+ <item msgid="7598231293776486217">"కేటాయించబడింది"</item>
+ <item msgid="3720547957514534185">"అవసరం లేదు"</item>
+ <item msgid="1264673582354896949">"ప్రోగ్రెస్లో ఉంది"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-th/strings.xml b/testapps/TestServerApp/app/src/main/res/values-th/strings.xml
new file mode 100644
index 0000000..78232ca
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-th/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"แอปเซิร์ฟเวอร์ทดสอบ"</string>
+ <string name="action_settings" msgid="1335152369747372374">"การตั้งค่า"</string>
+ <string name="server_running" msgid="2780193626090379172">"เซิร์ฟเวอร์กำลังทำงาน..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"หยุดเซิร์ฟเวอร์"</string>
+ <string name="server_down" msgid="1030249207496490556">"เซิร์ฟเวอร์ขัดข้อง"</string>
+ <string name="start_server" msgid="3878573341408591975">"เริ่มต้นเซิร์ฟเวอร์"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"ปิดใช้อยู่"</item>
+ <item msgid="3193389681837907872">"เปิดใช้อยู่"</item>
+ <item msgid="3124590179479393815">"ใช้งานร่วมกันไม่ได้"</item>
+ <item msgid="1606753456265236910">"การจัดสรร"</item>
+ <item msgid="3930807209231347454">"รวมอยู่ด้วย"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"ยังไม่ได้จัดสรร"</item>
+ <item msgid="7598231293776486217">"จัดสรรแล้ว"</item>
+ <item msgid="3720547957514534185">"ไม่บังคับ"</item>
+ <item msgid="1264673582354896949">"อยู่ในระหว่างดำเนินการ"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-ur/strings.xml b/testapps/TestServerApp/app/src/main/res/values-ur/strings.xml
new file mode 100644
index 0000000..5df75a7
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-ur/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"ترتیبات"</string>
+ <string name="server_running" msgid="2780193626090379172">"سرور چل رہا ہے..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"سرور روکیں"</string>
+ <string name="server_down" msgid="1030249207496490556">"سرور ڈاؤن ہے"</string>
+ <string name="start_server" msgid="3878573341408591975">"سرور شروع کریں"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"غیر فعال ہے"</item>
+ <item msgid="3193389681837907872">"فعال ہے"</item>
+ <item msgid="3124590179479393815">"غیر مطابقت پذیر"</item>
+ <item msgid="1606753456265236910">"فراہمی"</item>
+ <item msgid="3930807209231347454">"شامل ہے"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"فراہم نہیں کیا گا"</item>
+ <item msgid="7598231293776486217">"فراہم کیا گیا"</item>
+ <item msgid="3720547957514534185">"غیر مطلوب"</item>
+ <item msgid="1264673582354896949">"پیشرفت میں ہے"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-vi/strings.xml b/testapps/TestServerApp/app/src/main/res/values-vi/strings.xml
new file mode 100644
index 0000000..78bd3d8
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-vi/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Cài đặt"</string>
+ <string name="server_running" msgid="2780193626090379172">"Máy chủ đang chạy..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Dừng máy chủ"</string>
+ <string name="server_down" msgid="1030249207496490556">"Máy chủ không hoạt động"</string>
+ <string name="start_server" msgid="3878573341408591975">"Khởi động máy chủ"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Đã tắt"</item>
+ <item msgid="3193389681837907872">"Đã bật"</item>
+ <item msgid="3124590179479393815">"Không tương thích"</item>
+ <item msgid="1606753456265236910">"Đang cung cấp"</item>
+ <item msgid="3930807209231347454">"Đã bao gồm"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Chưa được cung cấp"</item>
+ <item msgid="7598231293776486217">"Đã cung cấp"</item>
+ <item msgid="3720547957514534185">"Không bắt buộc"</item>
+ <item msgid="1264673582354896949">"Đang xử lý"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-zh-rCN/strings.xml b/testapps/TestServerApp/app/src/main/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..6e26819
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-zh-rCN/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"设置"</string>
+ <string name="server_running" msgid="2780193626090379172">"服务器正在运行…"</string>
+ <string name="stop_server" msgid="6192029827529013598">"停止服务器"</string>
+ <string name="server_down" msgid="1030249207496490556">"服务器出现故障"</string>
+ <string name="start_server" msgid="3878573341408591975">"启动服务器"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"已停用"</item>
+ <item msgid="3193389681837907872">"已启用"</item>
+ <item msgid="3124590179479393815">"不兼容"</item>
+ <item msgid="1606753456265236910">"正在配置"</item>
+ <item msgid="3930807209231347454">"已包含"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"未配置"</item>
+ <item msgid="7598231293776486217">"已配置"</item>
+ <item msgid="3720547957514534185">"不需要"</item>
+ <item msgid="1264673582354896949">"进行中"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestServerApp/app/src/main/res/values-zu/strings.xml b/testapps/TestServerApp/app/src/main/res/values-zu/strings.xml
new file mode 100644
index 0000000..fbb6262
--- /dev/null
+++ b/testapps/TestServerApp/app/src/main/res/values-zu/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name" msgid="2894617184221823208">"I-TestServerApp"</string>
+ <string name="action_settings" msgid="1335152369747372374">"Amasethingi"</string>
+ <string name="server_running" msgid="2780193626090379172">"Iseva iyaqhubeka..."</string>
+ <string name="stop_server" msgid="6192029827529013598">"Misa Iseva"</string>
+ <string name="server_down" msgid="1030249207496490556">"Iseva iphansi"</string>
+ <string name="start_server" msgid="3878573341408591975">"Qalisa Iseva"</string>
+ <string-array name="entitlement_status">
+ <item msgid="5560300387618996934">"Kukhutshaziwe"</item>
+ <item msgid="3193389681837907872">"Kunikwe amandla"</item>
+ <item msgid="3124590179479393815">"Ayisebenzisani"</item>
+ <item msgid="1606753456265236910">"Iyahlinzeka"</item>
+ <item msgid="3930807209231347454">"Kuhlanganisiwe"</item>
+ </string-array>
+ <string-array name="provision_status">
+ <item msgid="3486273747926710021">"Akulungiselelwanga"</item>
+ <item msgid="7598231293776486217">"Kulungiselelwe"</item>
+ <item msgid="3720547957514534185">"Akudingekile"</item>
+ <item msgid="1264673582354896949">"Kuyaqhubeka"</item>
+ </string-array>
+</resources>
diff --git a/testapps/TestSliceApp/.idea/gradle.xml b/testapps/TestSliceApp/.idea/gradle.xml
index 526b4c2..a2d7c21 100644
--- a/testapps/TestSliceApp/.idea/gradle.xml
+++ b/testapps/TestSliceApp/.idea/gradle.xml
@@ -13,7 +13,6 @@
<option value="$PROJECT_DIR$/app" />
</set>
</option>
- <option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
diff --git a/testapps/TestSliceApp/.idea/misc.xml b/testapps/TestSliceApp/.idea/misc.xml
index a329266..7c85865 100644
--- a/testapps/TestSliceApp/.idea/misc.xml
+++ b/testapps/TestSliceApp/.idea/misc.xml
@@ -1,68 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
- <component name="DesignSurface">
- <option name="filePathToZoomLevelMap">
- <map>
- <entry key="app/src/main/res/drawable/ic_launcher_background.xml" value="0.38177083333333334" />
- <entry key="app/src/main/res/layout/_copy.xml" value="0.365625" />
- <entry key="app/src/main/res/layout/activity_main.xml" value="0.4891304347826087" />
- <entry key="app/src/main/res/layout/copy.xml" value="0.37135416666666665" />
- <entry key="app/src/main/res/layout/fragment_c_b_s.xml" value="0.473731884057971" />
- <entry key="app/src/main/res/layout/fragment_c_b_s_copy.xml" value="0.365625" />
- <entry key="app/src/main/res/layout/fragment_main.xml" value="0.46693840579710144" />
- <entry key="app/src/main/res/layout/fragment_prioritize_bandwidth.xml" value="0.473731884057971" />
- <entry key="app/src/main/res/layout/fragment_prioritize_bandwidth2.xml" value="0.365625" />
- <entry key="app/src/main/res/layout/fragment_prioritize_latency.xml" value="0.473731884057971" />
- <entry key="app/src/main/res/layout/fragment_prioritize_latency2.xml" value="0.365625" />
- </map>
- </option>
- </component>
+ <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="androidx.annotation.Nullable" />
<option name="myDefaultNotNull" value="androidx.annotation.NonNull" />
<option name="myNullables">
<value>
- <list size="17">
- <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
- <item index="1" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
- <item index="2" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
- <item index="3" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
- <item index="4" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
- <item index="5" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
- <item index="6" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
- <item index="7" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
- <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
- <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
- <item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
- <item index="11" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
- <item index="12" class="java.lang.String" itemvalue="io.reactivex.annotations.Nullable" />
- <item index="13" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.Nullable" />
- <item index="14" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
- <item index="15" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
- <item index="16" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
+ <list size="15">
+ <item index="0" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
+ <item index="1" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+ <item index="2" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
+ <item index="3" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.Nullable" />
+ <item index="4" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
+ <item index="5" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+ <item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
+ <item index="7" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+ <item index="8" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
+ <item index="9" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+ <item index="10" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
+ <item index="11" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
+ <item index="12" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
+ <item index="13" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
+ <item index="14" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
- <list size="17">
- <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
- <item index="1" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
- <item index="2" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+ <list size="14">
+ <item index="0" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
+ <item index="1" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
+ <item index="2" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
- <item index="4" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
- <item index="5" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
- <item index="6" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
- <item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
- <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
- <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
+ <item index="4" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
+ <item index="5" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+ <item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
+ <item index="7" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+ <item index="8" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+ <item index="9" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="10" class="java.lang.String" itemvalue="org.eclipse.jdt.annotation.NonNull" />
- <item index="11" class="java.lang.String" itemvalue="io.reactivex.annotations.NonNull" />
- <item index="12" class="java.lang.String" itemvalue="io.reactivex.rxjava3.annotations.NonNull" />
- <item index="13" class="java.lang.String" itemvalue="lombok.NonNull" />
- <item index="14" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
- <item index="15" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
- <item index="16" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
+ <item index="11" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
+ <item index="12" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
+ <item index="13" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
</list>
</value>
</option>
diff --git a/testapps/TestSliceApp/app/src/main/AndroidManifest.xml b/testapps/TestSliceApp/app/src/main/AndroidManifest.xml
index d28bbb0..53754de 100644
--- a/testapps/TestSliceApp/app/src/main/AndroidManifest.xml
+++ b/testapps/TestSliceApp/app/src/main/AndroidManifest.xml
@@ -3,6 +3,9 @@
package="com.google.android.sample.testsliceapp">
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+ <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+ <uses-permission android:name="android.permission.READ_BASIC_PHONE_STATE" />
+ <uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
@@ -10,7 +13,8 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat"
- android:versionCode="34">
+ android:versionCode="34"
+ android:usesCleartextTraffic="true">
<activity
android:name=".MainActivity"
android:exported="true">
@@ -29,4 +33,4 @@
android:value="true" />
</service>
</application>
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/CBS.java b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/CBS.java
index a555ce6..c85f830 100644
--- a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/CBS.java
+++ b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/CBS.java
@@ -20,7 +20,10 @@
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
+import android.net.TelephonyNetworkSpecifier;
import android.os.Bundle;
+import android.telephony.SubscriptionManager;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -62,6 +65,7 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
}
@Override
@@ -80,23 +84,33 @@
mRelease.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
- mConnectivityManager.unregisterNetworkCallback(
+ try {
+ mConnectivityManager.unregisterNetworkCallback(
mProfileCheckNetworkCallback);
+ } catch (Exception e) {
+ Log.d("SliceTest", "Exception: " + e);
+ }
}
});
mRequest = view.findViewById(R.id.requestcbs);
mRequest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
- NetworkCallback mProfileCheckNetworkCallback = new NetworkCallback() {
+ mProfileCheckNetworkCallback = new NetworkCallback() {
@Override
public void onAvailable(final Network network) {
mNetwork = network;
+ Log.d("CBS", "onAvailable + " + network);
}
};
NetworkRequest.Builder builder = new NetworkRequest.Builder();
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ int subId = SubscriptionManager.getDefaultDataSubscriptionId();
+ builder.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
+ .setSubscriptionId(subId).build());
mConnectivityManager.requestNetwork(builder.build(), mProfileCheckNetworkCallback);
+ Log.d("CBS", "onClick + " + builder.build());
}
});
mPing = view.findViewById(R.id.pingcbs);
@@ -106,8 +120,9 @@
if (mNetwork != null) {
//mNetwork.
try {
- new RequestTask().ping(mNetwork);
+ new RequestTask().execute(mNetwork);
} catch (Exception e) {
+ Log.d("SliceTest", "Exception: " + e);
}
}
}
diff --git a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/PrioritizeBandwidth.java b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/PrioritizeBandwidth.java
index d997178..6812ddc 100644
--- a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/PrioritizeBandwidth.java
+++ b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/PrioritizeBandwidth.java
@@ -21,6 +21,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Bundle;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -73,6 +74,7 @@
new NetworkCallback() {
@Override
public void onAvailable(final Network network) {
+ Log.d("SliceTest", "onAvailable: " + network);
mNetwork = network;
}
};
@@ -80,23 +82,30 @@
mRelease.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
- mConnectivityManager.unregisterNetworkCallback(mProfileCheckNetworkCallback);
+ try {
+ mConnectivityManager.unregisterNetworkCallback(
+ mProfileCheckNetworkCallback);
+ } catch (Exception e) {
+ Log.d("SliceTest", "Exception: " + e);
+ }
}
});
mRequest = view.findViewById(R.id.requestbw);
mRequest.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
- NetworkCallback mProfileCheckNetworkCallback =
+ mProfileCheckNetworkCallback =
new NetworkCallback() {
@Override
public void onAvailable(final Network network) {
+ Log.d("PrioritizeBandwidth", "onAvailable + " + network);
mNetwork = network;
}
};
NetworkRequest.Builder builder = new NetworkRequest.Builder();
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH);
mConnectivityManager.requestNetwork(builder.build(), mProfileCheckNetworkCallback);
+ Log.d("PrioritizeBandwidth", "onClick + " + builder.build());
}
});
mPing = view.findViewById(R.id.pingbw);
@@ -104,10 +113,10 @@
@Override
public void onClick(View view) {
if (mNetwork != null) {
- //mNetwork.
try {
- new RequestTask().ping(mNetwork);
+ new RequestTask().execute(mNetwork);
} catch (Exception e) {
+ Log.d("SliceTest", "Exception: " + e);
}
}
}
diff --git a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/PrioritizeLatency.java b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/PrioritizeLatency.java
index b45362c..a74e7f0 100644
--- a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/PrioritizeLatency.java
+++ b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/PrioritizeLatency.java
@@ -15,31 +15,64 @@
*/
package com.google.android.sample.testsliceapp;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_FEATURE_NOT_SUPPORTED;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NETWORK_NOT_AVAILABLE;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_SUCCESS;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT;
+import static android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED;
+
+import android.annotation.TargetApi;
+import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Bundle;
+import android.telephony.TelephonyManager;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.TextView;
import androidx.fragment.app.Fragment;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
/**
* A simple {@link Fragment} subclass. Use the {@link PrioritizeLatency#newInstance} factory method
* to create an instance of this fragment.
*/
public class PrioritizeLatency extends Fragment {
- Button mRelease, mRequest, mPing;
- Network mNetwork;
+ Button mPurchase, mNetworkRequestRelease, mPing;
+ TextView mResultTextView;
+ Network mNetwork = null;
ConnectivityManager mConnectivityManager;
NetworkCallback mProfileCheckNetworkCallback;
+ TelephonyManager mTelephonyManager;
+ Context mContext;
+ private final ExecutorService mFixedThreadPool = Executors.newFixedThreadPool(3);
+
+ private static final String LOG_TAG = "PrioritizeLatency";
+ private static final int TIMEOUT_FOR_PURCHASE = 5 * 60; // 5 minutes
+
public PrioritizeLatency() {
- // Required empty public constructor
+ // Required empty public constructor
}
/**
@@ -61,6 +94,9 @@
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ mContext = getContext();
+ mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
}
@Override
@@ -68,48 +104,205 @@
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_prioritize_latency, container, false);
- mProfileCheckNetworkCallback =
- new NetworkCallback() {
- @Override
- public void onAvailable(final Network network) {
- mNetwork = network;
- }
- };
- mRelease = view.findViewById(R.id.releaselatency);
- mRelease.setOnClickListener(new OnClickListener() {
+ mResultTextView = view.findViewById(R.id.resultTextView);
+
+ mPurchase = view.findViewById(R.id.purchaseButton);
+ mPurchase.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
- mConnectivityManager.unregisterNetworkCallback(mProfileCheckNetworkCallback);
+ Log.d(LOG_TAG, "Clicking purchase button");
+ onPurchaseButtonClick();
}
});
- mRequest = view.findViewById(R.id.requestlatency);
- mRequest.setOnClickListener(new OnClickListener() {
+
+ mNetworkRequestRelease = view.findViewById(R.id.requestReleaseButton);
+ mNetworkRequestRelease.setEnabled(false);
+ mNetworkRequestRelease.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
- NetworkCallback mProfileCheckNetworkCallback = new NetworkCallback() {
- @Override
- public void onAvailable(final Network network) {
- mNetwork = network;
- }
- };
- NetworkRequest.Builder builder = new NetworkRequest.Builder();
- builder.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
- mConnectivityManager.requestNetwork(builder.build(), mProfileCheckNetworkCallback);
+ Log.d(LOG_TAG, "Clicking Request/Release Network button");
+ onNetworkRequestReleaseClick();
}
});
+
mPing = view.findViewById(R.id.pinglatency);
+ mPing.setEnabled(false);
mPing.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
+ Log.d(LOG_TAG, "Clicking Ping button");
if (mNetwork != null) {
- //mNetwork.
- try {
- new RequestTask().ping(mNetwork);
- } catch (Exception e) {
- }
+ mFixedThreadPool.execute(() -> {
+ try {
+ RequestTask requestTask = new RequestTask();
+ requestTask.ping(mNetwork);
+ updateResultTextView("Result: Ping is done successfully!");
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Exception at ping: " + e);
+ updateResultTextView("Result: Got exception with ping!!!");
+ }
+ });
}
}
});
return view;
}
+
+ private void onNetworkRequestReleaseClick() {
+ if (mNetwork == null) {
+ mProfileCheckNetworkCallback = new NetworkCallback() {
+ @Override
+ public void onAvailable(final Network network) {
+ Log.d(LOG_TAG, "onAvailable + " + network);
+ mNetwork = network;
+ updateUIOnNetworkAvailable();
+ }
+ };
+ NetworkRequest.Builder builder = new NetworkRequest.Builder();
+ builder.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
+ mConnectivityManager.requestNetwork(builder.build(),
+ mProfileCheckNetworkCallback);
+ Log.d(LOG_TAG, "Network Request/Release onClick + " + builder.build());
+ mResultTextView.setText(R.string.network_requested);
+ } else {
+ try {
+ mConnectivityManager.unregisterNetworkCallback(
+ mProfileCheckNetworkCallback);
+ mNetwork = null;
+ mNetworkRequestRelease.setText(R.string.request_network);
+ mResultTextView.setText(R.string.network_released);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Exception when releasing network: " + e);
+ mResultTextView.setText(R.string.network_release_failed);
+ }
+ }
+ }
+
+ @TargetApi(34)
+ private void onPurchaseButtonClick() {
+ try {
+ if (mTelephonyManager.isPremiumCapabilityAvailableForPurchase(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY)) {
+ LinkedBlockingQueue<Integer> purchaseRequest = new LinkedBlockingQueue<>(1);
+
+ // Try to purchase the capability
+ mTelephonyManager.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY,
+ mFixedThreadPool, purchaseRequest::offer);
+ mResultTextView.setText(R.string.purchase_in_progress);
+
+ mFixedThreadPool.execute(() -> {
+ try {
+ Integer result = purchaseRequest.poll(
+ TIMEOUT_FOR_PURCHASE, TimeUnit.SECONDS);
+ if (result == null) {
+ updateResultTextView(R.string.purchase_empty_result);
+ Log.d(LOG_TAG, "Got null result at purchasePremiumCapability");
+ return;
+ }
+
+ String purchaseResultText = "Result: "
+ + purchasePremiumResultToText(result.intValue());
+ updateResultTextView(purchaseResultText);
+ Log.d(LOG_TAG, purchaseResultText);
+
+ if (isPremiumCapacityAvailableForUse(result.intValue())) {
+ updateNetworkRequestReleaseButton(true);
+ }
+ } catch (InterruptedException e) {
+ Log.e(LOG_TAG, "InterruptedException at onPurchaseButtonClick: " + e);
+ updateResultTextView(R.string.purchase_exception);
+ }
+ });
+ } else {
+ mResultTextView.setText(R.string.premium_not_available);
+ }
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Exception when purchasing network premium: " + e);
+ mResultTextView.setText(R.string.purchase_exception);
+ }
+ }
+
+ private void updateNetworkRequestReleaseButton(boolean enabled) {
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mNetworkRequestRelease.setEnabled(enabled);
+ }
+ });
+ }
+
+ private void updateResultTextView(int status) {
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.setText(status);
+ }
+ });
+ }
+
+ private void updateResultTextView(String status) {
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mResultTextView.setText(status);
+ }
+ });
+ }
+
+ private void updateUIOnNetworkAvailable() {
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ mPing.setEnabled(true);
+ mNetworkRequestRelease.setText(R.string.release_network);
+ mResultTextView.setText(R.string.network_available);
+ }
+ });
+ }
+
+ private String purchasePremiumResultToText(int result) {
+ switch (result) {
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_SUCCESS:
+ return "Success";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED:
+ return "Throttled";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED:
+ return "Already purchased";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS:
+ return "Already in progress";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_FOREGROUND:
+ return "Not foreground";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED:
+ return "User canceled";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED:
+ return "Carrier disabled";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR:
+ return "Carrier error";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT:
+ return "Timeout";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_FEATURE_NOT_SUPPORTED:
+ return "Feature not supported";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_NETWORK_NOT_AVAILABLE:
+ return "Network not available";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED:
+ return "Entitlement check failed";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION:
+ return "Not default data subscription";
+ case PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP:
+ return "Pending network setup";
+ default:
+ String errorStr = "Unknown purchasing result " + result;
+ Log.e(LOG_TAG, errorStr);
+ return errorStr;
+ }
+ }
+
+ private boolean isPremiumCapacityAvailableForUse(int purchaseResult) {
+ if (purchaseResult == PURCHASE_PREMIUM_CAPABILITY_RESULT_SUCCESS
+ || purchaseResult == PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/RequestTask.java b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/RequestTask.java
index b12939e..569c066 100644
--- a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/RequestTask.java
+++ b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/RequestTask.java
@@ -16,24 +16,35 @@
package com.google.android.sample.testsliceapp;
import android.net.Network;
+import android.os.AsyncTask;
+import android.util.Log;
-import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
+import java.util.Scanner;
-class RequestTask{
+class RequestTask extends AsyncTask<Network, Integer, Integer> {
+ protected Integer doInBackground(Network... network) {
+ ping(network[0]);
+ return 0;
+ }
String ping(Network network) {
URL url = null;
try {
url = new URL("http://www.google.com");
} catch (Exception e) {
+ Log.d("SliceTest", "exception: " + e);
}
if (url != null) {
try {
- return httpGet(network, url);
+ Log.d("SliceTest", "ping " + url);
+ String result = httpGet(network, url);
+ Log.d("SliceTest", "result " + result);
+ return result;
} catch (Exception e) {
+ Log.d("SliceTest", "exception: " + e);
}
}
return "";
@@ -47,7 +58,9 @@
HttpURLConnection connection = (HttpURLConnection) network.openConnection(httpUrl);
try {
InputStream inputStream = connection.getInputStream();
- return new BufferedInputStream(inputStream).toString();
+ Log.d("httpGet", "httpUrl + " + httpUrl);
+ Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
+ return scanner.hasNext() ? scanner.next() : "";
} finally {
connection.disconnect();
}
diff --git a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/TestCarrierService.java b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/TestCarrierService.java
index b1d019e..daa1d17 100644
--- a/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/TestCarrierService.java
+++ b/testapps/TestSliceApp/app/src/main/java/com/google/android/sample/testsliceapp/TestCarrierService.java
@@ -21,6 +21,7 @@
import android.service.carrier.CarrierService;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
+import android.util.Log;
/**
* Carrier Service that sets the carrier config upon being bound by the system. Requires UICC
@@ -32,11 +33,13 @@
CarrierConfigManager cfgMgr =
(CarrierConfigManager) getSystemService(Context.CARRIER_CONFIG_SERVICE);
cfgMgr.notifyConfigChangedForSubId(SubscriptionManager.getDefaultSubscriptionId());
+ Log.d("TestCarrierService", "onCreate + ");
}
@Override
public PersistableBundle onLoadConfig(CarrierIdentifier carrierIdentifier) {
PersistableBundle config = new PersistableBundle();
+ Log.d("TestCarrierService", "onLoadConfig + ");
return config;
}
}
diff --git a/testapps/TestSliceApp/app/src/main/res/layout/activity_main.xml b/testapps/TestSliceApp/app/src/main/res/layout/activity_main.xml
index a723e6f..8a7d991 100644
--- a/testapps/TestSliceApp/app/src/main/res/layout/activity_main.xml
+++ b/testapps/TestSliceApp/app/src/main/res/layout/activity_main.xml
@@ -6,7 +6,6 @@
android:layout_height="match_parent"
tools:context=".MainActivity" >
<androidx.fragment.app.FragmentContainerView
- xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayoutMainFrag"
diff --git a/testapps/TestSliceApp/app/src/main/res/layout/fragment_c_b_s.xml b/testapps/TestSliceApp/app/src/main/res/layout/fragment_c_b_s.xml
index ac2ef9d..eff68ac 100644
--- a/testapps/TestSliceApp/app/src/main/res/layout/fragment_c_b_s.xml
+++ b/testapps/TestSliceApp/app/src/main/res/layout/fragment_c_b_s.xml
@@ -8,9 +8,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayoutCBS">
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
+<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/frameLayout3"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -19,30 +17,33 @@
android:id="@+id/textView3"
android:layout_width="342dp"
android:layout_height="49dp"
- android:text="CBS"
+ android:text="@string/cbs_title"
tools:layout_editor_absoluteX="19dp"
tools:layout_editor_absoluteY="7dp" />
<Button
android:id="@+id/requestcbs"
android:layout_width="186dp"
android:layout_height="57dp"
- android:text="Request Network"
- tools:layout_editor_absoluteX="120dp"
- tools:layout_editor_absoluteY="154dp" />
+ android:layout_marginTop="164dp"
+ android:text="@string/request_network"
+ app:layout_constraintTop_toTopOf="parent"
+ tools:layout_editor_absoluteX="112dp" />
<Button
android:id="@+id/releasecbs"
android:layout_width="187dp"
android:layout_height="61dp"
- android:text="Release Network"
- tools:layout_editor_absoluteX="119dp"
- tools:layout_editor_absoluteY="273dp" />
+ android:layout_marginTop="124dp"
+ android:text="@string/release_network"
+ app:layout_constraintTop_toBottomOf="@+id/requestcbs"
+ tools:layout_editor_absoluteX="119dp" />
<Button
android:id="@+id/pingcbs"
android:layout_width="186dp"
android:layout_height="55dp"
- android:text="Ping"
- tools:layout_editor_absoluteX="120dp"
- tools:layout_editor_absoluteY="379dp" />
+ android:text="@string/ping"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/releasecbs"
+ tools:layout_editor_absoluteX="120dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
</RelativeLayout>
\ No newline at end of file
diff --git a/testapps/TestSliceApp/app/src/main/res/layout/fragment_main.xml b/testapps/TestSliceApp/app/src/main/res/layout/fragment_main.xml
index 11e95a8..5c12075 100644
--- a/testapps/TestSliceApp/app/src/main/res/layout/fragment_main.xml
+++ b/testapps/TestSliceApp/app/src/main/res/layout/fragment_main.xml
@@ -5,18 +5,17 @@
android:layout_height="match_parent"
tools:context=".MainFragment">
- <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ <androidx.constraintlayout.widget.ConstraintLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayoutMain"
tools:context=".MainActivity">
<Button
android:id="@+id/cbs"
- android:layout_width="222dp"
- android:layout_height="51dp"
- android:text="CBS"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/cbs_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.493"
@@ -25,9 +24,9 @@
app:layout_constraintVertical_bias="0.751" />
<Button
android:id="@+id/latency"
- android:layout_width="222dp"
- android:layout_height="46dp"
- android:text="PRIORITIZE LATENCY"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/latency_title"
app:layout_constraintBottom_toTopOf="@+id/cbs"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
@@ -38,7 +37,7 @@
android:id="@+id/bw"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="PRIORITIZE BANDWIDTH"
+ android:text="@string/bw_title"
app:layout_constraintBottom_toTopOf="@+id/latency"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
diff --git a/testapps/TestSliceApp/app/src/main/res/layout/fragment_prioritize_bandwidth.xml b/testapps/TestSliceApp/app/src/main/res/layout/fragment_prioritize_bandwidth.xml
index 8933e7a..412ec39 100644
--- a/testapps/TestSliceApp/app/src/main/res/layout/fragment_prioritize_bandwidth.xml
+++ b/testapps/TestSliceApp/app/src/main/res/layout/fragment_prioritize_bandwidth.xml
@@ -8,9 +8,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayoutBW">
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
+<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/frameLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -19,7 +17,7 @@
android:id="@+id/textView2"
android:layout_width="371dp"
android:layout_height="52dp"
- android:text="Prioritize Bandwidth"
+ android:text="@string/bw_title"
tools:layout_editor_absoluteX="20dp"
tools:layout_editor_absoluteY="4dp" />
<Button
@@ -27,7 +25,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="64dp"
- android:text="Release Network"
+ android:text="@string/release_network"
app:layout_constraintBottom_toTopOf="@+id/requestbw"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -38,7 +36,7 @@
android:layout_width="182dp"
android:layout_height="42dp"
android:layout_marginBottom="228dp"
- android:text="Ping"
+ android:text="@string/ping"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.493"
@@ -48,7 +46,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="308dp"
- android:text="RequestNetwork"
+ android:text="@string/request_network"
app:layout_constraintBottom_toTopOf="@+id/pingbw"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.495"
diff --git a/testapps/TestSliceApp/app/src/main/res/layout/fragment_prioritize_latency.xml b/testapps/TestSliceApp/app/src/main/res/layout/fragment_prioritize_latency.xml
index 9527d69..37a519f 100644
--- a/testapps/TestSliceApp/app/src/main/res/layout/fragment_prioritize_latency.xml
+++ b/testapps/TestSliceApp/app/src/main/res/layout/fragment_prioritize_latency.xml
@@ -8,51 +8,60 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/frameLayoutLatency">
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/frameLayout"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context=".PrioritizeLatency" >
- <Button
- android:id="@+id/requestlatency"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="RequestNetwork"
- app:layout_constraintBottom_toTopOf="@+id/button6"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_bias="0.461"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent"
- app:layout_constraintVertical_bias="0.717" />
- <Button
- android:id="@+id/releaselatency"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginBottom="76dp"
- android:text="Release Network"
- app:layout_constraintBottom_toTopOf="@+id/button7"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_bias="0.478"
- app:layout_constraintStart_toStartOf="parent" />
- <Button
- android:id="@+id/pinglatency"
- android:layout_width="182dp"
- android:layout_height="42dp"
- android:layout_marginBottom="308dp"
- android:text="Ping"
- app:layout_constraintBottom_toBottomOf="parent"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintHorizontal_bias="0.471"
- app:layout_constraintStart_toStartOf="parent" />
- <TextView
- android:id="@+id/textView"
- android:layout_width="371dp"
- android:layout_height="52dp"
- android:text="Prioritize Latency"
- tools:layout_editor_absoluteX="21dp"
- tools:layout_editor_absoluteY="1dp" />
-</androidx.constraintlayout.widget.ConstraintLayout>
- </FrameLayout>
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/frameLayout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".PrioritizeLatency">
+ <Button
+ android:id="@+id/purchaseButton"
+ android:layout_width="233dp"
+ android:layout_height="50dp"
+ android:layout_marginTop="176dp"
+ android:text="@string/purchase"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.495"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintVertical_bias="0.717" />
+ <Button
+ android:id="@+id/requestReleaseButton"
+ android:layout_width="183dp"
+ android:layout_height="50dp"
+ android:layout_marginTop="84dp"
+ android:text="@string/request_network"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/purchaseButton"
+ app:layout_constraintVertical_bias="0.717" />
+ <Button
+ android:id="@+id/pinglatency"
+ android:layout_width="182dp"
+ android:layout_height="42dp"
+ android:layout_marginBottom="92dp"
+ android:text="@string/ping"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintHorizontal_bias="0.493"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/requestReleaseButton" />
+ <TextView
+ android:id="@+id/resultTextView"
+ android:layout_width="283dp"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="84dp"
+ android:text="@string/result_prefix"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/pinglatency"
+ app:layout_constraintVertical_bias="0.717" />
+ <TextView
+ android:id="@+id/textView"
+ android:layout_width="371dp"
+ android:layout_height="52dp"
+ android:text="@string/latency_title"
+ tools:layout_editor_absoluteX="16dp"
+ tools:layout_editor_absoluteY="16dp" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
+ </FrameLayout>
</RelativeLayout>
\ No newline at end of file
diff --git a/testapps/TestSliceApp/app/src/main/res/values-af/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-af/strings.xml
index d172f0f..5e2a27f 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-af/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-af/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hallo leë fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Versoek netwerk"</string>
+ <string name="release_network" msgid="174252378593535238">"Stel netwerk vry"</string>
+ <string name="ping" msgid="7890607576220714932">"Pieng"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultaat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritiseer traagheid"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritiseer bandwydte"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Koop netwerkpremium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultaat: Die netwerk wat versoek is, is nou beskikbaar!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultaat: Die netwerk is versoek!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultaat: Die netwerk is vrygestel!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultaat: Kon nie die netwerk vrystel nie!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultaat: Uitsondering wanneer netwerkpremium gekoop word!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultaat: Het leë resultaat gekry toe netwerkpremium gekoop is!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultaat: Die netwerkpremium kan nie gekoop word nie!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultaat: Die netwerkpremium word tans gekoop …"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-am/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-am/strings.xml
index 229ff5d..ff5e8fa 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-am/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-am/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"አውታረ መረብ ይጠይቁ"</string>
+ <string name="release_network" msgid="174252378593535238">"አውታረ መረብ ይልቀቁ"</string>
+ <string name="ping" msgid="7890607576220714932">"ፒንግ"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ውጤት፦"</string>
+ <string name="latency_title" msgid="963052613947017009">"ለስርዓተ ምላሽ ጊዜ ቅድሚያ ይስጡ"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ለመተላለፊያ ይዘት ቅድሚያ ይስጡ"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"የአውታረ መረብ Premiumን ይግዙ"</string>
+ <string name="network_available" msgid="4780293262690730734">"ውጤት፦ የተጠየቀው አውታረ መረብ አሁን ይገኛል!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ውጤት፦ አውታረ መረቡ ተጠይቋል!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ውጤት፦ አውታረ መረቡ ተለቅቋል!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ውጤት፦ አውታረ መረቡን መልቀቅ አልተሳካም!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ውጤት፦የአውታረ መረብ premium በሚገዛበት ጊዜ ያለ ለየት ያለ!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ውጤት፦የአውታረ መረብ premium በሚገዛበት ጊዜ ባዶ ውጤት ተገኝቷል!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ውጤት፦የአውታረ መረቡ premium ለግዢ አይገኝም!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ውጤት፦ የአውታረ መረብ premium ግዢ በሂደት ላይ ነው ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ar/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ar/strings.xml
index 0cadb81..25fa479 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ar/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ar/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"جزء فارغ للترحيب"</string>
+ <string name="request_network" msgid="8945235490804849914">"طلب الشبكة"</string>
+ <string name="release_network" msgid="174252378593535238">"إطلاق الإصدار"</string>
+ <string name="ping" msgid="7890607576220714932">"فحص الاتصال"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"النتيجة:"</string>
+ <string name="latency_title" msgid="963052613947017009">"منح الأولوية لوقت الاستجابة"</string>
+ <string name="bw_title" msgid="3902162973688221344">"منح الأولوية لمعدّل نقل البيانات"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"شراء الاشتراك المميّز في الشبكة"</string>
+ <string name="network_available" msgid="4780293262690730734">"النتيجة: الشبكة المطلوبة متاحة الآن."</string>
+ <string name="network_requested" msgid="5646123922691865991">"النتيجة: تم طلب الشبكة."</string>
+ <string name="network_released" msgid="2992280481133877025">"النتيجة: تم إطلاق الشبكة."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"النتيجة: تعذَّر إطلاق الشبكة."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"النتيجة: حدث استثناء عند شراء اشتراك مميّز في الشبكة."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"النتيجة: لقد حصلْت على نتيجة فارغة عند شراء اشتراك مميّز في الشبكة."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"النتيجة: لا تتوفّر إمكانية شراء الاشتراك المميّز في الشبكة."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"النتيجة: عملية شراء الاشتراك المميّز في الشبكة جارية ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-as/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-as/strings.xml
index 229ff5d..350d8dd 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-as/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-as/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"নেটৱৰ্কৰ বাবে অনুৰোধ কৰক"</string>
+ <string name="release_network" msgid="174252378593535238">"নেটৱৰ্ক মুকলি কৰক"</string>
+ <string name="ping" msgid="7890607576220714932">"পিং"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ফলাফল:"</string>
+ <string name="latency_title" msgid="963052613947017009">"বিলম্বতাক অগ্ৰাধিকাৰ দিয়ক"</string>
+ <string name="bw_title" msgid="3902162973688221344">"বেণ্ডৱিথক অগ্ৰাধিকাৰ দিয়ক"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"নেটৱৰ্ক প্ৰিমিয়াম ক্ৰয় কৰক"</string>
+ <string name="network_available" msgid="4780293262690730734">"ফলাফল: অনুৰোধ কৰা নেটৱৰ্কটো বৰ্তমান উপলব্ধ নহয়!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ফলাফল: নেটৱৰ্কটোৰ বাবে অনুৰোধ কৰা হৈছে!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ফলাফল: নেটৱৰ্কটো মুকলি কৰি দিয়া হৈছে!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ফলাফল: নেটৱৰ্কটো মুকলি কৰি দিয়াত বিফল হৈছে!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ফলাফল: নেটৱৰ্ক প্ৰিমিয়াম ক্ৰয় কৰাৰ সময়ত ব্যতিক্ৰম!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ফলাফল: নেটৱৰ্ক প্ৰিমিয়াম ক্ৰয় কৰাৰ সময়ত খালী ফলাফল পোৱা গৈছে!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ফলাফল: ক্ৰয় কৰিবলৈ নেটৱৰ্ক প্ৰিমিয়াম উপলব্ধ নহয়!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ফলাফল: নেটৱৰ্ক প্ৰিমিয়াম ক্ৰয় কৰাৰ প্ৰক্ৰিয়া চলি আছে ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-az/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-az/strings.xml
index 3702d56..8d09fb9 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-az/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-az/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Boş salamlama fraqmenti"</string>
+ <string name="request_network" msgid="8945235490804849914">"Şəbəkə sorğusu göndərin"</string>
+ <string name="release_network" msgid="174252378593535238">"Şəbəkə ilə əlaqəni kəsin"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Nəticə:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Gecikməni prioritetləşdirin"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Ötürmə sürətini prioritetləşdirin"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Premium şəbəkə satın alın"</string>
+ <string name="network_available" msgid="4780293262690730734">"Nəticə: Tələb olunan şəbəkə indi əlçatandır!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Nəticə: Şəbəkə sorğusu göndərildi!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Nəticə: Şəbəkə ilə əlaqə kəsildi!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Nəticə: Şəbəkə ilə əlaqəni kəsmək alınmadı!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Nəticə: Premium şəbəkə satın alan zaman istisna baş verdi!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Nəticə: Premium şəbəkə satın alan zaman boş nəticə əldə edildi!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Nəticə: Premium şəbəkə satın almaq mümkün deyil!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Nəticə: Premium şəbəkə satın almaq prosesi davam edir ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-b+sr+Latn/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-b+sr+Latn/strings.xml
index 229ff5d..2ca99d3 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-b+sr+Latn/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-b+sr+Latn/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Zatražite mrežu"</string>
+ <string name="release_network" msgid="174252378593535238">"Objavite mrežu"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Rezultat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Dajte prioritet kašnjenju"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Dajte prioritet propusnom opsegu"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Kupite Premium mrežu"</string>
+ <string name="network_available" msgid="4780293262690730734">"Rezultat: Zahtevana mreža je trenutno dostupna!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Rezultat: Mreža je zatražena!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Rezultat: Mreža je objavljena!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Rezultat: Objavljivanje mreže nije uspelo!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Rezultat: Izuzetak pri kupovini Premium mreže!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Rezultat: Rezultat je prazan kada kupujete Premium mrežu!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Rezultat: Premium mreža nije dostupna za kupovinu!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Rezultat: Kupovina Premium mreže je u toku..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-be/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-be/strings.xml
index 385f84e..4b8a613 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-be/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-be/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Вітаем,"</string>
+ <string name="request_network" msgid="8945235490804849914">"Запытаць сетку"</string>
+ <string name="release_network" msgid="174252378593535238">"Вызваліць сетку"</string>
+ <string name="ping" msgid="7890607576220714932">"Пінг"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Вынік:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Аддаванне прыярытэту затрымцы"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Аддаванне прыярытэту паласе прапускання"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Купіць прэміяльную падпіску на выкарыстанне сеткі"</string>
+ <string name="network_available" msgid="4780293262690730734">"Вынік: запытаная сетка даступная!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Вынік: сетка запытана!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Вынік: сетка вызвалена!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Вынік: не ўдалося вызваліць сетку!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Вынік: пры спробе купіць прэміяльную падпіску на выкарыстанне сеткі ўзнікла выключэнне!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Вынік: пры спробе купіць прэміяльную падпіску на выкарыстанне сеткі атрыманы пусты вынік!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Вынік: прэміяльная падпіска на выкарыстанне сеткі недаступная для куплі!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Вынік: выконваецца купля прэміяльнай падпіскі на выкарыстанне сеткі..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-bg/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-bg/strings.xml
index 943a70d..b2951f9 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-bg/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-bg/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Здравей, празен фрагмент"</string>
+ <string name="request_network" msgid="8945235490804849914">"Заявка за мрежа"</string>
+ <string name="release_network" msgid="174252378593535238">"Освобождаване на мрежата"</string>
+ <string name="ping" msgid="7890607576220714932">"Команда ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Резултат:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Даване на приоритет на забавянето"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Даване на приоритет на пропускателната способност"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Купете Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Резултат: Заявената мрежа е достъпна сега!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Резултат: Мрежата е заявена!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Резултат: Мрежата е освободена!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Резултат: Мрежата не бе освободена!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Резултат: Изключение при покупка на Network Premium!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Резултат: При покупката на Network Premium получихте празен резултат."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Резултат: Network Premium не е налице за покупка!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Резултат: Network Premium се купува..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-bn/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-bn/strings.xml
index 229ff5d..5280d16 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-bn/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-bn/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Network সংক্রান্ত অনুরোধ করুন"</string>
+ <string name="release_network" msgid="174252378593535238">"Network রিলিজ করুন"</string>
+ <string name="ping" msgid="7890607576220714932">"পিং"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ফলাফল:"</string>
+ <string name="latency_title" msgid="963052613947017009">"লেটেন্সিকে অগ্রাধিকার দিন"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ব্যান্ডউইথকে অগ্রাধিকার দিন"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Network Premium কিনুন"</string>
+ <string name="network_available" msgid="4780293262690730734">"ফলাফল: অনুরোধ করা নেটওয়ার্ক এখন উপলভ্য আছে!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ফলাফল: নেটওয়ার্কের জন্য অনুরোধ জানানো হয়েছে!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ফলাফলt: নেটওয়ার্ক রিলিজ করা হয়েছে!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ফলাফল: নেটওয়ার্ক রিলিজ করা যায়নি!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ফলাফল: Network Premium কেনার সময় ব্যতিক্রম!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ফলাফল: Network Premium কেনার সময় কোনও ফলাফল পাওয়া যায়নি!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ফলাফল: Network Premium কেনার জন্য উপলভ্য নেই!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ফলাফল: Network Premium কেনার প্রক্রিয়া চলছে ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-bs/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-bs/strings.xml
index 229ff5d..e2ea203 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-bs/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-bs/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Zatraži mrežu"</string>
+ <string name="release_network" msgid="174252378593535238">"Otključaj mrežu"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Rezultat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Dodijeli prioritet latentnosti"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Dodijeli prioritet propusnosti"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Kupite premium verziju mreže"</string>
+ <string name="network_available" msgid="4780293262690730734">"Rezultat: zatražena mreža je sada dostupna."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Rezultat: mreža je zatražena."</string>
+ <string name="network_released" msgid="2992280481133877025">"Rezultat: mreža je otključana."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Rezultat: otključavanje mreže nije uspjelo."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Rezultat: izuzetak prilikom kupovine premium verzije mreže."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Rezultat: dobijen je prazan rezultat prilikom kupovine premium verzije mreže."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Rezultat: premium verzija mreže nije dostupna za kupovinu."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Rezultat: kupovina premium verzije mreže je u toku…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ca/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ca/strings.xml
index 9799d39..05529e3 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ca/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ca/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Fragment de benvinguda en blanc"</string>
+ <string name="request_network" msgid="8945235490804849914">"Sol·licita la xarxa"</string>
+ <string name="release_network" msgid="174252378593535238">"Allibera la xarxa"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritza la latència"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritza l\'amplada de banda"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Compra la xarxa prèmium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultat: la xarxa sol·licitada ja està disponible."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultat: s\'ha sol·licitat la xarxa."</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultat: s\'ha alliberat la xarxa."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultat: no s\'ha pogut alliberar la xarxa."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultat: s\'ha produït una excepció en comprar la xarxa prèmium."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultat: s\'ha obtingut un resultat buit en comprar la xarxa prèmium."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultat: la xarxa prèmium no es pot comprar."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultat: la compra de la xarxa prèmium està en curs..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-cs/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-cs/strings.xml
index 793ab6f..d25f77d 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-cs/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-cs/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Prázdný fragment pro pozdrav"</string>
+ <string name="request_network" msgid="8945235490804849914">"Odeslat požadavek na síť"</string>
+ <string name="release_network" msgid="174252378593535238">"Uvolnit síť"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Výsledek:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Upřednostnit latenci"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Upřednostnit rychlost připojení"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Pořiďte si bonus k síti"</string>
+ <string name="network_available" msgid="4780293262690730734">"Výsledek: Požadovaná síť je teď dostupná."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Výsledek: Byl odeslán požadavek na síť."</string>
+ <string name="network_released" msgid="2992280481133877025">"Výsledek: Síť byla uvolněna."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Výsledek: Síť se nepodařilo uvolnit."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Výsledek: Výjimka při nákupu bonusu k síti."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Výsledek: Při nákupu bonusu k síti se vrátil prázdný výsledek."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Výsledek: Bonus k síti není k prodeji."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Výsledek: Probíhá nákup bonusu k síti…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-da/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-da/strings.xml
index 229ff5d..6e074c2 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-da/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-da/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Anmod om tv-kanal"</string>
+ <string name="release_network" msgid="174252378593535238">"Udgiv tv-kanal"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioriter forsinkelse"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioriter båndbredde"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Køb Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultat: Den tv-kanal, der blev anmodet om, er tilgængelig nu!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultat: Der blev anmodet om tv-kanalen!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultat: Tv-kanalen er blevet udgivet!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultat: Tv-kanalen kunne ikke udgives!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultat: Undtagen, når du køber Network Premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultat: Der blev vist et tomt resultat ved køb af Network Premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultat: Network Premium kan ikke købes!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultat: Købet af Network Premium er i gang…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-de/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-de/strings.xml
index 229ff5d..4ff4b5f 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-de/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-de/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Netzwerk anfragen"</string>
+ <string name="release_network" msgid="174252378593535238">"Netzwerk freigeben"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Ergebnis:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Latenz priorisieren"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Bandbreite priorisieren"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Premium-Netzwerk erwerben"</string>
+ <string name="network_available" msgid="4780293262690730734">"Ergebnis: Das gewünschte Netzwerk ist jetzt verfügbar."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Ergebnis: Das Netzwerk wurde angefordert."</string>
+ <string name="network_released" msgid="2992280481133877025">"Ergebnis: Das Netzwerk wurde freigegeben."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Ergebnis: Netzwerk konnte nicht freigegeben werden."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Ergebnis: Ausnahme beim Kauf des Premium-Netzwerks."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Ergebnis: Beim Kauf des Premium-Netzwerks wurde ein leeres Ergebnis zurückgegeben."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Ergebnis: Premium-Netzwerk kann nicht erworben werden."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Ergebnis: Der Kauf des Premium-Netzwerks läuft..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-el/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-el/strings.xml
index 229ff5d..0d39d8b 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-el/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-el/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Υποβολή αιτήματος για δίκτυο"</string>
+ <string name="release_network" msgid="174252378593535238">"Κυκλοφορία δικτύου"</string>
+ <string name="ping" msgid="7890607576220714932">"Εφαρμογή Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Αποτέλεσμα:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Προτεραιότητα λανθάνοντος χρόνου"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Προτεραιότητα εύρους ζώνης"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Αγορά επιπλέον χρέωσης δικτύου"</string>
+ <string name="network_available" msgid="4780293262690730734">"Αποτέλεσμα: Το δίκτυο που ζητήθηκε είναι πλέον διαθέσιμο!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Αποτέλεσμα: Υποβλήθηκε αίτημα για το δίκτυο!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Αποτέλεσμα: Το δίκτυο κυκλοφόρησε!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Αποτέλεσμα: Αποτυχία κυκλοφορίας του δικτύου!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Αποτέλεσμα: Εξαίρεση κατά την αγορά δικτύου με επιπλέον χρέωση!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Αποτέλεσμα: Εμφανίστηκε κενό αποτέλεσμα κατά την αγορά δικτύου με επιπλέον χρέωση!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Αποτέλεσμα: Η επιπλέον χρέωση του δικτύου δεν είναι διαθέσιμη για αγορά!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Αποτέλεσμα: Η αγορά δικτύου με επιπλέον χρέωση βρίσκεται σε εξέλιξη …"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-en-rAU/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-en-rAU/strings.xml
index 229ff5d..fbb98d6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-en-rAU/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-en-rAU/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritise latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritise bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase network premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-en-rCA/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-en-rCA/strings.xml
index 229ff5d..a5c81f6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-en-rCA/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-en-rCA/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-en-rGB/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-en-rGB/strings.xml
index 229ff5d..fbb98d6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-en-rGB/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-en-rGB/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritise latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritise bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase network premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-en-rIN/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-en-rIN/strings.xml
index 229ff5d..fbb98d6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-en-rIN/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-en-rIN/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritise latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritise bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase network premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-en-rXC/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-en-rXC/strings.xml
index dafc7d2..a24b28a 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-en-rXC/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-en-rXC/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-es-rUS/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-es-rUS/strings.xml
index 229ff5d..39b1338 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-es-rUS/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-es-rUS/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Solicitar red"</string>
+ <string name="release_network" msgid="174252378593535238">"Publicar red"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultado:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioriza la latencia"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioriza el ancho de banda"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Comprar red premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultado: Ya está disponible la red solicitada."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultado: Se solicitó la red."</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultado: Se liberó la red."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultado: No se pudo liberar la red."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultado: Excepción cuando se compra la red premium."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultado: Se obtuvo un resultado vacío durante la compra de la red premium."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultado: La red premium no está disponible para comprarse."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultado: La compra de la red premium está en curso…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-es/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-es/strings.xml
index 355b912..8f46501 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-es/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-es/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hola, (segmento en blanco):"</string>
+ <string name="request_network" msgid="8945235490804849914">"Solicitar red"</string>
+ <string name="release_network" msgid="174252378593535238">"Lanzar red"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultado:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Priorizar latencia"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Priorizar ancho de banda"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Comprar red premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultado: la red solicitada ya está disponible."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultado: se ha solicitado la red."</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultado: la red se ha lanzado."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultado: no se ha podido lanzar la red."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultado: excepción al comprar la red premium."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultado: se ha obtenido un resultado vacío al comprar la red premium."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultado: no se puede comprar la red premium."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultado: la compra de la red premium está en curso..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-et/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-et/strings.xml
index 229ff5d..f5ff262 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-et/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-et/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Kõll"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Tulemus:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-eu/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-eu/strings.xml
index 229ff5d..ce566a1 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-eu/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-eu/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Eskatu sarea"</string>
+ <string name="release_network" msgid="174252378593535238">"Askatu sarea"</string>
+ <string name="ping" msgid="7890607576220714932">"Egin ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Emaitza:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Eman lehentasuna latentziari"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Eman lehentasuna banda-zabalerari"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Erosi sarearen premium bertsioa"</string>
+ <string name="network_available" msgid="4780293262690730734">"Emaitza: eskatutako sarea erabilgarri dago orain!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Emaitza: eskatu da sarea!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Emaitza: askatu da sarea!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Emaitza: ezin izan da askatu sarea!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Emaitza: salbuespena sarearen premium bertsioa erostean!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Emaitza: hutsik dauden emaitzak lortu dira sarearen premium bertsioa erostean!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Emaitza: ezin da erosi sarearen premium bertsioa!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Emaitza: abian da sarearen premium bertsioa erosteko prozesua…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-fa/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-fa/strings.xml
index 6f35108..5a51eaa 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-fa/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-fa/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"سلام بخش خالی"</string>
+ <string name="request_network" msgid="8945235490804849914">"درخواست شبکه"</string>
+ <string name="release_network" msgid="174252378593535238">"انتشار شبکه"</string>
+ <string name="ping" msgid="7890607576220714932">"پینگ"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"نتیجه:"</string>
+ <string name="latency_title" msgid="963052613947017009">"اولویتبندی تأخیر"</string>
+ <string name="bw_title" msgid="3902162973688221344">"اولویتبندی پهنای باند"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"خرید حساب ممتاز شبکه"</string>
+ <string name="network_available" msgid="4780293262690730734">"نتیجه: شبکه درخواستشده اکنون دردسترس است!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"نتیجه: شبکه درخواست شد!"</string>
+ <string name="network_released" msgid="2992280481133877025">"نتیجه: شبکه منتشر شد!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"نتیجه: شبکه منتشر نشد!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"نتیجه: هنگام خرید حساب ممتاز شبکهْ استثنائی پیش میآید!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"نتیجه: هنگام تلاش برای خرید حساب ممتاز شبکه نتیجه خالی برگردانده میشود!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"نتیجه: حساب ممتاز شبکه برای خرید دردسترس نیست!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"نتیجه: خرید حساب ممتاز شبکه درحال انجام است…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-fi/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-fi/strings.xml
index 229ff5d..df8ce6b 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-fi/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-fi/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Pyydä verkkoa"</string>
+ <string name="release_network" msgid="174252378593535238">"Vapauta verkko"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Tulos:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Priorisoi viive"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Priorisoi kaistanleveys"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Osta Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Tulos: Pyydetty verkko on nyt käytettävissä!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Tulos: Verkkoa on pyydetty!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Tulos: Verkko on vapautettu!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Tulos: Verkon vapautus epäonnistui!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Tulos: Poikkeus Network Premiumia ostettaessa!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Tulos: Tyhjä tulos Network Premiumia ostettaessa!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Tulos: Network Premium ei ole ostettavissa!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Tulos: Network Premiumin osto on käynnissä..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-fr-rCA/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-fr-rCA/strings.xml
index 229ff5d..70a891b 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-fr-rCA/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-fr-rCA/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Réseau de demande"</string>
+ <string name="release_network" msgid="174252378593535238">"Réseau de diffusion"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Résultat :"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioriser la latence"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioriser la bande passante"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Acheter le réseau Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Résultat : Le réseau demandé est maintenant disponible!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Résultat : Le réseau a été demandé!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Résultat : Le réseau est publié!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Résultat : Échec de la publication du réseau!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Résultat : Exception lors de l\'achat du réseau premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Résultat : Aucun résultat lors de l\'achat du réseau Premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Résultat : Le réseau Premium n\'est pas offert à l\'achat!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Résultat : L\'achat du réseau Premium est en cours…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-fr/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-fr/strings.xml
index e9b3b45..96d996b 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-fr/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-fr/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Bonjour fragment vierge"</string>
+ <string name="request_network" msgid="8945235490804849914">"Demander le réseau"</string>
+ <string name="release_network" msgid="174252378593535238">"Libérer le réseau"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Résultat :"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioriser la latence"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioriser la bande passante"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Souscrire au réseau premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Résultat : le réseau demandé est disponible."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Résultat : le réseau a été demandé."</string>
+ <string name="network_released" msgid="2992280481133877025">"Résultat : le réseau a été libéré."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Résultat : échec de la libération du réseau."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Résultat : une exception s\'est produite lors de la souscription au réseau premium."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Résultat : un résultat vide s\'est affiché lors de la souscription au réseau premium."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Résultat : le réseau premium n\'est pas disponible à l\'achat."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Résultat : la souscription au réseau premium est en cours…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-gl/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-gl/strings.xml
index 229ff5d..c505b21 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-gl/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-gl/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Solicitar rede"</string>
+ <string name="release_network" msgid="174252378593535238">"Liberar rede"</string>
+ <string name="ping" msgid="7890607576220714932">"Facer ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultado:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Darlle prioridade á latencia"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Darlle prioridade á largura de banda"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Comprar rede premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultado: A rede solicitada está dispoñible neste momento"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultado: Solicitouse a rede"</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultado: Liberouse a rede"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultado: Produciuse un erro ao liberar a rede"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultado: Excepción ao comprar a rede premium"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultado: Recibiuse un resultado baleiro ao comprar a rede premium"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultado: A rede premium non está á venda"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultado: A compra da rede premium está en curso…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-gu/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-gu/strings.xml
index 229ff5d..675ac46 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-gu/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-gu/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"નેટવર્કની વિનંતી કરો"</string>
+ <string name="release_network" msgid="174252378593535238">"નેટવર્ક રિલીઝ કરો"</string>
+ <string name="ping" msgid="7890607576220714932">"પિંગ"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"પરિણામ:"</string>
+ <string name="latency_title" msgid="963052613947017009">"વિલંબતાને પ્રાધાન્યતા આપો"</string>
+ <string name="bw_title" msgid="3902162973688221344">"બૅન્ડવિડ્થને પ્રાધાન્યતા આપો"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Network Premium ખરીદો"</string>
+ <string name="network_available" msgid="4780293262690730734">"પરિણામ: વિનંતી કરવામાં આવેલું નેટવર્ક હવે ઉપલબ્ધ છે!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"પરિણામ: નેટવર્કની વિનંતી કરવામાં આવી છે!"</string>
+ <string name="network_released" msgid="2992280481133877025">"પરિણામ: નેટવર્ક રિલીઝ કરવામાં આવ્યું છે!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"પરિણામ: નેટવર્ક રિલીઝ કરવામાં નિષ્ફળ રહ્યાં!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"પરિણામ: network premium ખરીદતી વખતે અપવાદ!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"પરિણામ: network premium ખરીદતી વખતે ખાલી પરિણામ મળ્યું!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"પરિણામ: ખરીદી કરવા માટે network premium ઉપલબ્ધ નથી!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"પરિણામ: network premiumની ખરીદીની પ્રક્રિયા ચાલુ છે ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-hi/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-hi/strings.xml
index 229ff5d..0f13f68 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-hi/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-hi/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"नेटवर्क का अनुरोध करें"</string>
+ <string name="release_network" msgid="174252378593535238">"नेटवर्क रिलीज़ करें"</string>
+ <string name="ping" msgid="7890607576220714932">"पिंग करें"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"नतीजा:"</string>
+ <string name="latency_title" msgid="963052613947017009">"इंतज़ार के समय को प्राथमिकता दें"</string>
+ <string name="bw_title" msgid="3902162973688221344">"बैंडविड्थ को प्राथमिकता दें"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"नेटवर्क प्रीमियम खरीदें"</string>
+ <string name="network_available" msgid="4780293262690730734">"नतीजा: अनुरोध किया गया नेटवर्क अब उपलब्ध है!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"नतीजा: नेटवर्क के लिए अनुरोध किया गया है!"</string>
+ <string name="network_released" msgid="2992280481133877025">"नतीजा: नेटवर्क रिलीज़ हो गया है!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"नतीजा: नेटवर्क रिलीज़ नहीं किया जा सका!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"नतीजा: नेटवर्क प्रीमियम खरीदते समय अपवाद!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"नतीजा: नेटवर्क प्रीमियम खरीदते समय खाली नतीजा मिला!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"नतीजा: नेटवर्क प्रीमियम खरीदारी के लिए उपलब्ध नहीं है!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"नतीजा: नेटवर्क प्रीमियम खरीदारी चल रही है ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-hr/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-hr/strings.xml
index 229ff5d..dd4f3f5 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-hr/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-hr/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Zahtjev za mrežu"</string>
+ <string name="release_network" msgid="174252378593535238">"Otkazivanje mreže"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Rezultat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prednost ima latencija"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prednost ima propusnost"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Kupnja premium sadržaja mreže"</string>
+ <string name="network_available" msgid="4780293262690730734">"Rezultat: zatražena mreža sada je dostupna!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Rezultat: mreža je zatražena!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Rezultat: mreža je otkazana!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Rezultat: otkazivanje mreže nije uspjelo!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Rezultat: iznimka pri kupnji premium sadržaja mreže!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Rezultat: dobiven je prazni rezultat pri kupnji premium sadržaja mreže!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Rezultat: premium sadržaj mreže nije dostupan za kupnju!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Rezultat: u tijeku je kupnja premium sadržaja mreže..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-hu/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-hu/strings.xml
index 0e73dba..524b271 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-hu/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-hu/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Üres üdvözlő rész"</string>
+ <string name="request_network" msgid="8945235490804849914">"Hálózat kérése"</string>
+ <string name="release_network" msgid="174252378593535238">"Hálózat felszabadítása"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Eredmény:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Várakozási idő előnyben"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Sávszélesség előnyben"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"A hálózati prémium megvásárlása"</string>
+ <string name="network_available" msgid="4780293262690730734">"Eredmény: A kért hálózat már rendelkezésre áll."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Eredmény: A hálózat igénylése megtörtént."</string>
+ <string name="network_released" msgid="2992280481133877025">"Eredmény: A hálózat felszabadult."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Eredmény: Nem sikerült felszabadítani a hálózatot."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Eredmény: Kivétel a hálózati prémium megvásárlásakor."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Eredmény: Üres eredmény érkezett vissza a hálózati prémium megvásárlásakor."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Eredmény: A hálózati prémium nem vásárolható meg."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Eredmény: A hálózati prémium megvásárlása folyamatban van..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-hy/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-hy/strings.xml
index 31a60c6..77ef65f 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-hy/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-hy/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Դատարկ հատված"</string>
+ <string name="request_network" msgid="8945235490804849914">"Ցանցն ազատելու հայտ ուղարկել"</string>
+ <string name="release_network" msgid="174252378593535238">"Ազատել ցանցը"</string>
+ <string name="ping" msgid="7890607576220714932">"Փինգ"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Արդյունքը՝"</string>
+ <string name="latency_title" msgid="963052613947017009">"Առաջնահերթություն տալ հապաղմանը"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Առաջնահերթություն տալ թողունակությանը"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Գնել ցանցի օգտագործման պրեմիում բաժանորդագրություն"</string>
+ <string name="network_available" msgid="4780293262690730734">"Արդյունքը՝ պահանջվող ցանցն այժմ հասանելի է։"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Արդյունքը՝ ցանցն ազատելու հայտն ուղարկվեց։"</string>
+ <string name="network_released" msgid="2992280481133877025">"Արդյունքը՝ ցանցն ազատվեց։"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Արդյունքը՝ չհաջողվեց ազատել ցանցը։"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Արդյունքը՝ ցանցի օգտագործման պրեմիում բաժանորդագրություն գնելու փորձի ժամանակ բացառություն է առաջացել։"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Արդյունքը՝ ցանցի օգտագործման պրեմիում բաժանորդագրություն գնելու փորձի ժամանակ ստացվել է դատարկ արդյունք։"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Արդյունքը՝ ցանցի օգտագործման պրեմիում բաժանորդագրությունը հասանելի չէ գնման համար։"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Արդյունքը՝ կատարվում է ցանցի օգտագործման պրեմիում բաժանորդագրության գնում ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-in/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-in/strings.xml
index 229ff5d..9e1aa19 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-in/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-in/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Meminta Jaringan"</string>
+ <string name="release_network" msgid="174252378593535238">"Melepaskan Jaringan"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Hasil:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Memprioritaskan Latensi"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Memprioritaskan Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Membeli Jaringan Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Hasil: Jaringan yang diminta kini tersedia."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Hasil: Jaringan telah diminta."</string>
+ <string name="network_released" msgid="2992280481133877025">"Hasil: Jaringan telah dilepas."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Hasil: Gagal melepaskan jaringan."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Hasil: Pengecualian saat membeli jaringan premium."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Hasil: Mendapatkan hasil kosong saat membeli jaringan premium."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Hasil: Jaringan premium tidak dapat dibeli."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Hasil: Pembelian jaringan premium sedang berlangsung."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-is/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-is/strings.xml
index 229ff5d..61772de 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-is/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-is/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Biðja um netkerfi"</string>
+ <string name="release_network" msgid="174252378593535238">"Gefa út netkerfi"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping-prófun"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Niðurstaða:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Forgangsraða biðtíma"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Forgangsraða bandvídd"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Kaupa úrvalsnetkerfi"</string>
+ <string name="network_available" msgid="4780293262690730734">"Niðurstaða: Netkerfið sem beðið var um er nú í boði!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Niðurstaða: Beiðni um netkerfið hefur verið send!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Niðurstaða: Útgáfa netkerfisins tókst!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Niðurstaða: Ekki tókst að gefa netkerfið út!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Niðurstaða: Undantekning við kaup á úrvalsnetkerfi!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Niðurstaða: Fékk tóma niðurstöðu við kaup á úrvalsnetkerfi!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Niðurstaða: Það er ekki hægt að kaupa úrvalsnetkerfið!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Niðurstaða: Kaup á úrvalsnetkerfi eru í vinnslu..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-it/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-it/strings.xml
index 229ff5d..0c7b5f0 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-it/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-it/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Risultato: la rete è stata richiesta."</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-iw/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-iw/strings.xml
index 4287a40..243e2c0 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-iw/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-iw/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"שלום קטע ריק"</string>
+ <string name="request_network" msgid="8945235490804849914">"שליחת בקשה לרשת"</string>
+ <string name="release_network" msgid="174252378593535238">"שחרור הרשת"</string>
+ <string name="ping" msgid="7890607576220714932">"פינג"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"תוצאה:"</string>
+ <string name="latency_title" msgid="963052613947017009">"עדיפות לזמן האחזור"</string>
+ <string name="bw_title" msgid="3902162973688221344">"עדיפות לרוחב הפס"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"רכישת רשת פרימיום"</string>
+ <string name="network_available" msgid="4780293262690730734">"תוצאה: הרשת המבוקשת זמינה"</string>
+ <string name="network_requested" msgid="5646123922691865991">"תוצאה: הבקשה לרשת נשלחה"</string>
+ <string name="network_released" msgid="2992280481133877025">"תוצאה: הרשת שוחררה"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"תוצאה: הרשת לא שוחררה"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"תוצאה: חריגה ברכישת פרמיה לרשת"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"תוצאה: התקבלה תוצאה ריקה בניסיון לרכוש פרמיה לרשת"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"תוצאה: אי אפשר לרכוש את הפרמיה לרשת"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"תוצאה: רכישת פרמיה לרשת מתבצעת…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ja/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ja/strings.xml
index 229ff5d..a265867 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ja/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ja/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"ネットワークをリクエストする"</string>
+ <string name="release_network" msgid="174252378593535238">"ネットワークを解放する"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"結果:"</string>
+ <string name="latency_title" msgid="963052613947017009">"レイテンシを優先する"</string>
+ <string name="bw_title" msgid="3902162973688221344">"帯域幅を優先する"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"ネットワーク プレミアムを購入"</string>
+ <string name="network_available" msgid="4780293262690730734">"結果: リクエストされたネットワークが利用できるようになりました。"</string>
+ <string name="network_requested" msgid="5646123922691865991">"結果: ネットワークがリクエストされました。"</string>
+ <string name="network_released" msgid="2992280481133877025">"結果: ネットワークが解放されました。"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"結果: ネットワークを解放できませんでした。"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"結果: ネットワーク プレミアム購入時に例外が発生しました。"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"結果: ネットワーク プレミアムの購入時に空の結果が返されました。"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"結果: ネットワーク プレミアムを購入できません。"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"結果: ネットワーク プレミアムの購入処理中です。"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ka/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ka/strings.xml
index 8d91ed0..1543a21 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ka/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ka/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"მოგესალმებით, ეს ცარიელი ფრაგმენტია"</string>
+ <string name="request_network" msgid="8945235490804849914">"მოთხოვნილი ქსელი"</string>
+ <string name="release_network" msgid="174252378593535238">"გამოშვების ქსელი"</string>
+ <string name="ping" msgid="7890607576220714932">"ზუზუნი"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"შედეგი:"</string>
+ <string name="latency_title" msgid="963052613947017009">"უპირატესობა მიანიჭეთ რეაგირების დროს"</string>
+ <string name="bw_title" msgid="3902162973688221344">"პრიორიტეტული გამტარუნარიანობა"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"შეიძინეთ ქსელის პრემიუმი"</string>
+ <string name="network_available" msgid="4780293262690730734">"შედეგი: მოთხოვნილი ქსელი უკვე ხელმისაწვდომია!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"შედეგი: ქსელი მოთხოვნილია!"</string>
+ <string name="network_released" msgid="2992280481133877025">"შედეგი: ქსელი გათავისუფლდა!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"შედეგი: ქსელის გათავისუფლება ვერ მოხერხდა"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"შედეგი: გამონაკლისი ქსელის პრემიუმის შეძენისას!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"შედეგი: მიიღეთ ცარიელი შედეგი ქსელის პრემიუმის შეძენისას!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"შედეგი: ქსელის პრემია არ არის ხელმისაწვდომი შესაძენად!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"შედეგი:მიმდინარეობს ქსელის პრემიუმ შესყიდვა ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-kk/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-kk/strings.xml
index 229ff5d..1dac729 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-kk/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-kk/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Желіні сұрау"</string>
+ <string name="release_network" msgid="174252378593535238">"Желіні шығару"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Нәтиже:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Кідіріске басымдық беру"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Өткізу мүмкіндігіне басымдық беру"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Премиум желіні сатып алу"</string>
+ <string name="network_available" msgid="4780293262690730734">"Нәтиже: сұралған желіні қазір пайдалануға болады!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Нәтиже: желі сұралды!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Нәтиже: желі шығарылды!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Нәтиже: желі шығарылмады!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Нәтиже: премиум желіні сатып алу кезінде ерекше жағдай шықты!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Нәтиже: премиум желіні сатып алу кезінде бос нәтиже шықты!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Нәтиже: премиум желіні сатып алу мүмкін емес!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Нәтиже: премиум желіні сатып алу процесі жүріп жатыр…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-km/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-km/strings.xml
index 229ff5d..1c4002a 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-km/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-km/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"ស្នើសុំបណ្ដាញ"</string>
+ <string name="release_network" msgid="174252378593535238">"ដកបណ្ដាញចេញ"</string>
+ <string name="ping" msgid="7890607576220714932">"ភីង"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"លទ្ធផល៖"</string>
+ <string name="latency_title" msgid="963052613947017009">"ផ្ដល់អាទិភាពការពន្យារ"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ផ្ដល់អាទិភាពកម្រិតបញ្ជូន"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"ទិញបណ្ដាញលំដាប់ខ្ពស់"</string>
+ <string name="network_available" msgid="4780293262690730734">"លទ្ធផល៖ ឥឡូវនេះអាចប្រើបណ្ដាញដែលបានស្នើសុំបានហើយ!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"លទ្ធផល៖ បានស្នើសុំបណ្ដាញ!"</string>
+ <string name="network_released" msgid="2992280481133877025">"លទ្ធផល៖ បានដកបណ្ដាញចេញ!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"លទ្ធផល៖ ការលើកលែង នៅពេលទិញបណ្ដាញលំដាប់ខ្ពស់!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"លទ្ធផល៖ ការទិញបណ្ដាញលំដាប់ខ្ពស់កំពុងដំណើរការ ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-kn/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-kn/strings.xml
index 13a202b..1c06a91 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-kn/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-kn/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"ಹಲೋ, ಖಾಲಿ ಫ್ರಾಗ್ಮೆಂಟ್"</string>
+ <string name="request_network" msgid="8945235490804849914">"ನೆಟ್ವರ್ಕ್ಗಾಗಿ ವಿನಂತಿಸಿ"</string>
+ <string name="release_network" msgid="174252378593535238">"ನೆಟ್ವರ್ಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡಿ"</string>
+ <string name="ping" msgid="7890607576220714932">"ಪಿಂಗ್"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ಫಲಿತಾಂಶ:"</string>
+ <string name="latency_title" msgid="963052613947017009">"ವಿಳಂಬವನ್ನು ಆದ್ಯತೆಗೊಳಿಸಿ"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ಬ್ಯಾಂಡ್ವಿಡ್ತ್ ಆದ್ಯತೆಗೊಳಿಸಿ"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"ನೆಟ್ವರ್ಕ್ ಪ್ರೀಮಿಯಂ ಖರೀದಿಸಿ"</string>
+ <string name="network_available" msgid="4780293262690730734">"ಫಲಿತಾಂಶ: ವಿನಂತಿಸಿದ ನೆಟ್ವರ್ಕ್ ಈಗ ಲಭ್ಯವಿದೆ!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ಫಲಿತಾಂಶ: ನೆಟ್ವರ್ಕ್ಗಾಗಿ ವಿನಂತಿಸಲಾಗಿದೆ!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ಫಲಿತಾಂಶ: ನೆಟ್ವರ್ಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲಾಗಿದೆ!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ಫಲಿತಾಂಶ: ನೆಟ್ವರ್ಕ್ ಅನ್ನು ಬಿಡುಗಡೆ ಮಾಡಲು ವಿಫಲವಾಗಿದೆ!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ಫಲಿತಾಂಶ: ನೆಟ್ವರ್ಕ್ ಪ್ರೀಮಿಯಂ ಅನ್ನು ಖರೀದಿಸುವಾಗ ದೊರೆಯುವ ವಿನಾಯಿತಿ!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ಫಲಿತಾಂಶ: ನೆಟ್ವರ್ಕ್ ಪ್ರೀಮಿಯಂ ಅನ್ನು ಖರೀದಿಸುವಾಗ ಫಲಿತಾಂಶವು ದೊರೆತಿಲ್ಲ!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ಫಲಿತಾಂಶ: ನೆಟ್ವರ್ಕ್ ಪ್ರೀಮಿಯಂ ಖರೀದಿಗೆ ಲಭ್ಯವಿಲ್ಲ!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ಫಲಿತಾಂಶ: ನೆಟ್ವರ್ಕ್ ಪ್ರೀಮಿಯಂ ಖರೀದಿ ಪ್ರಕ್ರಿಯೆ ಪ್ರಗತಿಯಲ್ಲಿದೆ ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ko/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ko/strings.xml
index 229ff5d..78199c8 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ko/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ko/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"네트워크 요청"</string>
+ <string name="release_network" msgid="174252378593535238">"네트워크 해제"</string>
+ <string name="ping" msgid="7890607576220714932">"핑"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"결과:"</string>
+ <string name="latency_title" msgid="963052613947017009">"지연 시간 우선순위 지정"</string>
+ <string name="bw_title" msgid="3902162973688221344">"대역폭의 우선순위 지정"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Network Premium 구매"</string>
+ <string name="network_available" msgid="4780293262690730734">"결과: 요청된 네트워크를 지금 사용할 수 있습니다."</string>
+ <string name="network_requested" msgid="5646123922691865991">"결과: 네트워크가 요청되었습니다."</string>
+ <string name="network_released" msgid="2992280481133877025">"결과: 네트워크가 해제되었습니다."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"결과: 네트워크 해제에 실패했습니다."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"결과: 네트워크 프리미엄 구매 시 예외 발생"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"결과: 네트워크 프리미엄을 구매할 때 결과가 비어 있습니다."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"결과: 네트워크 프리미엄을 구매할 수 없습니다."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"결과: 네트워크 프리미엄 구매가 진행 중입니다."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ky/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ky/strings.xml
index 229ff5d..8e9fd3d 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ky/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ky/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Тармак сурамы"</string>
+ <string name="release_network" msgid="174252378593535238">"Тармакты артка кайтаруу"</string>
+ <string name="ping" msgid="7890607576220714932">"Хрусталь"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Натыйжа:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Күтүү убакытына артыкчылык берүү"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Өткөрүү жөндөмдүүлүгүнө артыкчылык берүү"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Премиум тармагын сатып алуу"</string>
+ <string name="network_available" msgid="4780293262690730734">"Натыйжа: Суралган тармак азыр жеткиликтүү."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Натыйжа: Тармак суралды."</string>
+ <string name="network_released" msgid="2992280481133877025">"Натыйжа: Тармак артка кайтарылды."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Натыйжа: Тармак артка кайтарылган жок."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Натыйжа: Премиум тармагын сатып алууда өзгөчө учур чыкты."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Натыйжа: Премиум тармагын сатып алууда жыйынтык көрсөтүлгөн жок."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Натыйжа: Премиум тармагы сатылбайт."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Натыйжа: Премиум тармагы сатылып алынууда."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-lo/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-lo/strings.xml
index 3d47ad6..03812e7 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-lo/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-lo/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"ສະບາຍດີຈຸດແຕກທີ່ຫວ່າງເປົ່າ"</string>
+ <string name="request_network" msgid="8945235490804849914">"ຮ້ອງຂໍເຄືອຂ່າຍ"</string>
+ <string name="release_network" msgid="174252378593535238">"ປ່ອຍເຄືອຂ່າຍ"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"ຈັດລຳດັບຄວາມສຳຄັນເວລາຕອບສະໜອງ"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ຈັດລຳດັບຄວາມສຳຄັນແບນວິດ"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"ຊື້ເຄືອຂ່າຍ Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"ຜົນຮັບ: ຕອນນີ້ເຄືອຂ່າຍທີ່ຮ້ອງຂໍໃຊ້ໄດ້ແລ້ວ!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-lt/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-lt/strings.xml
index 509fd2d..4d6c73e 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-lt/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-lt/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Sveiki, tuščias fragmentas"</string>
+ <string name="request_network" msgid="8945235490804849914">"Pateikti tinklo užklausą"</string>
+ <string name="release_network" msgid="174252378593535238">"Išleisti tinklą"</string>
+ <string name="ping" msgid="7890607576220714932">"Ryšio patikra"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Rezultatas:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Suteikti prioritetą delsai"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Suteikti prioritetą pralaidumui"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Įsigyti tinklą „Premium“"</string>
+ <string name="network_available" msgid="4780293262690730734">"Rezultatas: tinklas, dėl kurio pateikta užklausa, dabar pasiekiamas!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Rezultatas: pateikta tinklo užklausa!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Rezultatas: tinklas išleistas!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Rezultatas: nepavyko išleisti tinklo!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Rezultatas: išimtis įsigyjant tinklą „Premium“!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Rezultatas: gautas tuščias rezultatas įsigyjant tinklą „Premium“!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Rezultatas: tinklo „Premium“ negalima įsigyti!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Rezultatas: vykdomas tinklo „Premium“ įsigijimas..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-lv/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-lv/strings.xml
index 229ff5d..3f24cf5 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-lv/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-lv/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Pieprasīt tīklu"</string>
+ <string name="release_network" msgid="174252378593535238">"Atbrīvot tīklu"</string>
+ <string name="ping" msgid="7890607576220714932">"Ehotestēt"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Rezultāts:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritāte latentumam"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritāte joslas platumam"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Iegādāties tīkla maksas abonementu"</string>
+ <string name="network_available" msgid="4780293262690730734">"Rezultāts: pieprasītais tīkls tagad ir pieejams."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Rezultāts: tīkls ir pieprasīts."</string>
+ <string name="network_released" msgid="2992280481133877025">"Rezultāts: tīkls ir atbrīvots."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Rezultāts: neizdevās atbrīvot tīklu."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Rezultāts: iegādājoties tīkla maksas abonementu, radās izņēmums."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Rezultāts: iegādājoties tīkla maksas abonementu, tika iegūts tukšs rezultāts."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Rezultāts: tīkla maksas abonementu nevar iegādāties."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Rezultāts: notiek tīkla maksas abonementa iegāde…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-mk/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-mk/strings.xml
index 229ff5d..41c891f 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-mk/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-mk/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Побарајте мрежа"</string>
+ <string name="release_network" msgid="174252378593535238">"Исклучете мрежа"</string>
+ <string name="ping" msgid="7890607576220714932">"Пинг"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Резултат:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Купете премиум-мрежа"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Резултат: мрежата е побарана!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Резултат: мрежата е исклучена!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Резултат: исклучок при купување премиум-мрежа!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Резултат: се доби празен резултат при купување премиум-мрежа!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Резултат: премиум-мрежата не е достапна за купување!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Резултат: купувањето на премиум-мрежата е во тек …"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ml/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ml/strings.xml
index 47ca9c8..bc8e8c5 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ml/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ml/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"ഹലോ ബ്ലാങ്ക് ഫ്രാഗ്മെന്റ്"</string>
+ <string name="request_network" msgid="8945235490804849914">"ഒരു നെറ്റ്വർക്ക് അഭ്യർത്ഥിക്കുക"</string>
+ <string name="release_network" msgid="174252378593535238">"നെറ്റ്വർക്ക് റിലീസ് ചെയ്യുക"</string>
+ <string name="ping" msgid="7890607576220714932">"പിംഗ്"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ഫലം:"</string>
+ <string name="latency_title" msgid="963052613947017009">"പ്രതികരണ സമയത്തിന് മുൻഗണന നൽകുക"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ബാൻഡ്വിഡ്ത്തിന് മുൻഗണന നൽകുക"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"നെറ്റ്വർക്ക് പ്രീമിയം വാങ്ങുക"</string>
+ <string name="network_available" msgid="4780293262690730734">"ഫലം: അഭ്യർത്ഥിച്ച നെറ്റ്വർക്ക് ഇപ്പോൾ ലഭ്യമാണ്!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ഫലം: നെറ്റ്വർക്കിന് അഭ്യർത്ഥിച്ചു!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ഫലം: നെറ്റ്വർക്ക് റിലീസ് ചെയ്തിരിക്കുന്നു!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ഫലം: നെറ്റ്വർക്ക് റിലീസ് ചെയ്യാനായില്ല!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ഫലം: നെറ്റ്വർക്ക് പ്രീമിയം വാങ്ങുമ്പോൾ ഒഴിവാക്കുന്നവ!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ഫലം: നെറ്റ്വർക്ക് പ്രീമിയം വാങ്ങുമ്പോൾ ഫലം ലഭിക്കുന്നില്ല!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ഫലം: നെറ്റ്വർക്ക് പ്രീമിയം വാങ്ങുന്നതിന് ലഭ്യമല്ല!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ഫലം: നെറ്റ്വർക്ക് പ്രീമിയം വാങ്ങൽ പുരോഗമിക്കുന്നു ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-mn/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-mn/strings.xml
index 1aa5138..117cd3a 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-mn/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-mn/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Сайн байна уу хоосон хэсэг"</string>
+ <string name="request_network" msgid="8945235490804849914">"Сүлжээний хүсэлт тавих"</string>
+ <string name="release_network" msgid="174252378593535238">"Сүлжээ шинээр гаргах"</string>
+ <string name="ping" msgid="7890607576220714932">"Пинг"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Үр дүн:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Хоцролтыг чухалчлах"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Зурвасын өргөнийг чухалчлах"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Сүлжээний премиумийг худалдан авах"</string>
+ <string name="network_available" msgid="4780293262690730734">"Үр дүн: Хүсэлт тавьсан сүлжээ одоо боломжтой боллоо!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Үр дүн: Сүлжээний хүсэлт тавьсан!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Үр дүн: Сүлжээг шинээр гаргалаа!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Үр дүн: Сүлжээг шинээр гаргаж чадсангүй!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Үр дүн: Сүлжээний премиумийг худалдан авах үед гажилт гарлаа!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Үр дүн: Сүлжээний премиумийг худалдан авах үед хоосон илэрц авсан!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Үр дүн: Сүлжээний премиумийг худалдан авах боломжгүй!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Үр дүн: Сүлжээний премиумийг худалдан авч байна ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-mr/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-mr/strings.xml
index 7fbe792..35347b6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-mr/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-mr/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"हॅलो ब्लँक फ्रॅग्मेंट"</string>
+ <string name="request_network" msgid="8945235490804849914">"नेटवर्कची विनंती करा"</string>
+ <string name="release_network" msgid="174252378593535238">"नेटवर्क रिलीझ करा"</string>
+ <string name="ping" msgid="7890607576220714932">"पिंग"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"परिणाम:"</string>
+ <string name="latency_title" msgid="963052613947017009">"लेटन्सी ला प्राधान्य द्या"</string>
+ <string name="bw_title" msgid="3902162973688221344">"बँडविड्थ ला प्राधान्य द्या"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"नेटवर्क प्रीमियमची खरेदी"</string>
+ <string name="network_available" msgid="4780293262690730734">"परिणाम: विनंती केलेले नेटवर्क आता उपलब्ध आहे!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"परिणाम: नटवर्कची विनंती केली आहे!"</string>
+ <string name="network_released" msgid="2992280481133877025">"परिणाम: नेटवर्क रिलीझ केले आहे!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"परिणाम: नेटवर्क रिलीझ करता आले नाही!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"परिणाम: नेटवर्क प्रीमियम खरेदी करताना एक्सेप्शन!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"परिणाम: नेटवर्क प्रीमियम खरेदी करताना कोणताही परिणाम आढळला नाही!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"परिणाम: नेटवर्क प्रीमियम खरेदी करण्यासाठी उपलब्ध नाही!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"परिणाम: नेटवर्क प्रीमियम खरेदी करणे प्रगतीपथावर आहे..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ms/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ms/strings.xml
index b928cd6..cfb7de6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ms/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ms/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Helo cebisan kosong"</string>
+ <string name="request_network" msgid="8945235490804849914">"Minta Rangkaian"</string>
+ <string name="release_network" msgid="174252378593535238">"Lepaskan Rangkaian"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Hasil:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Utamakan Kependaman"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Utamakan Lebar Jalur"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Beli Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Hasil: Rangkaian yang diminta kini tersedia!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Hasil: Rangkaian telah diminta!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Hasil: Rangkaian telah dilepaskan!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Hasil: Gagal mengeluarkan rangkaian!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Hasil: Pengecualian apabila membeli network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Hasil: Tiada hasil apabila membeli network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Hasil: Network premium tidak tersedia untuk pembelian!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Hasil: Pembelian network premium sedang diproses ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-my/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-my/strings.xml
index 229ff5d..a5c81f6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-my/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-my/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-nb/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-nb/strings.xml
index 3d601ab..abb1af4 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-nb/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-nb/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hei, tomt fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Forespør nettverk"</string>
+ <string name="release_network" msgid="174252378593535238">"Frigi nettverk"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioriter tidsforsinkelser"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioriter båndbredde"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Kjøp premiumnettverk"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultat: Det forespurte nettverket er tilgjengelig nå."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultat: Nettverket er forespurt."</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultat: Nettverket er frigitt."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultat: Kunne ikke frigi nettverket."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultat: Unntak ved kjøp av premiumnettverk."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultat: Fikk tomt resultat ved kjøp av premiumnettverk."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultat: Premiumnettverket er ikke tilgjengelig for kjøp."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultat: Kjøp av premiumnettverk pågår …"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ne/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ne/strings.xml
index 229ff5d..cb2d561 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ne/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ne/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"नेटवर्क अनुरोध गर्नुहोस्"</string>
+ <string name="release_network" msgid="174252378593535238">"नेटवर्क रिलिज गर्नुहोस्"</string>
+ <string name="ping" msgid="7890607576220714932">"पिङ"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"परिणाम:"</string>
+ <string name="latency_title" msgid="963052613947017009">"ल्याटेन्सीलाई प्राथमिकता दिनुहोस्"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ब्यान्डविथलाई प्राथमिकता दिनुहोस्"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Network Premium खरिद गर्नुहोस्"</string>
+ <string name="network_available" msgid="4780293262690730734">"परिणाम: अनुरोध गरिएको नेटवर्क अब उपलब्ध भएको छ!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"परिणाम: नेटवर्क अनुरोध गरिएको छ!"</string>
+ <string name="network_released" msgid="2992280481133877025">"परिणाम: नेटवर्क रिलिज गरिएको छ!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"परिणाम: नेटवर्क रिलिज गर्न सकिएन!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"परिणाम: Network Premium खरिद गर्दा अपवाद भयो!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"परिणाम: Network Premium खरिद गर्दा कुनै पनि परिणाम प्राप्त भएन!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"परिणाम: Network Premium खरिद गर्न मिल्दैन!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"परिणाम: Network Premium खरिद गरिँदै छ …"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-nl/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-nl/strings.xml
index 5d10fc6..9d98130 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-nl/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-nl/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hallo leeg fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Netwerk aanvragen"</string>
+ <string name="release_network" msgid="174252378593535238">"Netwerk vrijgeven"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultaat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Vertraging prioriteit geven"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Bandbreedte prioriteit geven"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Netwerkpremium kopen"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultaat: Het gevraagde netwerk is nu beschikbaar."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultaat: Het netwerk is aangevraagd."</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultaat: Het netwerk is vrijgegeven."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultaat: Het netwerk kan niet worden vrijgegeven."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultaat: Uitzondering bij kopen van netwerkpremium."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultaat: Er is een leeg resultaat geretourneerd bij het kopen van netwerkpremium."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultaat: Het netwerkpremium kan niet worden gekocht."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultaat: Netwerkpremium wordt gekocht..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-or/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-or/strings.xml
index 229ff5d..287aa01 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-or/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-or/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Networkର ଅନୁରୋଧ କରନ୍ତୁ"</string>
+ <string name="release_network" msgid="174252378593535238">"Network ରିଲିଜ କରନ୍ତୁ"</string>
+ <string name="ping" msgid="7890607576220714932">"ପିଂ"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ଫଳାଫଳ:"</string>
+ <string name="latency_title" msgid="963052613947017009">"ଲେଟେନ୍ସିକୁ ପ୍ରାଥମିକତା ଦିଅନ୍ତୁ"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ବେଣ୍ଡୱିଡଥକୁ ପ୍ରାଥମିକତା ଦିଅନ୍ତୁ"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Network Premium କିଣନ୍ତୁ"</string>
+ <string name="network_available" msgid="4780293262690730734">"ଫଳାଫଳ: ଅନୁରୋଧ କରାଯାଇଥିବା ନେଟୱାର୍କଟି ବର୍ତ୍ତମାନ ଉପଲବ୍ଧ ଅଛି!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ଫଳାଫଳ: ନେଟୱାର୍କର ଅନୁରୋଧ କରାଯାଇଛି!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ଫଳାଫଳ: ନେଟୱାର୍କକୁ ରିଲିଜ କରାଯାଇଛି!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ଫଳାଫଳ: ନେଟୱାର୍କକୁ ରିଲିଜ କରିବାରେ ବିଫଳ ହୋଇଛି!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ଫଳାଫଳ: Network Premium କିଣିବା ବେଳେ ବ୍ୟତିକ୍ରମ!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ଫଳାଫଳ: Network Premium କିଣିବା ବେଳେ ଖାଲି ଫଳାଫଳ ମିଳିଲା!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ଫଳାଫଳ: Network Premium କ୍ରୟ ପାଇଁ ଉପଲବ୍ଧ ନାହିଁ!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ଫଳାଫଳ: Network Premium କିଣିବାର ପ୍ରକ୍ରିୟା ଚାଲିଛି ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-pa/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-pa/strings.xml
index 229ff5d..e210500 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-pa/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-pa/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Network ਦੀ ਬੇਨਤੀ ਕਰੋ"</string>
+ <string name="release_network" msgid="174252378593535238">"Network ਰਿਲੀਜ਼ ਕਰੋ"</string>
+ <string name="ping" msgid="7890607576220714932">"ਪਿੰਗ"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ਨਤੀਜਾ:"</string>
+ <string name="latency_title" msgid="963052613947017009">"ਵਿਲੰਬਤਾ ਨੂੰ ਤਰਜੀਹ ਦਿਓ"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ਬੈਂਡਵਿਡਥ ਨੂੰ ਤਰਜੀਹ ਦਿਓ"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Network Premium ਖਰੀਦੋ"</string>
+ <string name="network_available" msgid="4780293262690730734">"ਨਤੀਜਾ: ਬੇਨਤੀ ਕੀਤਾ ਨੈੱਟਵਰਕ ਹੁਣ ਉਪਲਬਧ ਹੈ!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ਨਤੀਜਾ: ਨੈੱਟਵਰਕ ਦੇ ਲਈ ਬੇਨਤੀ ਕੀਤੀ ਗਈ ਹੈ!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ਨਤੀਜਾ: ਨੈੱਟਵਰਕ ਨੂੰ ਰਿਲੀਜ਼ ਕੀਤਾ ਗਿਆ ਹੈ!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ਨਤੀਜਾ: ਨੈੱਟਵਰਕ ਨੂੰ ਰਿਲੀਜ਼ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ਨਤੀਜਾ: ਨੈੱਟਵਰਕ ਪ੍ਰੀਮੀਅਮ ਖਰੀਦਣ ਵੇਲੇ ਅਪਵਾਦ!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ਨਤੀਜਾ: ਨੈੱਟਵਰਕ ਪ੍ਰੀਮੀਅਮ ਖਰੀਦਣ ਵੇਲੇ ਖਾਲੀ ਨਤੀਜਾ ਮਿਲਿਆ!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ਨਤੀਜਾ: ਨੈੱਟਵਰਕ ਪ੍ਰੀਮੀਅਮ ਖਰੀਦ ਲਈ ਉਪਲਬਧ ਨਹੀਂ ਹੈ!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ਨਤੀਜਾ: ਨੈੱਟਵਰਕ ਪ੍ਰੀਮੀਅਮ ਦੀ ਖਰੀਦ ਜਾਰੀ ਹੈ ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-pl/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-pl/strings.xml
index 0bf147b..21b1a78 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-pl/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-pl/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Tutaj jest pusty fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Poproś o dostęp do sieci"</string>
+ <string name="release_network" msgid="174252378593535238">"Zwolnij sieć"</string>
+ <string name="ping" msgid="7890607576220714932">"Dzyń"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Efekt:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Nadaj priorytet czasowi oczekiwania"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Nadaj priorytet przepustowości"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Kup sieć Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Efekt: żądana sieć jest już dostępna"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Efekt: zażądano dostępu do sieci"</string>
+ <string name="network_released" msgid="2992280481133877025">"Efekt: sieć została zwolniona"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Efekt: nie udało się zwolnić sieci"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Wynik: przy zakupie sieci premium pojawia się wyjątek"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Wynik: brak wyników w przypadku zakupu sieci premium"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Efekt: nie można kupić sieci premium"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Wynik: trwa kupowanie sieci premium…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-pt-rPT/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-pt-rPT/strings.xml
index b94a687..31c2720 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-pt-rPT/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-pt-rPT/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Olá, fragmento em branco"</string>
+ <string name="request_network" msgid="8945235490804849914">"Pedir rede"</string>
+ <string name="release_network" msgid="174252378593535238">"Lançar rede"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultado:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Priorizar latência"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Priorizar largura de banda"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Comprar serviço premium de rede"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultado: a rede pedida já está disponível!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultado: a rede foi pedida!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultado: a rede foi lançada!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultado: falha ao lançar a rede!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultado: exceção ao comprar o serviço premium de rede!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultado: obteve um resultado vazio ao comprar o serviço premium de rede!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultado: o serviço premium de rede não está disponível para compra!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultado: a compra do serviço premium de rede está em curso…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-pt/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-pt/strings.xml
index 229ff5d..b0b4b51 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-pt/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-pt/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Rede da solicitação"</string>
+ <string name="release_network" msgid="174252378593535238">"Rede de lançamento"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resultado:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Priorizar a latência"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Priorizar a largura de banda"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Comprar Rede Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resultado: a rede solicitada já está disponível."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resultado: a rede foi solicitada."</string>
+ <string name="network_released" msgid="2992280481133877025">"Resultado: a rede foi liberada."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resultado: falha ao liberar a rede."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resultado: exceção ao comprar uma rede Premium."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resultado: há um resultado vazio ao comprar a rede Premium."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resultado: a rede Premium não está disponível para compra."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resultado: a compra da rede Premium está em andamento..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ro/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ro/strings.xml
index 229ff5d..a5c81f6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ro/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ro/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ru/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ru/strings.xml
index 229ff5d..7763c62 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ru/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ru/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Запросить сеть"</string>
+ <string name="release_network" msgid="174252378593535238">"Освободить сеть"</string>
+ <string name="ping" msgid="7890607576220714932">"Запрос ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Результат."</string>
+ <string name="latency_title" msgid="963052613947017009">"Минимизировать задержку"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Минимизировать нагрузку на сеть"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Купить премиальную подписку на использование сети"</string>
+ <string name="network_available" msgid="4780293262690730734">"Результат: запрошенная сеть сейчас доступна."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Результат: сеть запрошена."</string>
+ <string name="network_released" msgid="2992280481133877025">"Результат: сеть освобождена."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Результат: не удалось освободить сеть."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Результат: при попытке купить премиальную подписку на использование сети возникло исключение."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Результат: получен пустой результат при попытке купить премиальную подписку на использование сети."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Результат: премиальная подписка на использование сети недоступна для покупки."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Результат: выполняется покупка премиальной подписки на использование сети."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-si/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-si/strings.xml
index 7c88afe..ed91dd7 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-si/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-si/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"ආයුබෝවන් හිස් කොටස"</string>
+ <string name="request_network" msgid="8945235490804849914">"ජාලය ඉල්ලන්න"</string>
+ <string name="release_network" msgid="174252378593535238">"ජාලය මුදා හරින්න"</string>
+ <string name="ping" msgid="7890607576220714932">"පිං"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ප්රතිඵලය:"</string>
+ <string name="latency_title" msgid="963052613947017009">"පමාවට ප්රමුඛත්වය දෙන්න"</string>
+ <string name="bw_title" msgid="3902162973688221344">"කලාප පළලට ප්රමුඛත්වය දෙන්න"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"ජාල ප්රිමියම් මිල දී ගන්න"</string>
+ <string name="network_available" msgid="4780293262690730734">"ප්රතිඵලය: ඉල්ලූ ජාලය දැන් තිබේ!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ප්රතිඵලය: ජාලය ඉල්ලා ඇත!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ප්රතිඵලය: ජාලය මුදා හැර ඇත!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ප්රතිඵලය: ජාලය මුදා හැරීමට අසමත් විය!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ප්රතිඵලය: ජාල ප්රිමියම් මිල දී ගැනීමේ දී ව්යතිරේකයක්!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ප්රතිඵලය: ජාල ප්රිමියම් මිල දී ගැනීමේ දී හිස් ප්රතිඵලයක් ලැබිණි!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ප්රතිඵලය: ජාල ප්රිමියම් මිල දී ගැනීමට නොමැත!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ප්රතිඵලය: ජාල ප්රිමියම් මිල දී ගැනීම සිදු වෙමින් පවතී ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-sk/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-sk/strings.xml
index 229ff5d..89628b4 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-sk/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-sk/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Vyžiadať sieť"</string>
+ <string name="release_network" msgid="174252378593535238">"Vydať sieť"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Výsledok:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Uprednostniť latenciu"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Uprednostniť rýchlosť pripojenia"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Kúpiť prémiovú sieť"</string>
+ <string name="network_available" msgid="4780293262690730734">"Výsledok: požadovaná sieť je už k dispozícii"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Výsledok: sieť bola vyžiadaná"</string>
+ <string name="network_released" msgid="2992280481133877025">"Výsledok: sieť bola vydaná"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Výsledok: sieť sa nepodarilo vydať"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Výsledok: výnimka pri nákupe prémiovej siete"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Výsledok: prázdny výsledok pri nákupe prémiovej siete"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Výsledok: prémiová sieť nie je k dispozícii na zakúpenie"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Výsledok: prebieha nákup prémiovej siete…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-sl/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-sl/strings.xml
index b3fd35a..0b94379 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-sl/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-sl/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Prazen del za pozdrav"</string>
+ <string name="request_network" msgid="8945235490804849914">"Zahtevanje omrežja"</string>
+ <string name="release_network" msgid="174252378593535238">"Sprostitev omrežja"</string>
+ <string name="ping" msgid="7890607576220714932">"Zven"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Rezultat:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Podelitev prednosti zakasnitvi"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Podelitev prednosti pasovni širini"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Nakup omrežne naročnine"</string>
+ <string name="network_available" msgid="4780293262690730734">"Rezultat: Zahtevano omrežje je zdaj na voljo."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Rezultat: Omrežje je bilo zahtevano."</string>
+ <string name="network_released" msgid="2992280481133877025">"Rezultat: Omrežje je sproščeno."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Rezultat: Sprostitev omrežja ni uspela."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Rezultat: Izjema pri nakupu omrežne naročnine."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Rezultat: Pri nakupu omrežne naročnine je prišlo do praznega rezultata."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Rezultat: Omrežna naročnina ni na voljo za nakup."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Rezultat: Nakup omrežne naročnine je v teku ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-sq/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-sq/strings.xml
index 229ff5d..ccbe35a 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-sq/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-sq/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Kërko rrjetin"</string>
+ <string name="release_network" msgid="174252378593535238">"Publiko rrjetin"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Rezultati:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Jepi përparësi vonesës"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Jepi përparësi gjerësisë së bandës"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Bli rrjetin premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Rezultati: Rrjeti i kërkuar ofrohet tani!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Rezultati: Rrjeti është kërkuar!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Rezultati: Rrjeti është publikuar!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Rezultati: Publikimi i rrjetit dështoi!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Rezultati: Përjashtim kur blihet rrjeti premium!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Rezultati: U mor një rezultat bosh kur u ble rrjeti premium!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Rezultati: Rrjeti premium nuk ofrohet për blerje!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Rezultati: Blerja e rrjetit premium është në vazhdim..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-sr/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-sr/strings.xml
index 229ff5d..60ba624 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-sr/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-sr/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Затражите мрежу"</string>
+ <string name="release_network" msgid="174252378593535238">"Објавите мрежу"</string>
+ <string name="ping" msgid="7890607576220714932">"Пинг"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Резултат:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Дајте приоритет кашњењу"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Дајте приоритет пропусном опсегу"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Купите Premium мрежу"</string>
+ <string name="network_available" msgid="4780293262690730734">"Резултат: Захтевана мрежа је тренутно доступна!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Резултат: Мрежа је затражена!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Резултат: Мрежа је објављена!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Резултат: Објављивање мреже није успело!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Резултат: Изузетак при куповини Premium мреже!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Резултат: Резултат је празан када купујете Premium мрежу!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Резултат: Premium мрежа није доступна за куповину!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Резултат: Куповина Premium мреже је у току..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-sv/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-sv/strings.xml
index 229ff5d..a5c81f6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-sv/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-sv/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-sw/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-sw/strings.xml
index 5cc6a6a..c01aa3a 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-sw/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-sw/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Kipande cha salamu kisichokuwa na kitu"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ta/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ta/strings.xml
index 229ff5d..2a05673 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ta/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ta/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"நெட்வொர்க்கைக் கோரு"</string>
+ <string name="release_network" msgid="174252378593535238">"நெட்வொர்க்கை வெளியிடு"</string>
+ <string name="ping" msgid="7890607576220714932">"பிங்"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"முடிவு:"</string>
+ <string name="latency_title" msgid="963052613947017009">"தாமதத்திற்கு முன்னுரிமை வழங்கு"</string>
+ <string name="bw_title" msgid="3902162973688221344">"இணைய வேகத்திற்கு முன்னுரிமை வழங்கு"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"நெட்வொர்க் பிரீமியத்தை வாங்கு"</string>
+ <string name="network_available" msgid="4780293262690730734">"முடிவு: கோரப்பட்ட நெட்வொர்க் இப்போது கிடைக்கிறது!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"முடிவு: நெட்வொர்க் கோரப்பட்டுள்ளது!"</string>
+ <string name="network_released" msgid="2992280481133877025">"முடிவு: நெட்வொர்க் வெளியிடப்பட்டுள்ளது!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"முடிவு: நெட்வொர்க்கை வெளியிட முடியவில்லை!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"முடிவு: நெட்வொர்க் பிரீமியம் வாங்கும்போது விதிவிலக்கு!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"முடிவு: நெட்வொர்க் பிரீமியம் வாங்கும்போது முடிவு எதுவும் கிடைக்கவில்லை!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"முடிவு: வாங்குவதற்கு நெட்வொர்க் பிரீமியம் கிடைக்கவில்லை!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"முடிவு: நெட்வொர்க் பிரீமியம் வாங்கப்படுகிறது..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-te/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-te/strings.xml
index ad9cef8..43d9a00 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-te/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-te/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"హలో ఖాళీ విడిభాగము"</string>
+ <string name="request_network" msgid="8945235490804849914">"రిక్వెస్ట్ నెట్వర్క్"</string>
+ <string name="release_network" msgid="174252378593535238">"నెట్వర్క్ను రిలీజ్ చేయండి"</string>
+ <string name="ping" msgid="7890607576220714932">"పింగ్"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ఫలితం:"</string>
+ <string name="latency_title" msgid="963052613947017009">"ప్రతిస్పందన సమయానికి ప్రాధాన్యత ఇవ్వండి"</string>
+ <string name="bw_title" msgid="3902162973688221344">"బ్యాండ్విడ్త్కు ప్రాధాన్యత ఇవ్వండి"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"ప్రీమియం నెట్వర్క్ను కొనుగోలు చేయండి"</string>
+ <string name="network_available" msgid="4780293262690730734">"ఫలితం: రిక్వెస్ట్ చేసిన నెట్వర్క్ ఇప్పుడు అందుబాటులో ఉంది!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ఫలితం: నెట్వర్క్ రిక్వెస్ట్ చేయబడింది!"</string>
+ <string name="network_released" msgid="2992280481133877025">"ఫలితం: నెట్వర్క్ రిలీజ్ చేయబడింది!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ఫలితం: నెట్వర్క్ను రిలీజ్ చేయడంలో విఫలమైంది!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ఫలితం: ప్రీమియం నెట్వర్క్ను కొనుగోలు చేసేటప్పుడు అరుదైన ఘటన సంభవించింది!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ఫలితం: ప్రీమియం నెట్వర్క్ను కొనుగోలు చేసినప్పుడు ఖాళీ ఫలితం వచ్చింది!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ఫలితం: కొనుగోలు కోసం ప్రీమియం నెట్వర్క్ అందుబాటులో లేదు!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ఫలితం: ప్రీమియం నెట్వర్క్ కొనుగోలు ప్రోగ్రెస్లో ఉంది ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-th/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-th/strings.xml
index 229ff5d..f0dbee8 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-th/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-th/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"ขอใช้งานเครือข่าย"</string>
+ <string name="release_network" msgid="174252378593535238">"เผยแพร่เครือข่าย"</string>
+ <string name="ping" msgid="7890607576220714932">"ใช้คำสั่ง ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"ผลลัพธ์:"</string>
+ <string name="latency_title" msgid="963052613947017009">"ตั้งเป็นเวลาในการตอบสนองสำคัญ"</string>
+ <string name="bw_title" msgid="3902162973688221344">"ตั้งเป็นแบนด์วิดท์สำคัญ"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"ซื้อเครือข่ายระดับพรีเมียม"</string>
+ <string name="network_available" msgid="4780293262690730734">"ผลลัพธ์: เครือข่ายที่ต้องการพร้อมใช้งานแล้ว"</string>
+ <string name="network_requested" msgid="5646123922691865991">"ผลลัพธ์: ขอใช้งานเครือข่ายแล้ว"</string>
+ <string name="network_released" msgid="2992280481133877025">"ผลลัพธ์: เผยแพร่เครือข่ายแล้ว"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"ผลลัพธ์: เผยแพร่เครือข่ายไม่สําเร็จ"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"ผลลัพธ์: ข้อยกเว้นในการซื้อเครือข่ายระดับพรีเมียม"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"ผลลัพธ์: ได้ผลลัพธ์ว่างเปล่าเมื่อซื้อเครือข่ายระดับพรีเมียม"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"ผลลัพธ์: เครือข่ายระดับพรีเมียมยังไม่พร้อมให้จำหน่าย"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"ผลลัพธ์: กําลังดําเนินการซื้อเครือข่ายระดับพรีเมียม ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-tl/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-tl/strings.xml
index 229ff5d..50897f6 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-tl/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-tl/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Hilingin ang Network"</string>
+ <string name="release_network" msgid="174252378593535238">"I-release ang Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Resulta:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Isapriyoridad ang Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Isapriyoridad ang Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Bilhin ang Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Resulta: Available na ang hiniling na network!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Resulta: Hiniling na ang network!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Resulta: Na-release na ang network!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Resulta: Hindi na-release ang network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Resulta: Nagkakaroon ng exception noong binili ang network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Resulta: Walang nakuhang resulta noong binili ang network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Resulta: Hindi available ang network premium para bilhin!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Resulta: Kasalukuyang binibili ang network premium..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-tr/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-tr/strings.xml
index 1e18a88..d8c2751 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-tr/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-tr/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Merhaba boş bölüm"</string>
+ <string name="request_network" msgid="8945235490804849914">"Request Network"</string>
+ <string name="release_network" msgid="174252378593535238">"Release Network"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Result:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Prioritize Latency"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Prioritize Bandwidth"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Purchase Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Result: The requested network is available now!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Result: The network has been requested!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Result: The network has been released!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Result: Failed to release the network!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Result: Exception when purchasing network premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Result: Got empty result when purchasing network premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Result: The network premium purchase is in progress ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-uk/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-uk/strings.xml
index 0219615..a5f6921 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-uk/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-uk/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Пустий фрагмент із привітанням"</string>
+ <string name="request_network" msgid="8945235490804849914">"Надіслати запит на мережу"</string>
+ <string name="release_network" msgid="174252378593535238">"Випустити мережу"</string>
+ <string name="ping" msgid="7890607576220714932">"Перевірити"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Результат:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Надати пріоритет затримці"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Надати пріоритет пропускній спроможності"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Придбати преміум-доступ до мережі"</string>
+ <string name="network_available" msgid="4780293262690730734">"Результат: потрібна мережа тепер доступна."</string>
+ <string name="network_requested" msgid="5646123922691865991">"Результат: надіслано запит на мережу."</string>
+ <string name="network_released" msgid="2992280481133877025">"Результат: мережу звільнено."</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Результат: не вдалося звільнити мережу."</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Результат: виняток під час покупки преміум-доступу до мережі."</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Результат: під час покупки преміум-доступу до мережі отримано пустий результат."</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Результат: преміум-доступ до мережі недоступний для купівлі."</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Результат: триває процес купівлі преміум-доступу до мережі."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-ur/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-ur/strings.xml
index 229ff5d..1068cf1 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-ur/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-ur/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"نیٹ ورک کی درخواست کریں"</string>
+ <string name="release_network" msgid="174252378593535238">"نیٹ ورک ریلیز کریں"</string>
+ <string name="ping" msgid="7890607576220714932">"پنگ"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"نتیجہ:"</string>
+ <string name="latency_title" msgid="963052613947017009">"تاخیر کو ترجیح دیں"</string>
+ <string name="bw_title" msgid="3902162973688221344">"بینڈوتھ کو ترجیح دیں"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"نیٹ ورک پریمیم خریدیں"</string>
+ <string name="network_available" msgid="4780293262690730734">"نتیجہ: درخواست کردہ نیٹ ورک اب دستیاب ہے!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"نتیجہ: نیٹ ورک کی درخواست کی گئی ہے!"</string>
+ <string name="network_released" msgid="2992280481133877025">"نتیجہ: نیٹ ورک ریلیز کر دیا گیا ہے!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"نتیجہ: نیٹ ورک ریلیز کرنے میں ناکام!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"نتیجہ: نیٹ ورک پریمیم کی خریداری کرتے وقت استثنا!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"نتیجہ: نیٹ ورک پریمیم کی خریداری کرتے وقت خالی نتیجہ ملا!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"نتیجہ: نیٹ ورک پریمیم خریداری کے لیے دستیاب نہیں ہے!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"نتیجہ: نیٹ ورک پریمیم خریداری جاری ہے..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-uz/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-uz/strings.xml
index 229ff5d..a0d4547 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-uz/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-uz/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Tarmoqni talab qilish"</string>
+ <string name="release_network" msgid="174252378593535238">"Tarmoqni chiqarish"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Natija:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Kechikish vaqti ustuvorligi"</string>
+ <string name="bw_title" msgid="3902162973688221344">"O‘tkazuvchanlik qobiliyati ustuvorligi"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Tarmoq premiumni xarid qilish"</string>
+ <string name="network_available" msgid="4780293262690730734">"Natija: Talab qilingan tarmoq hozir mavjud!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Natija: Tarmoq talab qilindi!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Natija: Tarmoq chiqarildi!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Natija: Tarmoqni chiqarib bo‘lmadi!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Natija: Tarmoq premiumni xarid qilishda istisno!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Natija: Tarmoq premiumni xarid qilayotganda bo‘sh natijaga erishildi!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Natija: Tarmoq premiumni xarid qilib bo‘lmaydi!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Natija: Tarmoq premium xaridi davom etmoqda ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-vi/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-vi/strings.xml
index 229ff5d..75bb2a3 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-vi/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-vi/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Yêu cầu mạng"</string>
+ <string name="release_network" msgid="174252378593535238">"Phát hành mạng"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Kết quả:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Ưu tiên độ trễ"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Ưu tiên băng thông"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Mua dịch vụ đặc biệt cho mạng"</string>
+ <string name="network_available" msgid="4780293262690730734">"Kết quả: Mạng bạn yêu cầu hiện đã sử dụng được!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Kết quả: Mạng đã được yêu cầu!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Kết quả: Mạng đã được phát hành!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Kết quả: Không phát hành được mạng!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Kết quả: Ngoại lệ khi mua dịch vụ đặc biệt cho mạng!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Kết quả: Đã nhận kết quả không có nội dung khi mua dịch vụ đặc biệt cho mạng!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Kết quả: Không thể mua dịch vụ đặc biệt cho mạng!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Kết quả: Đang xử lý yêu cầu mua dịch vụ đặc biệt cho mạng ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-zh-rCN/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-zh-rCN/strings.xml
index 229ff5d..0f22142 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-zh-rCN/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-zh-rCN/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"请求网络"</string>
+ <string name="release_network" msgid="174252378593535238">"释放网络"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"结果:"</string>
+ <string name="latency_title" msgid="963052613947017009">"划分延迟时间优先级"</string>
+ <string name="bw_title" msgid="3902162973688221344">"划分带宽优先级"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"购买 Network Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"结果:请求的网络现已可用!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"结果:已请求网络!"</string>
+ <string name="network_released" msgid="2992280481133877025">"结果:已释放网络!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"结果:未能释放网络!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"结果:购买 Network Premium 时出现异常!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"结果:购买 Network Premium 时获得空的结果!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"结果:无法购买 Network Premium!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"结果:正在购买 Network Premium…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-zh-rHK/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-zh-rHK/strings.xml
index 93c0492..18e7286 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-zh-rHK/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-zh-rHK/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"歡迎詞空白片段"</string>
+ <string name="request_network" msgid="8945235490804849914">"要求網絡"</string>
+ <string name="release_network" msgid="174252378593535238">"釋出網絡"</string>
+ <string name="ping" msgid="7890607576220714932">"Ping"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"結果:"</string>
+ <string name="latency_title" msgid="963052613947017009">"以延遲時間為優先"</string>
+ <string name="bw_title" msgid="3902162973688221344">"以頻寬為優先"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"購買進階網絡"</string>
+ <string name="network_available" msgid="4780293262690730734">"結果:要求的網絡現可使用!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"結果:已要求網絡!"</string>
+ <string name="network_released" msgid="2992280481133877025">"結果:已釋出網絡!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"結果:無法釋出網絡!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"結果:購買進階網絡時出現例外情況!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"結果:購買進階網絡時獲得空白結果!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Result: The network premium is not available for purchase!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"結果:進階網絡購買過程正在進行…"</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-zh-rTW/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-zh-rTW/strings.xml
index 229ff5d..3307122 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-zh-rTW/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-zh-rTW/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"要求網路"</string>
+ <string name="release_network" msgid="174252378593535238">"發布網路"</string>
+ <string name="ping" msgid="7890607576220714932">"連線偵測 (ping)"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"結果:"</string>
+ <string name="latency_title" msgid="963052613947017009">"優先處理延遲"</string>
+ <string name="bw_title" msgid="3902162973688221344">"優先處理頻寬"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"購買網路付費項目"</string>
+ <string name="network_available" msgid="4780293262690730734">"結果:要求的網路現已可供使用!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"結果:已要求網路!"</string>
+ <string name="network_released" msgid="2992280481133877025">"結果:已發布網路!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"結果:無法發布網路!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"結果:購買網路付費項目時發生例外狀況!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"結果:購買網路付費項目時收到空白結果!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"結果:無法購買網路付費項目!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"結果:正在購買網路付費項目..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values-zu/strings.xml b/testapps/TestSliceApp/app/src/main/res/values-zu/strings.xml
index 229ff5d..3f329f3 100644
--- a/testapps/TestSliceApp/app/src/main/res/values-zu/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values-zu/strings.xml
@@ -3,4 +3,20 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="1265450418387661962">"TestSliceApp"</string>
<string name="hello_blank_fragment" msgid="1245093642770491175">"Hello blank fragment"</string>
+ <string name="request_network" msgid="8945235490804849914">"Cela Inethiwekhi"</string>
+ <string name="release_network" msgid="174252378593535238">"Khulula Inethiwekhi"</string>
+ <string name="ping" msgid="7890607576220714932">"Qhweba"</string>
+ <string name="result_prefix" msgid="3522796186427501399">"Umphumela:"</string>
+ <string name="latency_title" msgid="963052613947017009">"Beka kuqala Ukubambezeleka"</string>
+ <string name="bw_title" msgid="3902162973688221344">"Beka kuqala Umkhawulokudonsa"</string>
+ <string name="cbs_title" msgid="5234410535569935600">"I-CBS"</string>
+ <string name="purchase" msgid="7843181995697372128">"Thenga Inethiwekhi ye-Premium"</string>
+ <string name="network_available" msgid="4780293262690730734">"Umphumela: Inethiwekhi eceliwe isiyatholakala manje!"</string>
+ <string name="network_requested" msgid="5646123922691865991">"Umphumela: Inethiwekhi iceliwe!"</string>
+ <string name="network_released" msgid="2992280481133877025">"Umphumela: Inethiwekhi isikhishiwe!"</string>
+ <string name="network_release_failed" msgid="256471231420029151">"Umphumela: Yehlulekile ukukhipha inethiwekhi!!!"</string>
+ <string name="purchase_exception" msgid="8876841120055716671">"Umphumela: Okuhlukile lapho uthenga nethiwekhi ye-premium!!!"</string>
+ <string name="purchase_empty_result" msgid="7497824191649973928">"Umphumela: Uthole umphumela ongenalutho lapho uthenga wenethiwekhi ye-premium!!!"</string>
+ <string name="premium_not_available" msgid="7346368693802644748">"Umphumela: Inethiwekhi ye-premium ayitholakaleli ukuthengwa!!!"</string>
+ <string name="purchase_in_progress" msgid="5450288183685032424">"Umphumela: Ukuthengwa kwenethiwekhi ye-premium kuyaqhubeka ..."</string>
</resources>
diff --git a/testapps/TestSliceApp/app/src/main/res/values/strings.xml b/testapps/TestSliceApp/app/src/main/res/values/strings.xml
index c2bb089..4990cec 100644
--- a/testapps/TestSliceApp/app/src/main/res/values/strings.xml
+++ b/testapps/TestSliceApp/app/src/main/res/values/strings.xml
@@ -1,5 +1,20 @@
-<resources>
+<resources xmlns:tools="http://schemas.android.com/tools">
<string name="app_name">TestSliceApp</string>
- <!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
+ <string name="request_network">Request Network</string>
+ <string name="release_network">Release Network</string>
+ <string name="ping">Ping</string>
+ <string name="result_prefix">Result: </string>
+ <string name="latency_title">Prioritize Latency</string>
+ <string name="bw_title">Prioritize Bandwidth</string>
+ <string name="cbs_title">CBS</string>
+ <string name="purchase">Purchase Network Premium</string>
+ <string name="network_available">Result: The requested network is available now!</string>
+ <string name="network_requested">Result: The network has been requested!</string>
+ <string name="network_released">Result: The network has been released!</string>
+ <string name="network_release_failed">Result: Failed to release the network!!!</string>
+ <string name="purchase_exception">Result: Exception when purchasing network premium!!!</string>
+ <string name="purchase_empty_result">Result: Got empty result when purchasing network premium!!!</string>
+ <string name="premium_not_available">Result: The network premium is not available for purchase!!!</string>
+ <string name="purchase_in_progress">Result: The network premium purchase is in progress ...</string>
</resources>
\ No newline at end of file
diff --git a/tests/src/com/android/TelephonyTestBase.java b/tests/src/com/android/TelephonyTestBase.java
index ffda81b..d72d85e 100644
--- a/tests/src/com/android/TelephonyTestBase.java
+++ b/tests/src/com/android/TelephonyTestBase.java
@@ -24,10 +24,16 @@
import com.android.internal.telephony.PhoneConfigurationManager;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Rule;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -40,6 +46,10 @@
protected TestContext mContext;
+ private final HashMap<InstanceKey, Object> mOldInstances = new HashMap<>();
+ private final LinkedList<InstanceKey> mInstanceKeys = new LinkedList<>();
+
+ @Before
public void setUp() throws Exception {
mContext = spy(new TestContext());
// Set up the looper if it does not exist on the test thread.
@@ -56,9 +66,11 @@
}
}
+ @After
public void tearDown() throws Exception {
// Ensure there are no static references to handlers after test completes.
PhoneConfigurationManager.unregisterAllMultiSimConfigChangeRegistrants();
+ restoreInstances();
}
protected final boolean waitForExecutorAction(Executor executor, long timeoutMillis) {
@@ -108,6 +120,61 @@
}
}
+ protected synchronized void replaceInstance(final Class c, final String instanceName,
+ final Object obj, final Object newValue)
+ throws Exception {
+ Field field = c.getDeclaredField(instanceName);
+ field.setAccessible(true);
+
+ InstanceKey key = new InstanceKey(c, instanceName, obj);
+ if (!mOldInstances.containsKey(key)) {
+ mOldInstances.put(key, field.get(obj));
+ mInstanceKeys.add(key);
+ }
+ field.set(obj, newValue);
+ }
+
+ private synchronized void restoreInstances() throws Exception {
+ Iterator<InstanceKey> it = mInstanceKeys.descendingIterator();
+
+ while (it.hasNext()) {
+ InstanceKey key = it.next();
+ Field field = key.mClass.getDeclaredField(key.mInstName);
+ field.setAccessible(true);
+ field.set(key.mObj, mOldInstances.get(key));
+ }
+
+ mInstanceKeys.clear();
+ mOldInstances.clear();
+ }
+
+ private static class InstanceKey {
+ public final Class mClass;
+ public final String mInstName;
+ public final Object mObj;
+ InstanceKey(final Class c, final String instName, final Object obj) {
+ mClass = c;
+ mInstName = instName;
+ mObj = obj;
+ }
+
+ @Override
+ public int hashCode() {
+ return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || obj.getClass() != getClass()) {
+ return false;
+ }
+
+ InstanceKey other = (InstanceKey) obj;
+ return (other.mClass == mClass && other.mInstName.equals(mInstName)
+ && other.mObj == mObj);
+ }
+ }
+
protected TestContext getTestContext() {
return mContext;
}
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index 7c3a842..111df53 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -17,6 +17,7 @@
package com.android;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
import android.content.AttributionSource;
@@ -61,7 +62,11 @@
@Mock ImsManager mMockImsManager;
@Mock UserManager mMockUserManager;
- private SparseArray<PersistableBundle> mCarrierConfigs = new SparseArray<>();
+ private final SparseArray<PersistableBundle> mCarrierConfigs = new SparseArray<>();
+
+ private Intent mIntent;
+
+ private BroadcastReceiver mReceiver;
private final HashSet<String> mPermissionTable = new HashSet<>();
@@ -69,13 +74,12 @@
MockitoAnnotations.initMocks(this);
doAnswer((Answer<PersistableBundle>) invocation -> {
int subId = (int) invocation.getArguments()[0];
- if (subId < 0) {
- return new PersistableBundle();
- }
- PersistableBundle b = mCarrierConfigs.get(subId);
-
- return (b != null ? b : new PersistableBundle());
+ return getTestConfigs(subId);
}).when(mMockCarrierConfigManager).getConfigForSubId(anyInt());
+ doAnswer((Answer<PersistableBundle>) invocation -> {
+ int subId = (int) invocation.getArguments()[0];
+ return getTestConfigs(subId);
+ }).when(mMockCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
}
@Override
@@ -105,28 +109,42 @@
}
@Override
+ public void sendBroadcast(Intent intent) {
+ mIntent = intent;
+ }
+
+ @Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ mReceiver = receiver;
return null;
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {
+ mReceiver = receiver;
return null;
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
+ mReceiver = receiver;
return null;
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler, int flags) {
+ mReceiver = receiver;
return null;
}
@Override
+ public void unregisterReceiver(BroadcastReceiver receiver) {
+ mReceiver = null;
+ }
+
+ @Override
public ContentResolver getContentResolver() {
return null;
}
@@ -134,22 +152,22 @@
@Override
public Object getSystemService(String name) {
switch (name) {
- case (Context.CARRIER_CONFIG_SERVICE) : {
+ case Context.CARRIER_CONFIG_SERVICE: {
return mMockCarrierConfigManager;
}
- case (Context.TELECOM_SERVICE) : {
+ case Context.TELECOM_SERVICE: {
return mMockTelecomManager;
}
- case (Context.TELEPHONY_SERVICE) : {
+ case Context.TELEPHONY_SERVICE: {
return mMockTelephonyManager;
}
- case (Context.TELEPHONY_SUBSCRIPTION_SERVICE) : {
+ case Context.TELEPHONY_SUBSCRIPTION_SERVICE: {
return mMockSubscriptionManager;
}
- case(Context.TELEPHONY_IMS_SERVICE) : {
+ case Context.TELEPHONY_IMS_SERVICE: {
return mMockImsManager;
}
- case(Context.USER_SERVICE) : {
+ case Context.USER_SERVICE: {
return mMockUserManager;
}
}
@@ -170,6 +188,9 @@
if (serviceClass == SubscriptionManager.class) {
return Context.TELEPHONY_SUBSCRIPTION_SERVICE;
}
+ if (serviceClass == ImsManager.class) {
+ return Context.TELEPHONY_IMS_SERVICE;
+ }
if (serviceClass == UserManager.class) {
return Context.USER_SERVICE;
}
@@ -231,18 +252,16 @@
public void grantPermission(String permission) {
synchronized (mPermissionTable) {
- if (mPermissionTable != null && permission != null) {
- mPermissionTable.remove(STUB_PERMISSION_ENABLE_ALL);
- mPermissionTable.add(permission);
- }
+ if (permission == null) return;
+ mPermissionTable.remove(STUB_PERMISSION_ENABLE_ALL);
+ mPermissionTable.add(permission);
}
}
public void revokePermission(String permission) {
synchronized (mPermissionTable) {
- if (mPermissionTable != null && permission != null) {
- mPermissionTable.remove(permission);
- }
+ if (permission == null) return;
+ mPermissionTable.remove(permission);
}
}
@@ -252,6 +271,22 @@
}
}
+ public Intent getBroadcast() {
+ return mIntent;
+ }
+
+ public BroadcastReceiver getBroadcastReceiver() {
+ return mReceiver;
+ }
+
+ private PersistableBundle getTestConfigs(int subId) {
+ if (subId < 0) {
+ return new PersistableBundle();
+ }
+ PersistableBundle b = getCarrierConfig(subId);
+ return (b != null ? b : new PersistableBundle());
+ }
+
private static void logd(String s) {
Log.d(TAG, s);
}
diff --git a/tests/src/com/android/phone/CarrierConfigLoaderTest.java b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
index 60c3a84..f29c123 100644
--- a/tests/src/com/android/phone/CarrierConfigLoaderTest.java
+++ b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
@@ -28,8 +28,11 @@
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -44,6 +47,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyRegistryManager;
import android.testing.TestableLooper;
import androidx.test.InstrumentationRegistry;
@@ -51,7 +55,9 @@
import com.android.TelephonyTestBase;
import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SubscriptionInfoUpdater;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import org.junit.After;
import org.junit.Before;
@@ -60,6 +66,7 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -84,7 +91,9 @@
@Mock PackageManager mPackageManager;
@Mock PackageInfo mPackageInfo;
@Mock SubscriptionInfoUpdater mSubscriptionInfoUpdater;
+ @Mock SubscriptionManagerService mSubscriptionManagerService;
@Mock SharedPreferences mSharedPreferences;
+ @Mock TelephonyRegistryManager mTelephonyRegistryManager;
private TelephonyManager mTelephonyManager;
private CarrierConfigLoader mCarrierConfigLoader;
@@ -95,7 +104,11 @@
@Before
public void setUp() throws Exception {
super.setUp();
+ MockitoAnnotations.initMocks(this);
+ replaceInstance(SubscriptionManagerService.class, "sInstance", null,
+ mSubscriptionManagerService);
+ // TODO: replace doReturn/when with when/thenReturn which is more readable
doReturn(mSharedPreferences).when(mContext).getSharedPreferences(anyString(), anyInt());
doReturn(Build.FINGERPRINT).when(mSharedPreferences).getString(eq("build_fingerprint"),
any());
@@ -114,6 +127,10 @@
eq(PLATFORM_CARRIER_CONFIG_PACKAGE), eq(0) /*flags*/);
doReturn(PLATFORM_CARRIER_CONFIG_PACKAGE_VERSION_CODE).when(
mPackageInfo).getLongVersionCode();
+ when(mContext.getSystemServiceName(TelephonyRegistryManager.class)).thenReturn(
+ Context.TELEPHONY_REGISTRY_SERVICE);
+ when(mContext.getSystemService(TelephonyRegistryManager.class)).thenReturn(
+ mTelephonyRegistryManager);
mHandlerThread = new HandlerThread("CarrierConfigLoaderTest");
mHandlerThread.start();
@@ -185,6 +202,11 @@
assertThat(mCarrierConfigLoader.getNoSimConfig().getInt(CARRIER_CONFIG_EXAMPLE_KEY))
.isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
verify(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
+ verify(mTelephonyRegistryManager).notifyCarrierConfigChanged(
+ eq(DEFAULT_PHONE_ID),
+ eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID),
+ eq(TelephonyManager.UNKNOWN_CARRIER_ID),
+ eq(TelephonyManager.UNKNOWN_CARRIER_ID));
}
/**
@@ -192,6 +214,7 @@
* will return the right config in the XML.
*/
@Test
+ @Ignore("b/257169357")
public void testUpdateConfigForPhoneId_simLoaded_withCachedConfigInXml() throws Exception {
// Bypass case if default subId is not supported by device to reduce flakiness
if (!SubscriptionManager.isValidPhoneId(SubscriptionManager.getPhoneId(DEFAULT_SUB_ID))) {
@@ -256,9 +279,15 @@
mTestableLooper.processAllMessages();
assertThat(mCarrierConfigLoader.getOverrideConfig(DEFAULT_PHONE_ID).isEmpty()).isTrue();
- verify(mSubscriptionInfoUpdater).updateSubscriptionByCarrierConfigAndNotifyComplete(
- eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
- any(PersistableBundle.class), any(Message.class));
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ verify(mSubscriptionManagerService).updateSubscriptionByCarrierConfig(
+ eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
+ any(PersistableBundle.class), any(Runnable.class));
+ } else {
+ verify(mSubscriptionInfoUpdater).updateSubscriptionByCarrierConfigAndNotifyComplete(
+ eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
+ any(PersistableBundle.class), any(Message.class));
+ }
}
/**
@@ -279,9 +308,15 @@
assertThat(mCarrierConfigLoader.getOverrideConfig(DEFAULT_PHONE_ID).getInt(
CARRIER_CONFIG_EXAMPLE_KEY)).isEqualTo(CARRIER_CONFIG_EXAMPLE_VALUE);
- verify(mSubscriptionInfoUpdater).updateSubscriptionByCarrierConfigAndNotifyComplete(
- eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
- any(PersistableBundle.class), any(Message.class));
+ if (PhoneFactory.isSubscriptionManagerServiceEnabled()) {
+ verify(mSubscriptionManagerService).updateSubscriptionByCarrierConfig(
+ eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
+ any(PersistableBundle.class), any(Runnable.class));
+ } else {
+ verify(mSubscriptionInfoUpdater).updateSubscriptionByCarrierConfigAndNotifyComplete(
+ eq(DEFAULT_PHONE_ID), eq(PLATFORM_CARRIER_CONFIG_PACKAGE),
+ any(PersistableBundle.class), any(Message.class));
+ }
}
/**
@@ -395,4 +430,21 @@
: TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS).when(
mockTelephonyManager).getCarrierPrivilegeStatus(anyInt());
}
+
+ @Test
+ public void testMultiSimConfigChanged() throws Exception {
+ replaceInstance(TelephonyManager.class, "sInstance", null, mTelephonyManager);
+ mContext.grantPermission(STUB_PERMISSION_ENABLE_ALL);
+
+ // Changed from 1 to 2.
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+ doReturn(true).when(mContext).bindService(
+ any(Intent.class), any(ServiceConnection.class), anyInt());
+ doNothing().when(mContext).sendBroadcastAsUser(any(Intent.class), any(UserHandle.class));
+ mHandler.sendMessage(mHandler.obtainMessage(17 /* EVENT_MULTI_SIM_CONFIG_CHANGED */));
+ mTestableLooper.processAllMessages();
+
+ mCarrierConfigLoader.updateConfigForPhoneId(1, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
+ mTestableLooper.processAllMessages();
+ }
}
diff --git a/tests/src/com/android/phone/ImsProvisioningControllerTest.java b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
index 2094e20..db83cca 100644
--- a/tests/src/com/android/phone/ImsProvisioningControllerTest.java
+++ b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
@@ -63,6 +63,7 @@
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.aidl.IFeatureProvisioningCallback;
import android.telephony.ims.aidl.IImsConfig;
+import android.telephony.ims.aidl.IImsConfigCallback;
import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.ImsConfigImplBase;
@@ -159,6 +160,9 @@
@Mock
IFeatureProvisioningCallback mIFeatureProvisioningCallback1;
+ @Captor
+ ArgumentCaptor<IImsConfigCallback> mIImsConfigCallback;
+
@Mock
IBinder mIbinder0;
@Mock
@@ -347,6 +351,8 @@
mSubChangedListener.onSubscriptionsChanged();
processAllMessages();
+ verify(mImsConfig, times(1)).addConfigCallback((IImsConfigCallback) any());
+
int[] keys = {
ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE,
ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS,
@@ -390,6 +396,8 @@
mRcsConnectorListener0.getValue().connectionReady(mRcsFeatureManager, mSubId0);
processAllMessages();
+ verify(mImsConfig, times(1)).addConfigCallback((IImsConfigCallback) any());
+
// verify # of read data times from storage : # of Rcs storage length
verify(mImsProvisioningLoader, times(1))
.getProvisioningStatus(eq(mSubId0), eq(FEATURE_RCS), anyInt(), anyInt());
@@ -1736,6 +1744,110 @@
verifyNoMoreInteractions(mImsProvisioningLoader);
}
+ @Test
+ @SmallTest
+ public void changedProvisioningValue_withMmTel() throws Exception {
+ createImsProvisioningController();
+
+ // provisioning required capability
+ // voice, all tech
+ // video, all tech
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY,
+ RADIO_TECHS);
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+
+ mMmTelConnectorListener0.getValue().connectionReady(mImsManager, mSubId0);
+
+ // clear interactions
+ clearInvocations(mIFeatureProvisioningCallback0);
+ clearInvocations(mImsConfig);
+ clearInvocations(mImsProvisioningLoader);
+
+ // MmTel valid
+ int[] keys = {
+ ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS,
+ ProvisioningManager.KEY_VT_PROVISIONING_STATUS,
+ ProvisioningManager.KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE
+ };
+ int[] capas = {
+ MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+ MmTelCapabilities.CAPABILITY_TYPE_VIDEO,
+ MmTelCapabilities.CAPABILITY_TYPE_VOICE
+ };
+ int[] techs = {
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
+ ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
+ };
+
+ for (int index = 0; index < keys.length; index++) {
+ mIImsConfigCallback.getValue().onIntConfigChanged(keys[index],
+ PROVISIONING_VALUE_DISABLED);
+ processAllMessages();
+
+ // verify # of read data times from storage : # of MmTel storage length
+ verify(mImsProvisioningLoader, times(1))
+ .setProvisioningStatus(eq(mSubId0), eq(FEATURE_MMTEL), eq(capas[index]),
+ eq(techs[index]), eq(false));
+
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onFeatureProvisioningChanged(eq(capas[index]), eq(techs[index]), eq(false));
+ }
+
+ verifyNoMoreInteractions(mImsProvisioningLoader);
+ verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
+ verifyNoMoreInteractions(mImsConfig);
+ }
+
+ @Test
+ @SmallTest
+ public void changedProvisioningValue_withRcs() throws Exception {
+ createImsProvisioningController();
+
+ // provisioning required capability : PRESENCE, tech : all
+ setCarrierConfig(mSubId0,
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY, RADIO_TECHS);
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+
+ mRcsConnectorListener0.getValue().connectionReady(mRcsFeatureManager, mSubId0);
+
+ // clear interactions
+ clearInvocations(mIFeatureProvisioningCallback0);
+ clearInvocations(mImsConfig);
+ clearInvocations(mImsProvisioningLoader);
+
+ mIImsConfigCallback.getValue().onIntConfigChanged(KEY_EAB_PROVISIONING_STATUS,
+ PROVISIONING_VALUE_DISABLED);
+ processAllMessages();
+
+ // verify # of read data times from storage : # of MmTel storage length
+ verify(mImsProvisioningLoader, times(RADIO_TECHS.length))
+ .setProvisioningStatus(eq(mSubId0), eq(FEATURE_RCS),
+ eq(CAPABILITY_TYPE_PRESENCE_UCE), anyInt(), eq(false));
+
+ verify(mIFeatureProvisioningCallback0, times(RADIO_TECHS.length))
+ .onRcsFeatureProvisioningChanged(eq(CAPABILITY_TYPE_PRESENCE_UCE), anyInt(),
+ eq(false));
+
+ verifyNoMoreInteractions(mImsProvisioningLoader);
+ verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
+ verifyNoMoreInteractions(mImsConfig);
+ }
+
private void createImsProvisioningController() throws Exception {
if (Looper.myLooper() == null) {
Looper.prepare();
@@ -1755,6 +1867,9 @@
.create(any(), eq(1), mRcsConnectorListener1.capture(), any(), any()))
.thenReturn(mRcsFeatureConnector1);
+ doNothing().when(mImsConfig).addConfigCallback(mIImsConfigCallback.capture());
+ doNothing().when(mImsConfig).removeConfigCallback(any());
+
when(mImsConfig.getConfigInt(anyInt()))
.thenAnswer(invocation -> {
int i = (Integer) (invocation.getArguments()[0]);
diff --git a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
index cb4321c..2bd87be 100644
--- a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
+++ b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
@@ -28,6 +28,8 @@
import static com.android.ims.FeatureConnector.UNAVAILABLE_REASON_NOT_READY;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.mockito.Matchers.any;
@@ -50,6 +52,7 @@
import android.testing.TestableLooper;
import android.util.Log;
+import com.android.TelephonyTestBase;
import com.android.ims.FeatureConnector;
import com.android.ims.ImsManager;
import com.android.ims.RcsFeatureManager;
@@ -68,13 +71,12 @@
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-import java.lang.reflect.Field;
import java.util.concurrent.Executor;
/**
* Unit tests for RcsProvisioningMonitor
*/
-public class ImsStateCallbackControllerTest {
+public class ImsStateCallbackControllerTest extends TelephonyTestBase {
private static final String TAG = "ImsStateCallbackControllerTest";
private static final int FAKE_SUB_ID_BASE = 0x0FFFFFF0;
@@ -187,6 +189,7 @@
mLooper.destroy();
mLooper = null;
}
+ super.tearDown();
}
@Test
@@ -874,6 +877,36 @@
assertFalse(mImsStateCallbackController.isRegistered(mCallback1));
}
+ @Test
+ @SmallTest
+ public void testImsManagerInstance() throws Exception {
+ createController(1);
+
+ // MmTelConnection not ready
+ // check ImsManager instance
+ ImsManager imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
+ assertNull(imsManager);
+
+ // MmTelConnection ready
+ mMmTelConnectorListenerSlot0.getValue()
+ .connectionReady(mMmTelFeatureManager, SLOT_0_SUB_ID);
+ processAllMessages();
+
+ // check ImsManager instance
+ imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
+ assertNotNull(imsManager);
+
+ // MmTelConnection unavailable
+ mMmTelConnectorListenerSlot0.getValue()
+ .connectionUnavailable(UNAVAILABLE_REASON_NOT_READY);
+ processAllMessages();
+
+ // MmTelConnection unavailable
+ // check ImsManager instance
+ imsManager = mImsStateCallbackController.getImsManager(SLOT_0_SUB_ID);
+ assertNull(imsManager);
+ }
+
private void createController(int slotCount) throws Exception {
if (Looper.myLooper() == null) {
Looper.prepare();
@@ -920,13 +953,6 @@
}
}
- private static void replaceInstance(final Class c,
- final String instanceName, final Object obj, final Object newValue) throws Exception {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
- field.set(obj, newValue);
- }
-
private void makeFakeActiveSubIds(int count) {
final int[] subIds = new int[count];
for (int i = 0; i < count; i++) {
diff --git a/tests/src/com/android/phone/NotificationMgrTest.java b/tests/src/com/android/phone/NotificationMgrTest.java
new file mode 100644
index 0000000..e009446
--- /dev/null
+++ b/tests/src/com/android/phone/NotificationMgrTest.java
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone;
+
+import static android.telephony.RadioAccessFamily.RAF_1xRTT;
+import static android.telephony.RadioAccessFamily.RAF_EDGE;
+import static android.telephony.RadioAccessFamily.RAF_EHRPD;
+import static android.telephony.RadioAccessFamily.RAF_EVDO_0;
+import static android.telephony.RadioAccessFamily.RAF_EVDO_A;
+import static android.telephony.RadioAccessFamily.RAF_EVDO_B;
+import static android.telephony.RadioAccessFamily.RAF_GPRS;
+import static android.telephony.RadioAccessFamily.RAF_GSM;
+import static android.telephony.RadioAccessFamily.RAF_HSDPA;
+import static android.telephony.RadioAccessFamily.RAF_HSPA;
+import static android.telephony.RadioAccessFamily.RAF_HSPAP;
+import static android.telephony.RadioAccessFamily.RAF_HSUPA;
+import static android.telephony.RadioAccessFamily.RAF_IS95A;
+import static android.telephony.RadioAccessFamily.RAF_IS95B;
+import static android.telephony.RadioAccessFamily.RAF_LTE;
+import static android.telephony.RadioAccessFamily.RAF_LTE_CA;
+import static android.telephony.RadioAccessFamily.RAF_TD_SCDMA;
+import static android.telephony.RadioAccessFamily.RAF_UMTS;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import static com.android.phone.NotificationMgr.DATA_ROAMING_NOTIFICATION;
+import static com.android.phone.NotificationMgr.LIMITED_SIM_FUNCTION_NOTIFICATION;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.StatusBarManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.os.Build;
+import android.os.PersistableBundle;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.TelephonyTestBase;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.SignalStrengthController;
+import com.android.internal.telephony.data.DataConfigManager;
+import com.android.internal.telephony.data.DataNetworkController;
+import com.android.internal.telephony.data.DataSettingsManager;
+import com.android.internal.telephony.util.NotificationChannelController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit Test for NotificationMgr
+ */
+@RunWith(AndroidTestingRunner.class)
[email protected]
+public class NotificationMgrTest extends TelephonyTestBase {
+ private static final int TEST_SUB_ID = 1;
+ private static final long SERIAL_NUMBER_OF_USER = 1234567L;
+ private static final String TEST_LABEL_CF = "test_call_forwarding";
+ private static final String TEST_SUB_INFO_DISPLAY_NAME = "display_name";
+ private static final String TEST_PACKAGE_NAME = "com.android.phone";
+ private static final String TEST_SELECTED_NETWORK_OPERATOR_NAME = "TheOperator";
+ private static final String MOBILE_NETWORK_SELECTION_PACKAGE = "com.android.phone";
+ private static final String MOBILE_NETWORK_SELECTION_CLASS = ".testClass";
+ private static final String CARRIER_NAME = "CoolCarrier";
+
+ @Mock PhoneGlobals mApp;
+ @Mock StatusBarManager mStatusBarManager;
+ @Mock UserManager mUserManager;
+ @Mock SubscriptionManager mSubscriptionManager;
+ @Mock TelecomManager mTelecomManager;
+ @Mock TelephonyManager mTelephonyManager;
+ @Mock Phone mPhone;
+ @Mock SharedPreferences mSharedPreferences;
+ @Mock NotificationManager mNotificationManager;
+ @Mock SubscriptionInfo mSubscriptionInfo;
+ @Mock Resources mResources;
+ @Mock Context mMockedContext;
+ @Mock ServiceStateTracker mServiceStateTracker;
+ @Mock ServiceState mServiceState;
+ @Mock CarrierConfigManager mCarrierConfigManager;
+ @Mock DataNetworkController mDataNetworkController;
+ @Mock DataSettingsManager mDataSettingsManager;
+ @Mock DataConfigManager mDataConfigManager;
+ @Mock SignalStrengthController mSignalStrengthController;
+
+ private Phone[] mPhones;
+ private NotificationMgr mNotificationMgr;
+ private TestableLooper mTestableLooper;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mPhones = new Phone[]{mPhone};
+ replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
+ when(mPhone.getContext()).thenReturn(mMockedContext);
+ when(mMockedContext.getResources()).thenReturn(mResources);
+ when(mPhone.getServiceState()).thenReturn(mServiceState);
+ when(mServiceState.getNetworkRegistrationInfo(anyInt(), anyInt())).thenReturn(
+ new NetworkRegistrationInfo.Builder()
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .build());
+ when(mPhone.getServiceStateTracker()).thenReturn(mServiceStateTracker);
+ mServiceStateTracker.mSS = mServiceState;
+ when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
+ when(mPhone.getDataNetworkController()).thenReturn(mDataNetworkController);
+ when(mDataNetworkController.getInternetDataDisallowedReasons()).thenReturn(
+ Collections.emptyList());
+ when(mDataNetworkController.getDataConfigManager()).thenReturn(mDataConfigManager);
+ when(mPhone.getDataSettingsManager()).thenReturn(mDataSettingsManager);
+ when(mDataSettingsManager.isDataEnabledForReason(anyInt())).thenReturn(true);
+ when(mApp.getSharedPreferences(anyString(), anyInt())).thenReturn(mSharedPreferences);
+
+ when(mApp.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
+ when(mApp.getSystemService(Context.STATUS_BAR_SERVICE)).thenReturn(mStatusBarManager);
+ when(mApp.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ when(mApp.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)).thenReturn(
+ mSubscriptionManager);
+ when(mApp.getSystemServiceName(TelecomManager.class)).thenReturn(Context.TELECOM_SERVICE);
+ when(mApp.getSystemService(TelecomManager.class)).thenReturn(mTelecomManager);
+ when(mApp.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
+ when(mApp.getSystemServiceName(CarrierConfigManager.class)).thenReturn(
+ Context.CARRIER_CONFIG_SERVICE);
+ when(mApp.getSystemService(CarrierConfigManager.class)).thenReturn(mCarrierConfigManager);
+ when(mApp.getSystemServiceName(CarrierConfigManager.class)).thenReturn(
+ Context.CARRIER_CONFIG_SERVICE);
+ when(mApp.getSystemService(CarrierConfigManager.class)).thenReturn(mCarrierConfigManager);
+
+ when(mApp.createPackageContextAsUser(any(), eq(0), any())).thenReturn(mApp);
+ when(mApp.getSystemService(Context.NOTIFICATION_SERVICE)).thenReturn(mNotificationManager);
+ when(mUserManager.getSerialNumbersOfUsers(true)).thenReturn(
+ new long[]{SERIAL_NUMBER_OF_USER});
+ when(mUserManager.getUserForSerialNumber(eq(SERIAL_NUMBER_OF_USER))).thenReturn(
+ UserHandle.SYSTEM);
+ when(mApp.getResources()).thenReturn(mResources);
+ when(mResources.getString(R.string.labelCF)).thenReturn(TEST_LABEL_CF);
+ ApplicationInfo appWithSdkS = buildApplicationInfo(Build.VERSION_CODES.S);
+ when(mApp.getApplicationInfo()).thenReturn(appWithSdkS);
+ when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
+ when(mTelephonyManager.getServiceState()).thenReturn(mServiceState);
+
+ mTestableLooper = TestableLooper.get(this);
+ // Spy it only to avoid sleep for SystemClock.elapsedRealtime()
+ mNotificationMgr = spy(new NotificationMgr(mApp));
+ mTestableLooper.processAllMessages();
+ }
+
+ @Test
+ public void testUpdateCfi_visible_noActiveSubscription_notificationNeverSent() {
+ // Given no active subscription available
+ when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(null);
+
+ // When updateCfi method is called
+ mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/true, /*isFresh=*/false);
+
+ // Then the notification should never be sent
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateCfi_visible_hasActiveSub_singleSIM_notificationSent() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(1);
+ when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
+ mSubscriptionInfo);
+
+ mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/true, /*isFresh=*/false);
+
+ verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_CALL_FORWARD);
+ }
+
+ @Test
+ public void testUpdateCfi_visible_hasActiveSub_multiSIM_notificationSentWithoutDisplayName() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+ when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
+ mSubscriptionInfo);
+ when(mSubscriptionInfo.getDisplayName()).thenReturn(null);
+
+ mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/true, /*isFresh=*/false);
+
+ verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_CALL_FORWARD);
+ }
+
+ @Test
+ public void testUpdateCfi_visible_hasActiveSub_multiSIM_notificationSentWithDisplayName() {
+ when(mTelephonyManager.getPhoneCount()).thenReturn(2);
+ when(mSubscriptionManager.getActiveSubscriptionInfo(eq(TEST_SUB_ID))).thenReturn(
+ mSubscriptionInfo);
+ when(mSubscriptionInfo.getDisplayName()).thenReturn(TEST_SUB_INFO_DISPLAY_NAME);
+
+ mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/true, /*isFresh=*/false);
+
+ verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_CALL_FORWARD);
+ }
+
+ @Test
+ public void testUpdateCfi_invisible_hasUnmanagedProfile_notificationCanceled() {
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(false);
+
+ mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/false, /*isFresh=*/false);
+
+ verify(mNotificationManager).cancel(any(), anyInt());
+ }
+
+ @Test
+ public void testUpdateCfi_invisible_allProfilesAreManaged_notificationNeverCanceled() {
+ when(mUserManager.isManagedProfile(anyInt())).thenReturn(true);
+
+ mNotificationMgr.updateCfi(TEST_SUB_ID, /*visible=*/false, /*isFresh=*/false);
+
+ verify(mNotificationManager, never()).cancel(any(), anyInt());
+ }
+
+ @Test
+ public void testShowDataRoamingNotification_roamingOn() {
+ mNotificationMgr.showDataRoamingNotification(TEST_SUB_ID, /*roamingOn=*/true);
+
+ verifyNotificationSentWithChannelId(
+ NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS);
+ }
+
+ @Test
+ public void testShowDataRoamingNotification_roamingOff() {
+ mNotificationMgr.showDataRoamingNotification(TEST_SUB_ID, /*roamingOn=*/false);
+
+ verifyNotificationSentWithChannelId(
+ NotificationChannelController.CHANNEL_ID_MOBILE_DATA_STATUS);
+ }
+
+ @Test
+ public void testHideDataRoamingNotification() {
+ mNotificationMgr.hideDataRoamingNotification();
+
+ verify(mNotificationManager).cancel(any(), eq(DATA_ROAMING_NOTIFICATION));
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_justOutOfService_notificationNeverSent() {
+ prepareResourcesForNetworkSelection();
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(2 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_oosEnoughTime_selectionVisibleToUser_notificationSent() {
+ prepareResourcesForNetworkSelection();
+ when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(true);
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ // update to OOS as base state
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ // 10 seconds later
+ moveTimeForward(10 /* seconds */);
+ // verify the behavior on new request
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_ALERT);
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_invalidSubscription_notificationNotSent() {
+ prepareResourcesForNetworkSelection();
+ when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(true);
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE,
+ INVALID_SUBSCRIPTION_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE,
+ INVALID_SUBSCRIPTION_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_nullCarrierConfig_notificationNotSent() {
+ prepareResourcesForNetworkSelection();
+
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(null);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_userNotAllowedToChooseOperator_notificationNotSent() {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ // User is NOT allowed to choose operator
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(false);
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void
+ testUpdateNetworkSelection_OverrideHideCarrierNetworkSelection_notificationNotSent() {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ // Hide network selection menu
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(false);
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_simPreventManualSelection_notificationNotSent()
+ throws Exception {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ // SIM card can prevent manual network selection which is forbidden
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, true);
+ when(mTelephonyManager.isManualNetworkSelectionAllowed()).thenReturn(false);
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_worldMode_userSetLTE_notificationNotSent() {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+
+ // World mode is on
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
+ // User set Network mode as LTE
+ when(mTelephonyManager.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn(
+ (long) (RAF_LTE | RAF_LTE_CA | RAF_IS95A | RAF_IS95B | RAF_1xRTT | RAF_EVDO_0
+ | RAF_EVDO_A | RAF_EVDO_B | RAF_EHRPD));
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_worldMode_userSetTDSCDMA_notSupported_notifNotSent() {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+
+ // World mode is on
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
+ // User set Network mode as NETWORK_MODE_LTE_TDSCDMA_GSM
+ when(mTelephonyManager.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn(
+ (long) (RAF_LTE | RAF_LTE_CA | RAF_TD_SCDMA | RAF_GSM | RAF_GPRS | RAF_EDGE));
+ // But TDSCDMA is NOT supported
+ config.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_worldMode_userSetWCDMA_notificationSent() {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+
+ // World mode is on
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, true);
+ // User set Network mode as NETWORK_MODE_LTE_TDSCDMA_GSM
+ when(mTelephonyManager.getAllowedNetworkTypesForReason(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER)).thenReturn(
+ (long) (RAF_LTE | RAF_LTE_CA | RAF_GSM | RAF_GPRS | RAF_EDGE | RAF_HSUPA | RAF_HSDPA
+ | RAF_HSPA | RAF_HSPAP | RAF_UMTS));
+ // But TDSCDMA is NOT supported
+ config.putBoolean(CarrierConfigManager.KEY_SUPPORT_TDSCDMA_BOOL, false);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_ALERT);
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_worldPhone_networkSelectionNotHide_notificationSent() {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ // World mode is off
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, false);
+ // World phone is on
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_ALERT);
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_gsmBasicOptionOn_notificationSent() {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ // World phone is on
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL, true);
+ // World mode is off
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, false);
+ when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verifyNotificationSentWithChannelId(NotificationChannelController.CHANNEL_ID_ALERT);
+ }
+
+ @Test
+ public void testUpdateNetworkSelection_gsmBasicOptionOff_notificationNotSent() {
+ prepareResourcesForNetworkSelection();
+
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_OPERATOR_SELECTION_EXPAND_BOOL, true);
+ config.putBoolean(CarrierConfigManager.KEY_HIDE_CARRIER_NETWORK_SETTINGS_BOOL, false);
+ config.putBoolean(CarrierConfigManager.KEY_CSP_ENABLED_BOOL, false);
+ // World mode is off
+ config.putBoolean(CarrierConfigManager.KEY_WORLD_MODE_ENABLED_BOOL, false);
+ when(mCarrierConfigManager.getConfigForSubId(TEST_SUB_ID)).thenReturn(config);
+ when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA);
+
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+ moveTimeForward(10 /* seconds */);
+ mNotificationMgr.updateNetworkSelection(ServiceState.STATE_OUT_OF_SERVICE, TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).notify(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testShowLimitedSimFunctionWarningNotification_forTheFirstTime_notificationSent() {
+ when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
+ CARRIER_NAME);
+ when(mResources.getText(
+ R.string.limited_sim_function_with_phone_num_notification_message)).thenReturn(
+ "123");
+
+ mNotificationMgr.showLimitedSimFunctionWarningNotification(TEST_SUB_ID, CARRIER_NAME);
+
+ verifyNotificationSentWithChannelId(
+ NotificationChannelController.CHANNEL_ID_SIM_HIGH_PRIORITY);
+ }
+
+ @Test
+ public void
+ testShowLimitedSimFunctionWarningNotification_consecutiveCall_notificationSentOnce() {
+ when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
+ CARRIER_NAME);
+ when(mResources.getText(
+ R.string.limited_sim_function_with_phone_num_notification_message)).thenReturn(
+ "123");
+
+ // Call the method TWICE with the same subscription
+ mNotificationMgr.showLimitedSimFunctionWarningNotification(TEST_SUB_ID, CARRIER_NAME);
+ mNotificationMgr.showLimitedSimFunctionWarningNotification(TEST_SUB_ID, CARRIER_NAME);
+
+ // Verify the notification is only sent ONCE
+ verifyNotificationSentWithChannelId(
+ NotificationChannelController.CHANNEL_ID_SIM_HIGH_PRIORITY);
+ }
+
+ @Test
+ public void testDismissLimitedSimFunctionWarningNotification_noShowCalledBefore_noCancelSent() {
+ // showLimitedSimFunctionWarningNotification was never called before
+
+ mNotificationMgr.dismissLimitedSimFunctionWarningNotification(TEST_SUB_ID);
+
+ verify(mNotificationManager, never()).cancel(any(), anyInt());
+ }
+
+ @Test
+ public void testDismissLimitedSimFunctionWarningNotification_showCalledBefore_cancelSent() {
+ when(mResources.getText(R.string.limited_sim_function_notification_message)).thenReturn(
+ CARRIER_NAME);
+ when(mResources.getText(
+ R.string.limited_sim_function_with_phone_num_notification_message)).thenReturn(
+ "123");
+ mNotificationMgr.showLimitedSimFunctionWarningNotification(TEST_SUB_ID, CARRIER_NAME);
+
+ mNotificationMgr.dismissLimitedSimFunctionWarningNotification(TEST_SUB_ID);
+
+ verify(mNotificationManager).cancel(any(), eq(LIMITED_SIM_FUNCTION_NOTIFICATION));
+ }
+
+ private ApplicationInfo buildApplicationInfo(int targetSdkVersion) {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.targetSdkVersion = targetSdkVersion;
+ return applicationInfo;
+ }
+
+ private void verifyNotificationSentWithChannelId(String expectedNotificationChannelId) {
+ ArgumentCaptor<Notification> notificationArgumentCaptor = ArgumentCaptor.forClass(
+ Notification.class);
+ verify(mNotificationManager).notify(any(), anyInt(), notificationArgumentCaptor.capture());
+ Notification capturedNotification = notificationArgumentCaptor.getAllValues().get(0);
+ assertThat(capturedNotification.getChannelId()).isEqualTo(expectedNotificationChannelId);
+ }
+
+ private void prepareResourcesForNetworkSelection() {
+ when(mSharedPreferences.getString(Phone.NETWORK_SELECTION_NAME_KEY + TEST_SUB_ID,
+ "")).thenReturn(TEST_SELECTED_NETWORK_OPERATOR_NAME);
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.skip_restoring_network_selection)).thenReturn(false);
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mApp.getString(R.string.mobile_network_settings_package)).thenReturn(
+ MOBILE_NETWORK_SELECTION_PACKAGE);
+ when(mApp.getString(R.string.mobile_network_settings_class)).thenReturn(
+ MOBILE_NETWORK_SELECTION_CLASS);
+ }
+
+ private void moveTimeForward(long seconds) {
+ final long millis = TimeUnit.SECONDS.toMillis(seconds);
+ mTestableLooper.moveTimeForward(millis);
+ mTestableLooper.processAllMessages();
+ doReturn(SystemClock.elapsedRealtime() + millis).when(mNotificationMgr).getTimeStamp();
+ }
+}
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
index ffc0177..e702279 100644
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -17,11 +17,23 @@
package com.android.phone;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
-import android.content.pm.PackageManager;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
import android.telephony.RadioAccessFamily;
import android.telephony.TelephonyManager;
@@ -29,40 +41,50 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.TelephonyTestBase;
+import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.RILConstants;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import java.util.Locale;
/**
- * Unit Test for CarrierConfigLoader.
+ * Unit Test for PhoneInterfaceManager.
*/
@RunWith(AndroidJUnit4.class)
public class PhoneInterfaceManagerTest extends TelephonyTestBase {
private PhoneInterfaceManager mPhoneInterfaceManager;
+ private SharedPreferences mSharedPreferences;
+ private IIntegerConsumer mIIntegerConsumer;
@Mock
PhoneGlobals mPhoneGlobals;
@Mock
Phone mPhone;
+
@Mock
- PackageManager mPackageManager;
+ private SubscriptionManagerService mSubscriptionManagerService;
@Before
@UiThreadTest
public void setUp() throws Exception {
super.setUp();
- MockitoAnnotations.initMocks(this);
- doReturn(mPackageManager).when(mPhoneGlobals).getPackageManager();
- doReturn(false).when(mPackageManager).hasSystemFeature(
- PackageManager.FEATURE_TELEPHONY_IMS);
- mPhoneInterfaceManager = PhoneInterfaceManager.init(mPhoneGlobals);
+ // Note that PhoneInterfaceManager is a singleton. Calling init gives us a handle to the
+ // global singleton, but the context that is passed in is unused if the phone app is already
+ // alive on a test devices. You must use the spy to mock behavior. Mocks stemming from the
+ // passed context will remain unused.
+ mPhoneInterfaceManager = spy(PhoneInterfaceManager.init(mPhoneGlobals));
+ doReturn(mSubscriptionManagerService).when(mPhoneInterfaceManager)
+ .getSubscriptionManagerService();
+ TelephonyManager.setupISubForTest(mSubscriptionManagerService);
+ mSharedPreferences = mPhoneInterfaceManager.getSharedPreferences();
+ mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED).commit();
+ mIIntegerConsumer = mock(IIntegerConsumer.class);
}
@Test
@@ -90,17 +112,175 @@
}
@Test
+ public void matchLocaleFromSupportedLocaleList_inputLocaleChangeToSupportedLocale_notMatched() {
+ Context context = mock(Context.class);
+ when(mPhone.getContext()).thenReturn(context);
+ Resources resources = mock(Resources.class);
+ when(context.getResources()).thenReturn(resources);
+ when(resources.getStringArray(anyInt()))
+ .thenReturn(new String[]{"fi-FI", "ff-Adlm-BF", "en-US"});
+
+ // Input empty string, then return default locale of ICU.
+ String resultInputEmpty = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(mPhone,
+ Locale.forLanguageTag(""));
+
+ assertEquals("und", resultInputEmpty);
+
+ // Input en, then look up the matched supported locale. No matched, so return input locale.
+ String resultOnlyLanguage = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(
+ mPhone,
+ Locale.forLanguageTag("en"));
+
+ assertEquals("en", resultOnlyLanguage);
+ }
+
+ @Test
public void matchLocaleFromSupportedLocaleList_inputLocaleChangeToSupportedLocale() {
+ Context context = mock(Context.class);
+ when(mPhone.getContext()).thenReturn(context);
+ Resources resources = mock(Resources.class);
+ when(context.getResources()).thenReturn(resources);
+ when(resources.getStringArray(anyInt())).thenReturn(new String[]{"zh-Hant-TW"});
+
// Input zh-TW, then look up the matched supported locale, zh-Hant-TW, instead.
- String result1 = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(
+ String resultInputZhTw = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(mPhone,
Locale.forLanguageTag("zh-TW"));
- assertEquals(result1, "zh-Hant-TW");
+ assertEquals("zh-Hant-TW", resultInputZhTw);
+
+ when(resources.getStringArray(anyInt())).thenReturn(
+ new String[]{"fi-FI", "ff-Adlm-BF", "ff-Latn-BF"});
// Input ff-BF, then find the matched supported locale, ff-Latn-BF, instead.
- String result2 = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(
+ String resultFfBf = mPhoneInterfaceManager.matchLocaleFromSupportedLocaleList(mPhone,
Locale.forLanguageTag("ff-BF"));
- assertEquals(result2, "ff-Latn-BF");
+ assertEquals("ff-Latn-BF", resultFfBf);
+ }
+
+ @Test
+ public void setNullCipherAndIntegrityEnabled_successfullyEnable() {
+ whenModemSupportsNullCiphers();
+ doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+ assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED));
+
+ mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(true);
+
+ assertTrue(
+ mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, false));
+ }
+
+ @Test
+ public void setNullCipherAndIntegrityEnabled_successfullyDisable() {
+ whenModemSupportsNullCiphers();
+ doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+ assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED));
+
+ mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(false);
+
+ assertFalse(
+ mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, true));
+ }
+
+ @Test
+ public void setNullCipherAndIntegrityEnabled_lackingNecessaryHal() {
+ doReturn(101).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+
+ assertThrows(UnsupportedOperationException.class, () -> {
+ mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(true);
+ });
+
+ }
+
+ @Test
+ public void setNullCipherAndIntegrityEnabled_lackingPermissions() {
+ doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doThrow(SecurityException.class).when(mPhoneInterfaceManager).enforceModifyPermission();
+
+ assertThrows(SecurityException.class, () -> {
+ mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(true);
+ });
+ }
+
+ @Test
+ public void isNullCipherAndIntegrityPreferenceEnabled() {
+ whenModemSupportsNullCiphers();
+ doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+
+ mPhoneInterfaceManager.setNullCipherAndIntegrityEnabled(false);
+ assertFalse(
+ mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED, true));
+ }
+
+ @Test
+ public void isNullCipherAndIntegrityPreferenceEnabled_lackingNecessaryHal() {
+ doReturn(101).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+
+ assertThrows(UnsupportedOperationException.class, () -> {
+ mPhoneInterfaceManager.isNullCipherAndIntegrityPreferenceEnabled();
+ });
+
+ }
+
+ @Test
+ public void isNullCipherAndIntegrityPreferenceEnabled_lackingModemSupport() {
+ whenModemDoesNotSupportNullCiphers();
+ doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+
+ assertThrows(UnsupportedOperationException.class, () -> {
+ mPhoneInterfaceManager.isNullCipherAndIntegrityPreferenceEnabled();
+ });
+
+ }
+
+ @Test
+ public void isNullCipherAndIntegrityPreferenceEnabled_lackingPermissions() {
+ doReturn(201).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doThrow(SecurityException.class).when(mPhoneInterfaceManager).enforceReadPermission();
+
+ assertThrows(SecurityException.class, () -> {
+ mPhoneInterfaceManager.isNullCipherAndIntegrityPreferenceEnabled();
+ });
+ }
+
+ private void whenModemDoesNotSupportNullCiphers() {
+ doReturn(false).when(mPhone).isNullCipherAndIntegritySupported();
+ doReturn(mPhone).when(
+ mPhoneInterfaceManager).getDefaultPhone();
+ }
+
+ private void whenModemSupportsNullCiphers() {
+ doReturn(true).when(mPhone).isNullCipherAndIntegritySupported();
+ doReturn(mPhone).when(
+ mPhoneInterfaceManager).getDefaultPhone();
+ }
+
+ /**
+ * Verify getCarrierRestrictionStatus throws exception for invalid caller package name.
+ */
+ @Test
+ public void getCarrierRestrictionStatus_ReadPrivilegedException2() {
+ doThrow(SecurityException.class).when(
+ mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+ assertThrows(SecurityException.class, () -> {
+ mPhoneInterfaceManager.getCarrierRestrictionStatus(mIIntegerConsumer, "");
+ });
+ }
+
+ /**
+ * Verify getCarrierRestrictionStatus doesn't throw any exception with valid package name
+ * and with READ_PHONE_STATE permission granted.
+ */
+ @Test
+ public void getCarrierRestrictionStatus() {
+ when(mPhoneInterfaceManager.validateCallerAndGetCarrierId(anyString())).thenReturn(1);
+ mPhoneInterfaceManager.getCarrierRestrictionStatus(mIIntegerConsumer,
+ "com.test.package");
}
}
diff --git a/tests/src/com/android/phone/PhoneUtilsTest.java b/tests/src/com/android/phone/PhoneUtilsTest.java
index eb4c248..3d7815c 100644
--- a/tests/src/com/android/phone/PhoneUtilsTest.java
+++ b/tests/src/com/android/phone/PhoneUtilsTest.java
@@ -22,29 +22,26 @@
import static org.mockito.Mockito.when;
import android.content.ComponentName;
+import android.os.UserHandle;
import android.telecom.PhoneAccountHandle;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import androidx.test.runner.AndroidJUnit4;
+import com.android.TelephonyTestBase;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashMap;
-
@RunWith(AndroidJUnit4.class)
-public class PhoneUtilsTest {
+public class PhoneUtilsTest extends TelephonyTestBase {
@Mock
private SubscriptionManager mMockSubscriptionManager;
@Mock
@@ -59,37 +56,6 @@
private PhoneAccountHandle mPhoneAccountHandleTest = new PhoneAccountHandle(
PSTN_CONNECTION_SERVICE_COMPONENT, mPhoneAccountHandleIdString);
- private HashMap<InstanceKey, Object> mOldInstances = new HashMap<InstanceKey, Object>();
-
- private ArrayList<InstanceKey> mInstanceKeys = new ArrayList<InstanceKey>();
-
- private static class InstanceKey {
- public final Class mClass;
- public final String mInstName;
- public final Object mObj;
- InstanceKey(final Class c, final String instName, final Object obj) {
- mClass = c;
- mInstName = instName;
- mObj = obj;
- }
-
- @Override
- public int hashCode() {
- return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || !(obj instanceof InstanceKey)) {
- return false;
- }
-
- InstanceKey other = (InstanceKey) obj;
- return (other.mClass == mClass && other.mInstName.equals(mInstName)
- && other.mObj == mObj);
- }
- }
-
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -100,37 +66,6 @@
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
}
- @After
- public void tearDown() throws Exception {
- restoreInstance(PhoneFactory.class, "sPhones", null);
- }
-
- protected synchronized void replaceInstance(final Class c, final String instanceName,
- final Object obj, final Object newValue)
- throws Exception {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
-
- InstanceKey key = new InstanceKey(c, instanceName, obj);
- if (!mOldInstances.containsKey(key)) {
- mOldInstances.put(key, field.get(obj));
- mInstanceKeys.add(key);
- }
- field.set(obj, newValue);
- }
-
- protected synchronized void restoreInstance(final Class c, final String instanceName,
- final Object obj) throws Exception {
- InstanceKey key = new InstanceKey(c, instanceName, obj);
- if (mOldInstances.containsKey(key)) {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
- field.set(obj, mOldInstances.get(key));
- mOldInstances.remove(key);
- mInstanceKeys.remove(key);
- }
- }
-
@Test
public void testIsPhoneAccountActive() throws Exception {
assertTrue(PhoneUtils.isPhoneAccountActive(
@@ -147,7 +82,16 @@
public void testMakePstnPhoneAccountHandleWithPrefix() throws Exception {
PhoneAccountHandle phoneAccountHandleTest = new PhoneAccountHandle(
PSTN_CONNECTION_SERVICE_COMPONENT, mPhoneAccountHandleIdString);
- assertEquals(phoneAccountHandleTest, PhoneUtils.makePstnPhoneAccountHandleWithPrefix(
- mPhoneAccountHandleIdString, "", false));
+ assertEquals(phoneAccountHandleTest, PhoneUtils.makePstnPhoneAccountHandleWithId(
+ mPhoneAccountHandleIdString, null));
+ }
+
+ @Test
+ public void testMakePstnPhoneAccountHandleWithPrefixForAnotherUser() throws Exception {
+ UserHandle userHandle = new UserHandle(10);
+ PhoneAccountHandle phoneAccountHandleTest = new PhoneAccountHandle(
+ PSTN_CONNECTION_SERVICE_COMPONENT, mPhoneAccountHandleIdString, userHandle);
+ assertEquals(phoneAccountHandleTest, PhoneUtils.makePstnPhoneAccountHandleWithId(
+ mPhoneAccountHandleIdString, userHandle));
}
}
diff --git a/tests/src/com/android/phone/Telephony2gUpdaterTest.java b/tests/src/com/android/phone/Telephony2gUpdaterTest.java
deleted file mode 100644
index 3684f30..0000000
--- a/tests/src/com/android/phone/Telephony2gUpdaterTest.java
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.phone;
-
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Intent;
-import android.os.UserManager;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.TelephonyTestBase;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-public class Telephony2gUpdaterTest extends TelephonyTestBase {
- private static final long DRAIN_TIMEOUT = 10;
- private Telephony2gUpdater mTelephony2gUpdater;
- private SubscriptionManager.OnSubscriptionsChangedListener mChangedListener;
- private Executor mExecutor;
- private CountDownLatch mLatch;
-
- private UserManager mMockUserManager;
- private TelephonyManager mMockTelephonyManager;
- private SubscriptionManager mMockSubscriptionManager;
-
- // Set up to be returned from mMockSubscriptionManager.getCompleteActiveSubscriptionInfoList()
- // Updates will be reflected in subsequent calls to the mock method.
- private List<SubscriptionInfo> mCurrentSubscriptions;
-
- // 2G Bitmask is 0b10000000_01001011
- private static final long BASE_NETWORK = 0b11111111_11111111;
- private static final long EXPECTED_DISABLED = 0b01111111_10110100;
- private static final long EXPECTED_ENABLED = 0b11111111_11111111;
-
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
-
- mMockTelephonyManager = mContext.getSystemService(TelephonyManager.class);
- mMockUserManager = mContext.getSystemService(UserManager.class);
- mMockSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
-
- mCurrentSubscriptions = new ArrayList<>();
- setupMutableSubscriptionInfoMock();
-
- mExecutor = Executors.newSingleThreadExecutor();
- mTelephony2gUpdater = new Telephony2gUpdater(mExecutor, getTestContext(), BASE_NETWORK);
- mTelephony2gUpdater.init();
- ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> argument =
- ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
- verify(mMockSubscriptionManager).addOnSubscriptionsChangedListener(any(Executor.class),
- argument.capture());
- mChangedListener = argument.getValue();
- }
-
- @Test
- public void onSubscriptionsChanged_noSubscriptions_noAllowedNetworksChanged() {
- triggerOnSubscriptionChangedAndWait();
- verify(mMockTelephonyManager, never()).setAllowedNetworkTypesForReason(anyInt(), anyInt());
- }
-
- @Test
- public void onSubscriptionsChanged_oneSubscription_allowedNetworksUpdated() {
- TelephonyManager tmSubscription1 = addSubscriptionAndGetMock(1001);
- triggerOnSubscriptionChangedAndWait();
-
- verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- }
-
- @Test
- public void onSubscriptionsChanged_manySubscriptionsDisallow2g_allowedNetworkUpdated() {
- // 2g is disallowed
- when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
- true);
- triggerBroadcastReceiverAndWait();
-
- TelephonyManager tmSubscription1 = addSubscriptionAndGetMock(1001);
- TelephonyManager tmSubscription2 = addSubscriptionAndGetMock(1002);
-
- triggerOnSubscriptionChangedAndWait();
-
- verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
- verify(tmSubscription2, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
- }
-
- @Test
- public void onSubscriptionsChanged_noNewSubscriptions_noAllowedNetworksChanged() {
- when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
- true);
- triggerBroadcastReceiverAndWait();
-
- TelephonyManager tmSubscription1 = addSubscriptionAndGetMock(1001);
-
- triggerOnSubscriptionChangedAndWait();
- triggerOnSubscriptionChangedAndWait();
-
- // subscriptions were updated twice, but we have no new subIds so we only expect one update
- verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
- }
-
- @Test
- public void onSubscriptionsChanged_removeSubscription_noAdditionalNetworkChanges() {
- // We start with 2 subIds
- TelephonyManager tmSubscription1 = addSubscriptionAndGetMock(1001);
- TelephonyManager tmSubscription2 = addSubscriptionAndGetMock(1002);
-
- triggerOnSubscriptionChangedAndWait();
-
- // 2g is still enabled since the default is to not set the user restriction
- verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- verify(tmSubscription2, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
-
-
- mCurrentSubscriptions.remove(1);
- triggerOnSubscriptionChangedAndWait();
-
- // Subscriptions have changed, but we've only removed a subscription so there should be no
- // extra updates to allowed network types
- verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- verify(tmSubscription2, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- }
-
- @Test
- public void onSubscriptionsChanged_removeSubscriptionAndReAdd() {
- when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
- true);
- triggerBroadcastReceiverAndWait();
-
- TelephonyManager tmSubscription1 = addSubscriptionAndGetMock(1001);
- triggerOnSubscriptionChangedAndWait();
- mCurrentSubscriptions.remove(0);
- triggerOnSubscriptionChangedAndWait();
- mCurrentSubscriptions.add(getSubInfo(1001));
- triggerOnSubscriptionChangedAndWait();
-
- // subscriptions were updated thrice, but one of those updates removed a subscription
- // such that the sub list was empty, so we only expect an update on the first and last
- // updates.
- verify(tmSubscription1, times(2)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
- }
-
- @Test
- public void onSubscriptionsChanged_addSubscription_updateAllowedNetworks() {
- // We start with 2 subIds and update subscriptions
- TelephonyManager tmSubscription1 = addSubscriptionAndGetMock(1001);
- TelephonyManager tmSubscription2 = addSubscriptionAndGetMock(1002);
- triggerOnSubscriptionChangedAndWait();
-
- // Then add a subId and update subscriptions again
- TelephonyManager tmSubscription3 = addSubscriptionAndGetMock(1003);
- triggerOnSubscriptionChangedAndWait();
-
- // we only need to update the new subscription
- verify(tmSubscription1, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- verify(tmSubscription2, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- verify(tmSubscription3, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- }
-
- @Test
- public void onUserRestrictionUnchanged_noChangeToRestriction_noAllowedNetworksUpdated() {
- TelephonyManager tmSubscription = addSubscriptionAndGetMock(1001);
- triggerOnSubscriptionChangedAndWait();
- // precondition: we've updated allowed networks to the default (2g enabled)
- verify(tmSubscription, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- verify(tmSubscription, never()).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
-
- when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
- true);
- triggerBroadcastReceiverAndWait();
- triggerBroadcastReceiverAndWait();
-
- // expect we only updated once even though we got two broadcasts for user restriction
- // updates
- verify(tmSubscription, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
- // extra check to ensure we haven't also somehow updated back to enabled along the way
- verify(tmSubscription, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- }
-
- @Test
- public void onUserRestrictionChanged_restrictionChanged_allowedNetworksUpdated() {
- // precondition: we've updated allowed networks to the default (2g enabled)
- TelephonyManager tmSubscription = addSubscriptionAndGetMock(1001);
- triggerOnSubscriptionChangedAndWait();
- verify(tmSubscription, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- verify(tmSubscription, never()).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
-
- // update the user restriction to disallow 2g
- reset(tmSubscription);
- when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
- true);
- triggerBroadcastReceiverAndWait();
- verify(tmSubscription, never()).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- verify(tmSubscription, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
-
-
- // update the user restriction to allow 2g again
- reset(tmSubscription);
- when(mMockUserManager.hasUserRestriction(UserManager.DISALLOW_CELLULAR_2G)).thenReturn(
- false);
- triggerBroadcastReceiverAndWait();
- verify(tmSubscription, times(1)).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_ENABLED);
- verify(tmSubscription, never()).setAllowedNetworkTypesForReason(
- TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER_RESTRICTIONS, EXPECTED_DISABLED);
-
- }
-
- private SubscriptionInfo getSubInfo(int id) {
- return new SubscriptionInfo(id, "890126042XXXXXXXXXXX", 0, "T-mobile", "T-mobile", 0, 255,
- "12345", 0, null, "310", "260", "156", false, null, null);
- }
-
- private void triggerOnSubscriptionChangedAndWait() {
- mExecutor.execute(() -> mChangedListener.onSubscriptionsChanged());
- drainSingleThreadedExecutor();
- }
-
- private void triggerBroadcastReceiverAndWait() {
- mTelephony2gUpdater.onReceive(mContext, new Intent());
- drainSingleThreadedExecutor();
- }
-
- /**
- * Wait for all tasks on executor up to the point of invocation to drain, then return.
- *
- * This helper takes advantage of the fact that we're using an immutable single threaded
- * executor that guarantees tasks are executed in the order they are enqueued. It enqueues a
- * task that decrements a latch and then waits on that task to finish. By definition, once the
- * test task finishes, all previously enqueued tasks will have also completed.
- */
- private void drainSingleThreadedExecutor() {
- resetExecutorLatch();
- mExecutor.execute(() -> mLatch.countDown());
- try {
- mLatch.await(DRAIN_TIMEOUT, TimeUnit.SECONDS);
- } catch (InterruptedException e) {
- fail(e.getMessage());
- }
- }
-
- private void resetExecutorLatch() {
- mLatch = new CountDownLatch(1);
- }
-
- /**
- * Helper that allows you to update subInfo and have that change reflected on subsequent calls
- * to {@link SubscriptionManager#getCompleteActiveSubscriptionInfoList()}
- */
- private void setupMutableSubscriptionInfoMock() {
- var answer = new Answer<List<SubscriptionInfo>>() {
- @Override
- public List<SubscriptionInfo> answer(InvocationOnMock invocation) throws Throwable {
- return mCurrentSubscriptions;
- }
- };
- when(mMockSubscriptionManager.getCompleteActiveSubscriptionInfoList()).thenAnswer(answer);
- }
-
- private TelephonyManager addSubscriptionAndGetMock(int subId) {
- mCurrentSubscriptions.add(getSubInfo(subId));
- TelephonyManager tmSubscription = mock(TelephonyManager.class);
- when(mMockTelephonyManager.createForSubscriptionId(subId)).thenReturn(tmSubscription);
- return tmSubscription;
- }
-
-}
diff --git a/tests/src/com/android/phone/ecc/EccDataTest.java b/tests/src/com/android/phone/ecc/EccDataTest.java
index 911d3c5..baa4c7b 100644
--- a/tests/src/com/android/phone/ecc/EccDataTest.java
+++ b/tests/src/com/android/phone/ecc/EccDataTest.java
@@ -32,6 +32,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
+import java.util.Locale;
import java.util.zip.GZIPInputStream;
/**
@@ -49,10 +50,12 @@
HashSet loadedIsos = new HashSet(300);
HashSet loadedNumbers = new HashSet(5);
+ HashSet loadedMncs = new HashSet(5);
for (ProtobufEccData.CountryInfo countryInfo : allEccMessages.countries) {
assertThat(countryInfo.isoCode).isNotEmpty();
- assertThat(countryInfo.isoCode).isEqualTo(countryInfo.isoCode.toUpperCase().trim());
+ assertThat(countryInfo.isoCode).isEqualTo(countryInfo.isoCode.toUpperCase(
+ Locale.ROOT).trim());
assertThat(loadedIsos.contains(countryInfo.isoCode)).isFalse();
loadedIsos.add(countryInfo.isoCode);
@@ -63,6 +66,17 @@
assertThat(loadedNumbers.contains(eccInfo.phoneNumber)).isFalse();
assertThat(eccInfo.types).isNotEmpty();
loadedNumbers.add(eccInfo.phoneNumber);
+ if (eccInfo.routing == ProtobufEccData.EccInfo.Routing.NORMAL) {
+ loadedMncs.clear();
+ for (String mnc : eccInfo.normalRoutingMncs) {
+ assertThat(mnc).isNotEmpty();
+ assertThat(mnc).isEqualTo(mnc.trim());
+ assertThat(loadedMncs.contains(mnc)).isFalse();
+ assertThat(mnc.length()).isGreaterThan(1);
+ assertThat(mnc.length()).isLessThan(4);
+ loadedMncs.add(mnc);
+ }
+ }
}
}
}
diff --git a/tests/src/com/android/phone/euicc/EuiccUiDispatcherActivityTest.java b/tests/src/com/android/phone/euicc/EuiccUiDispatcherActivityTest.java
index 8b0ac5c..817220c 100644
--- a/tests/src/com/android/phone/euicc/EuiccUiDispatcherActivityTest.java
+++ b/tests/src/com/android/phone/euicc/EuiccUiDispatcherActivityTest.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.service.euicc.EuiccService;
import android.telephony.euicc.EuiccManager;
import androidx.test.InstrumentationRegistry;
@@ -111,6 +112,24 @@
assertEquals("bar", euiccUiIntent.getStringExtra("foo"));
}
+ @Test
+ public void testTransferEmbeddedSubscriptionsAction() {
+ mIntent = new Intent(EuiccManager.ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS);
+ Intent euiccUiIntent = mActivity.resolveEuiccUiIntent();
+ assertNotNull(euiccUiIntent);
+ assertEquals(EuiccService.ACTION_TRANSFER_EMBEDDED_SUBSCRIPTIONS,
+ euiccUiIntent.getAction());
+ }
+
+ @Test
+ public void testConvertToEmbeddedSubscriptionAction() {
+ mIntent = new Intent(EuiccManager.ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION);
+ Intent euiccUiIntent = mActivity.resolveEuiccUiIntent();
+ assertNotNull(euiccUiIntent);
+ assertEquals(EuiccService.ACTION_CONVERT_TO_EMBEDDED_SUBSCRIPTION,
+ euiccUiIntent.getAction());
+ }
+
class TestEuiccUiDispatcherActivity extends EuiccUiDispatcherActivity {
public TestEuiccUiDispatcherActivity() {
attachBaseContext(mMockContext);
diff --git a/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java b/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java
new file mode 100644
index 0000000..544d7ea
--- /dev/null
+++ b/tests/src/com/android/phone/slice/SlicePurchaseControllerTest.java
@@ -0,0 +1,749 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.slice;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.telephony.data.NetworkSliceInfo;
+import android.telephony.data.NetworkSlicingConfig;
+import android.testing.TestableLooper;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.internal.telephony.CommandsInterface;
+import com.android.internal.telephony.Phone;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+
+import java.time.LocalDate;
+import java.util.Collections;
+import java.util.Map;
+
+@RunWith(AndroidJUnit4.class)
+public class SlicePurchaseControllerTest extends TelephonyTestBase {
+ private static final String CARRIER = "Some Carrier";
+ private static final String DAILY_NOTIFICATION_COUNT_KEY = "daily_notification_count0";
+ private static final String MONTHLY_NOTIFICATION_COUNT_KEY = "monthly_notification_count0";
+ private static final int YEAR = 2000;
+ private static final int MONTH = 6;
+ private static final int DATE = 1;
+ private static final int PHONE_ID = 0;
+ private static final int DAILY_NOTIFICATION_MAX = 3;
+ private static final int MONTHLY_NOTIFICATION_MAX = 5;
+ private static final long NOTIFICATION_TIMEOUT = 1000;
+ private static final long PURCHASE_CONDITION_TIMEOUT = 2000;
+ private static final long NETWORK_SETUP_TIMEOUT = 3000;
+ private static final long THROTTLE_TIMEOUT = 4000;
+
+ @Mock Phone mPhone;
+ @Mock CarrierConfigManager mCarrierConfigManager;
+ @Mock CommandsInterface mCommandsInterface;
+ @Mock ServiceState mServiceState;
+ @Mock PremiumNetworkEntitlementApi mPremiumNetworkEntitlementApi;
+ @Mock SharedPreferences mSharedPreferences;
+ @Mock SharedPreferences.Editor mEditor;
+
+ private SlicePurchaseController mSlicePurchaseController;
+ private PersistableBundle mBundle;
+ private PremiumNetworkEntitlementResponse mEntitlementResponse;
+ private Handler mHandler;
+ private TestableLooper mTestableLooper;
+ @TelephonyManager.PurchasePremiumCapabilityResult private int mResult;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ HandlerThread handlerThread = new HandlerThread("SlicePurchaseControllerTest");
+ handlerThread.start();
+ mHandler = new Handler(handlerThread.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ AsyncResult ar = (AsyncResult) msg.obj;
+ mResult = (int) ar.result;
+ }
+ };
+ mTestableLooper = new TestableLooper(mHandler.getLooper());
+
+ doReturn(PHONE_ID).when(mPhone).getPhoneId();
+ doReturn(mContext).when(mPhone).getContext();
+ doReturn(mServiceState).when(mPhone).getServiceState();
+ mPhone.mCi = mCommandsInterface;
+
+ doReturn(mCarrierConfigManager).when(mContext)
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ mBundle = new PersistableBundle();
+ mBundle.putInt(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_DAILY_NOTIFICATION_COUNT_INT,
+ DAILY_NOTIFICATION_MAX);
+ mBundle.putInt(
+ CarrierConfigManager.KEY_PREMIUM_CAPABILITY_MAXIMUM_MONTHLY_NOTIFICATION_COUNT_INT,
+ MONTHLY_NOTIFICATION_MAX);
+ doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
+ doReturn(mSharedPreferences).when(mContext).getSharedPreferences(anyString(), anyInt());
+ doReturn(mEditor).when(mSharedPreferences).edit();
+ doAnswer(invocation -> {
+ doReturn(invocation.getArgument(1)).when(mSharedPreferences)
+ .getInt(eq(invocation.getArgument(0)), anyInt());
+ return null;
+ }).when(mEditor).putInt(anyString(), anyInt());
+ doAnswer(invocation -> {
+ doReturn(invocation.getArgument(1)).when(mSharedPreferences)
+ .getString(eq(invocation.getArgument(0)), anyString());
+ return null;
+ }).when(mEditor).putString(anyString(), anyString());
+
+ // create a spy to mock final PendingIntent methods
+ SlicePurchaseController slicePurchaseController =
+ new SlicePurchaseController(mPhone, mHandler.getLooper());
+ mSlicePurchaseController = spy(slicePurchaseController);
+ doReturn(null).when(mSlicePurchaseController).createPendingIntent(
+ anyString(), anyInt(), anyBoolean());
+ doReturn(CARRIER).when(mSlicePurchaseController).getSimOperator();
+ replaceInstance(SlicePurchaseController.class, "sInstances", mSlicePurchaseController,
+ Map.of(PHONE_ID, mSlicePurchaseController));
+ replaceInstance(SlicePurchaseController.class, "mPremiumNetworkEntitlementApi",
+ mSlicePurchaseController, mPremiumNetworkEntitlementApi);
+ replaceInstance(SlicePurchaseController.class, "mIsSlicingUpsellEnabled",
+ mSlicePurchaseController, true);
+ mEntitlementResponse = new PremiumNetworkEntitlementResponse();
+ doReturn(mEntitlementResponse).when(mPremiumNetworkEntitlementApi)
+ .checkEntitlementStatus(anyInt());
+ }
+
+ @Test
+ public void testCreatePendingIntent() {
+ doCallRealMethod().when(mSlicePurchaseController).createPendingIntent(
+ anyString(), anyInt(), anyBoolean());
+ try {
+ mSlicePurchaseController.createPendingIntent(
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_CANCELED",
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY,
+ true);
+ } catch (Exception expected) {
+ return;
+ }
+ fail("Expected createPendingIntent to throw an exception");
+ }
+
+ @Test
+ public void testIsPremiumCapabilityAvailableForPurchase() {
+ assertFalse(mSlicePurchaseController.isPremiumCapabilityAvailableForPurchase(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY));
+
+ // all conditions met
+ doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR).when(mPhone)
+ .getCachedAllowedNetworkTypesBitmask();
+ mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
+ new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
+ mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+ SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+ doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
+
+ // retry to verify available
+ assertTrue(mSlicePurchaseController.isPremiumCapabilityAvailableForPurchase(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY));
+ }
+
+ @Test
+ public void testGetPurchaseURL() {
+ mEntitlementResponse.mServiceFlowURL = SlicePurchaseController.SLICE_PURCHASE_TEST_FILE;
+ String purchaseUrl = mSlicePurchaseController.getPurchaseUrl(mEntitlementResponse);
+ assertEquals(purchaseUrl, SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+
+ mEntitlementResponse.mServiceFlowURL = null;
+ mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+ SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+ purchaseUrl = mSlicePurchaseController.getPurchaseUrl(mEntitlementResponse);
+ assertEquals(purchaseUrl, SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+
+ String[] invalidUrls = new String[] {
+ null,
+ "",
+ "www.google.com",
+ "htt://www.google.com",
+ "http//www.google.com",
+ "http:/www.google.com",
+ "file:///android_asset/",
+ "file:///android_asset/slice_store_test.html"
+ };
+ for (String url : invalidUrls) {
+ mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING, url);
+ assertEquals("", mSlicePurchaseController.getPurchaseUrl(mEntitlementResponse));
+ }
+ }
+
+ @Test
+ public void testUpdateNotificationCounts() {
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR, MONTH, DATE));
+ mSlicePurchaseController.updateNotificationCounts();
+
+ // change only date, month and year remain the same
+ Mockito.clearInvocations(mEditor);
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR, MONTH, DATE + 1));
+ mSlicePurchaseController.updateNotificationCounts();
+ verify(mEditor).putInt(eq(DAILY_NOTIFICATION_COUNT_KEY), eq(0));
+ verify(mEditor, never()).putInt(eq(MONTHLY_NOTIFICATION_COUNT_KEY), eq(0));
+
+ // change only month, date and year remain the same
+ Mockito.clearInvocations(mEditor);
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR, MONTH + 1, DATE + 1));
+ mSlicePurchaseController.updateNotificationCounts();
+ verify(mEditor).putInt(eq(DAILY_NOTIFICATION_COUNT_KEY), eq(0));
+ verify(mEditor).putInt(eq(MONTHLY_NOTIFICATION_COUNT_KEY), eq(0));
+
+ // change only year, date and month remain the same
+ Mockito.clearInvocations(mEditor);
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR + 1, MONTH + 1, DATE + 1));
+ mSlicePurchaseController.updateNotificationCounts();
+ verify(mEditor).putInt(eq(DAILY_NOTIFICATION_COUNT_KEY), eq(0));
+ verify(mEditor).putInt(eq(MONTHLY_NOTIFICATION_COUNT_KEY), eq(0));
+
+ // change only month and year, date remains the same
+ Mockito.clearInvocations(mEditor);
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR + 2, MONTH + 2, DATE + 1));
+ mSlicePurchaseController.updateNotificationCounts();
+ verify(mEditor).putInt(eq(DAILY_NOTIFICATION_COUNT_KEY), eq(0));
+ verify(mEditor).putInt(eq(MONTHLY_NOTIFICATION_COUNT_KEY), eq(0));
+
+ // change only date and year, month remains the same
+ Mockito.clearInvocations(mEditor);
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR + 3, MONTH + 2, DATE + 2));
+ mSlicePurchaseController.updateNotificationCounts();
+ verify(mEditor).putInt(eq(DAILY_NOTIFICATION_COUNT_KEY), eq(0));
+ verify(mEditor).putInt(eq(MONTHLY_NOTIFICATION_COUNT_KEY), eq(0));
+
+ // change only date and month, year remains the same
+ Mockito.clearInvocations(mEditor);
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR + 3, MONTH + 3, DATE + 3));
+ mSlicePurchaseController.updateNotificationCounts();
+ verify(mEditor).putInt(eq(DAILY_NOTIFICATION_COUNT_KEY), eq(0));
+ verify(mEditor).putInt(eq(MONTHLY_NOTIFICATION_COUNT_KEY), eq(0));
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultFeatureNotSupported() {
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_FEATURE_NOT_SUPPORTED,
+ mResult);
+
+ // retry after enabling feature
+ doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR).when(mPhone)
+ .getCachedAllowedNetworkTypesBitmask();
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertNotEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_FEATURE_NOT_SUPPORTED,
+ mResult);
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultCarrierDisabled() {
+ doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR).when(mPhone)
+ .getCachedAllowedNetworkTypesBitmask();
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED, mResult);
+
+ // retry after enabling carrier configs
+ mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
+ new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
+ mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+ SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertNotEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_DISABLED,
+ mResult);
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultNotDefaultDataSubscription() {
+ doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR).when(mPhone)
+ .getCachedAllowedNetworkTypesBitmask();
+ mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
+ new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
+ mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+ SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION,
+ mResult);
+
+ // retry on default data subscription
+ doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertNotEquals(
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION,
+ mResult);
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultNetworkNotAvailable() {
+ doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR).when(mPhone)
+ .getCachedAllowedNetworkTypesBitmask();
+ mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
+ new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
+ mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+ SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+ doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NETWORK_NOT_AVAILABLE,
+ mResult);
+
+ // retry with valid network
+ doReturn(TelephonyManager.NETWORK_TYPE_NR).when(mServiceState).getDataNetworkType();
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertNotEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NETWORK_NOT_AVAILABLE,
+ mResult);
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultEntitlementCheckFailed() {
+ doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR).when(mPhone)
+ .getCachedAllowedNetworkTypesBitmask();
+ mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
+ new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
+ mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+ SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+ doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
+ doReturn(TelephonyManager.NETWORK_TYPE_NR).when(mServiceState).getDataNetworkType();
+ doReturn(null).when(mPremiumNetworkEntitlementApi).checkEntitlementStatus(anyInt());
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED,
+ mResult);
+
+ // retry with provisioned response
+ mEntitlementResponse.mProvisionStatus =
+ PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_PROVISION_STATUS_PROVISIONED;
+ doReturn(mEntitlementResponse).when(mPremiumNetworkEntitlementApi)
+ .checkEntitlementStatus(anyInt());
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED,
+ mResult);
+
+ // retry with provisioning response
+ mEntitlementResponse.mProvisionStatus =
+ PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_PROVISION_STATUS_IN_PROGRESS;
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS,
+ mResult);
+
+ // retry with disallowed response and throttling
+ mEntitlementResponse.mProvisionStatus =
+ PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_PROVISION_STATUS_NOT_PROVISIONED;
+ mEntitlementResponse.mEntitlementStatus =
+ PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_ENTITLEMENT_STATUS_INCOMPATIBLE;
+ mBundle.putLong(CarrierConfigManager
+ .KEY_PREMIUM_CAPABILITY_PURCHASE_CONDITION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG,
+ PURCHASE_CONDITION_TIMEOUT);
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ENTITLEMENT_CHECK_FAILED,
+ mResult);
+
+ // retry to verify throttled
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, mResult);
+
+ // retry with valid entitlement check to verify unthrottled
+ mTestableLooper.moveTimeForward(PURCHASE_CONDITION_TIMEOUT);
+ mTestableLooper.processAllMessages();
+
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultAlreadyInProgress() {
+ sendValidPurchaseRequest();
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS,
+ mResult);
+
+ // retry to verify same result
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_IN_PROGRESS,
+ mResult);
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultSuccess() {
+ sendValidPurchaseRequest();
+
+ // broadcast SUCCESS response from slice purchase application
+ Intent intent = new Intent();
+ intent.setAction("com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_SUCCESS");
+ intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID);
+ intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
+ mContext.getBroadcastReceiver().onReceive(mContext, intent);
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_SUCCESS, mResult);
+
+ // retry tested in testPurchasePremiumCapabilityResultPendingNetworkSetup
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultPendingNetworkSetup() {
+ testPurchasePremiumCapabilityResultSuccess();
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_PENDING_NETWORK_SETUP,
+ mResult);
+
+ // retry to verify unthrottled
+ mTestableLooper.moveTimeForward(NETWORK_SETUP_TIMEOUT);
+ mTestableLooper.processAllMessages();
+
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultAlreadyPurchased() {
+ testPurchasePremiumCapabilityResultSuccess();
+
+ sendNetworkSlicingConfig(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, true);
+
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED,
+ mResult);
+
+ // retry to verify same result
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_ALREADY_PURCHASED,
+ mResult);
+
+ // retry to verify purchase expired
+ sendNetworkSlicingConfig(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, false);
+
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultTimeout() {
+ sendValidPurchaseRequest();
+
+ mTestableLooper.moveTimeForward(NOTIFICATION_TIMEOUT);
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_TIMEOUT, mResult);
+
+ // retry to verify throttled
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, mResult);
+
+ // retry to verify unthrottled
+ mTestableLooper.moveTimeForward(THROTTLE_TIMEOUT);
+ mTestableLooper.processAllMessages();
+
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultUserCanceled() {
+ sendValidPurchaseRequest();
+
+ // broadcast CANCELED response from slice purchase application
+ Intent intent = new Intent();
+ intent.setAction("com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_CANCELED");
+ intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID);
+ intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
+ mContext.getBroadcastReceiver().onReceive(mContext, intent);
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_CANCELED, mResult);
+
+ // retry to verify throttled
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, mResult);
+
+ // retry to verify unthrottled
+ mTestableLooper.moveTimeForward(THROTTLE_TIMEOUT);
+ mTestableLooper.processAllMessages();
+
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultCarrierError() {
+ sendValidPurchaseRequest();
+
+ // broadcast CARRIER_ERROR response from slice purchase application
+ Intent intent = new Intent();
+ intent.setAction(
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_CARRIER_ERROR");
+ intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID);
+ intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
+ intent.putExtra(SlicePurchaseController.EXTRA_FAILURE_CODE,
+ SlicePurchaseController.FAILURE_CODE_SERVER_UNREACHABLE);
+ mContext.getBroadcastReceiver().onReceive(mContext, intent);
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_CARRIER_ERROR, mResult);
+
+ // retry to verify throttled
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, mResult);
+
+ // retry to verify unthrottled
+ mTestableLooper.moveTimeForward(PURCHASE_CONDITION_TIMEOUT);
+ mTestableLooper.processAllMessages();
+
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultRequestFailed() {
+ sendValidPurchaseRequest();
+
+ // broadcast REQUEST_FAILED response from slice purchase application
+ Intent intent = new Intent();
+ intent.setAction(
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_REQUEST_FAILED");
+ intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID);
+ intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
+ mContext.getBroadcastReceiver().onReceive(mContext, intent);
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_REQUEST_FAILED, mResult);
+
+ // retry to verify no throttling
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultNotDefaultDataSubscriptionResponse() {
+ sendValidPurchaseRequest();
+
+ Intent intent = new Intent();
+ intent.setAction("com.android.phone.slice.action."
+ + "SLICE_PURCHASE_APP_RESPONSE_NOT_DEFAULT_DATA_SUBSCRIPTION");
+ intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID);
+ intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
+ mContext.getBroadcastReceiver().onReceive(mContext, intent);
+ mTestableLooper.processAllMessages();
+ assertEquals(
+ TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_NOT_DEFAULT_DATA_SUBSCRIPTION,
+ mResult);
+
+ // retry to verify no throttling
+ testPurchasePremiumCapabilityResultSuccess();
+ }
+
+ @Test
+ public void testPurchasePremiumCapabilityResultNotificationThrottled() {
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR, MONTH, DATE));
+ mSlicePurchaseController.updateNotificationCounts();
+
+ for (int count = 1; count <= DAILY_NOTIFICATION_MAX; count++) {
+ completeSuccessfulPurchase();
+ verify(mEditor).putInt(eq(DAILY_NOTIFICATION_COUNT_KEY), eq(count));
+ verify(mEditor).putInt(eq(MONTHLY_NOTIFICATION_COUNT_KEY), eq(count));
+ }
+
+ // retry to verify throttled
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, mResult);
+
+ // change the date to trigger daily reset
+ mSlicePurchaseController.setLocalDate(LocalDate.of(YEAR, MONTH, DATE + 1));
+ Mockito.clearInvocations(mEditor);
+
+ for (int count = 1; count <= (MONTHLY_NOTIFICATION_MAX - DAILY_NOTIFICATION_MAX); count++) {
+ completeSuccessfulPurchase();
+ verify(mEditor).putInt(eq(DAILY_NOTIFICATION_COUNT_KEY), eq(count));
+ verify(mEditor).putInt(eq(MONTHLY_NOTIFICATION_COUNT_KEY),
+ eq(count + DAILY_NOTIFICATION_MAX));
+ }
+
+ // retry to verify throttled
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_THROTTLED, mResult);
+ }
+
+ private void completeSuccessfulPurchase() {
+ sendValidPurchaseRequest();
+
+ // broadcast NOTIFICATION_SHOWN response from slice purchase application
+ Intent intent = new Intent();
+ intent.setAction(
+ "com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_NOTIFICATION_SHOWN");
+ intent.putExtra(SlicePurchaseController.EXTRA_PHONE_ID, PHONE_ID);
+ intent.putExtra(SlicePurchaseController.EXTRA_PREMIUM_CAPABILITY,
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY);
+ mContext.getBroadcastReceiver().onReceive(mContext, intent);
+ mTestableLooper.processAllMessages();
+
+ // broadcast SUCCESS response from slice purchase application
+ intent.setAction("com.android.phone.slice.action.SLICE_PURCHASE_APP_RESPONSE_SUCCESS");
+ mContext.getBroadcastReceiver().onReceive(mContext, intent);
+ mTestableLooper.processAllMessages();
+ assertEquals(TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_SUCCESS, mResult);
+
+ // complete network setup
+ sendNetworkSlicingConfig(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, true);
+ // purchase expired
+ sendNetworkSlicingConfig(TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, false);
+ }
+
+ private void sendValidPurchaseRequest() {
+ clearInvocations(mContext);
+
+ // feature supported
+ doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR).when(mPhone)
+ .getCachedAllowedNetworkTypesBitmask();
+ // carrier supported
+ mBundle.putIntArray(CarrierConfigManager.KEY_SUPPORTED_PREMIUM_CAPABILITIES_INT_ARRAY,
+ new int[]{TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY});
+ mBundle.putString(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_PURCHASE_URL_STRING,
+ SlicePurchaseController.SLICE_PURCHASE_TEST_FILE);
+ mBundle.putLong(CarrierConfigManager
+ .KEY_PREMIUM_CAPABILITY_NOTIFICATION_DISPLAY_TIMEOUT_MILLIS_LONG,
+ NOTIFICATION_TIMEOUT);
+ mBundle.putLong(CarrierConfigManager.KEY_PREMIUM_CAPABILITY_NETWORK_SETUP_TIME_MILLIS_LONG,
+ NETWORK_SETUP_TIMEOUT);
+ mBundle.putLong(CarrierConfigManager
+ .KEY_PREMIUM_CAPABILITY_NOTIFICATION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG,
+ THROTTLE_TIMEOUT);
+ mBundle.putLong(CarrierConfigManager
+ .KEY_PREMIUM_CAPABILITY_PURCHASE_CONDITION_BACKOFF_HYSTERESIS_TIME_MILLIS_LONG,
+ PURCHASE_CONDITION_TIMEOUT);
+ // default data subscription
+ doReturn(SubscriptionManager.getDefaultDataSubscriptionId()).when(mPhone).getSubId();
+ // network available
+ doReturn(TelephonyManager.NETWORK_TYPE_NR).when(mServiceState).getDataNetworkType();
+ // entitlement check passed
+ mEntitlementResponse.mEntitlementStatus =
+ PremiumNetworkEntitlementResponse.PREMIUM_NETWORK_ENTITLEMENT_STATUS_DISABLED;
+
+ // send purchase request
+ mSlicePurchaseController.purchasePremiumCapability(
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY, mHandler.obtainMessage());
+ mTestableLooper.processAllMessages();
+
+ // verify that the purchase request was sent successfully
+ verify(mContext).sendBroadcast(any(Intent.class));
+ assertEquals(SlicePurchaseController.ACTION_START_SLICE_PURCHASE_APP,
+ mContext.getBroadcast().getAction());
+ assertTrue(mSlicePurchaseController.hasMessages(4 /* EVENT_PURCHASE_TIMEOUT */,
+ TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY));
+ verify(mContext).registerReceiver(any(BroadcastReceiver.class), any(IntentFilter.class));
+ }
+
+ private void sendNetworkSlicingConfig(int capability, boolean configActive) {
+ int sliceServiceType = capability == TelephonyManager.PREMIUM_CAPABILITY_PRIORITIZE_LATENCY
+ ? NetworkSliceInfo.SLICE_SERVICE_TYPE_URLLC
+ : NetworkSliceInfo.SLICE_SERVICE_TYPE_NONE;
+ NetworkSliceInfo sliceInfo = new NetworkSliceInfo.Builder()
+ .setStatus(configActive ? NetworkSliceInfo.SLICE_STATUS_ALLOWED
+ : NetworkSliceInfo.SLICE_STATUS_UNKNOWN)
+ .setSliceServiceType(sliceServiceType)
+ .build();
+ NetworkSlicingConfig slicingConfig = new NetworkSlicingConfig(Collections.emptyList(),
+ Collections.singletonList(sliceInfo));
+ mSlicePurchaseController.obtainMessage(2 /* EVENT_SLICING_CONFIG_CHANGED */,
+ new AsyncResult(null, slicingConfig, null)).sendToTarget();
+ mTestableLooper.processAllMessages();
+ }
+}
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index 28a7b02..969622a 100644
--- a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
+++ b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
@@ -38,19 +38,14 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.phone.common.R;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.Locale;
-
@RunWith(AndroidJUnit4.class)
public class DisconnectCauseUtilTest extends TelephonyTestBase {
@@ -60,42 +55,11 @@
// dynamic
private Context mContext;
- private HashMap<InstanceKey, Object> mOldInstances = new HashMap<InstanceKey, Object>();
- private ArrayList<InstanceKey> mInstanceKeys = new ArrayList<InstanceKey>();
//Mocks
@Mock
private GsmCdmaPhone mMockPhone;
- // inner classes
- private static class InstanceKey {
- public final Class mClass;
- public final String mInstName;
- public final Object mObj;
-
- InstanceKey(final Class c, final String instName, final Object obj) {
- mClass = c;
- mInstName = instName;
- mObj = obj;
- }
-
- @Override
- public int hashCode() {
- return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == null || !(obj instanceof InstanceKey)) {
- return false;
- }
-
- InstanceKey other = (InstanceKey) obj;
- return (other.mClass == mClass && other.mInstName.equals(mInstName)
- && other.mObj == mObj);
- }
- }
-
@Before
public void setUp() throws Exception {
super.setUp();
@@ -106,15 +70,6 @@
setSinglePhone();
}
- @After
- public void tearDown() throws Exception {
- // restoreInstance.
- // Not doing so will potentially "confuse" other tests with the mocked instance
- restoreInstance(PhoneFactory.class, "sPhones", null);
- super.tearDown();
- }
-
-
/**
* Verifies that a call drop due to loss of WIFI results in a disconnect cause of error and that
* the label, description and tone are all present.
@@ -176,33 +131,6 @@
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
}
-
- protected synchronized void replaceInstance(final Class c, final String instanceName,
- final Object obj, final Object newValue)
- throws Exception {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
-
- InstanceKey key = new InstanceKey(c, instanceName, obj);
- if (!mOldInstances.containsKey(key)) {
- mOldInstances.put(key, field.get(obj));
- mInstanceKeys.add(key);
- }
- field.set(obj, newValue);
- }
-
- protected synchronized void restoreInstance(final Class c, final String instanceName,
- final Object obj) throws Exception {
- InstanceKey key = new InstanceKey(c, instanceName, obj);
- if (mOldInstances.containsKey(key)) {
- Field field = c.getDeclaredField(instanceName);
- field.setAccessible(true);
- field.set(obj, mOldInstances.get(key));
- mOldInstances.remove(key);
- mInstanceKeys.remove(key);
- }
- }
-
private Resources getResourcesForLocale(Context context, Locale locale) {
Configuration config = new Configuration();
config.setToDefaults();
diff --git a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
index 33c8b8a..a9207e6 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
@@ -24,7 +24,9 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.ComponentName;
import android.os.Looper;
+import android.telecom.PhoneAccountHandle;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.Before;
@@ -46,6 +48,14 @@
@Mock
private TelecomAccountRegistry mMockTelecomAccountRegistry;
+ private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(
+ "com.android.phone.tests", ImsConferenceControllerTest.class.getName());
+ private static final String TEST_ACCOUNT_ID1 = "id1";
+ private static final String TEST_ACCOUNT_ID2 = "id2";
+ private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_1 = new PhoneAccountHandle(
+ TEST_COMPONENT_NAME, TEST_ACCOUNT_ID1);
+ private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_2 = new PhoneAccountHandle(
+ TEST_COMPONENT_NAME, TEST_ACCOUNT_ID2);
private TestTelephonyConnection mTestTelephonyConnectionA;
private TestTelephonyConnection mTestTelephonyConnectionB;
@@ -61,6 +71,9 @@
mTestTelephonyConnectionA = new TestTelephonyConnection();
mTestTelephonyConnectionB = new TestTelephonyConnection();
+ mTestTelephonyConnectionA.setPhoneAccountHandle(PHONE_ACCOUNT_HANDLE_1);
+ mTestTelephonyConnectionB.setPhoneAccountHandle(PHONE_ACCOUNT_HANDLE_1);
+
mControllerTest = new ImsConferenceController(mTelecomAccountRegistry,
mMockTelephonyConnectionServiceProxy, () -> false);
}
@@ -99,6 +112,27 @@
}
/**
+ * Behavior: add telephony connections A and B to conference controller;
+ * Assumption: Connection A and B have different PhoneAccountHandles, belong to different subs;
+ * Expected: Connection A and Connection B are not conferenceable with each other;
+ */
+ @Test
+ @SmallTest
+ public void testCallsOnDifferentSubsNotConferenceable() {
+ mTestTelephonyConnectionB.setPhoneAccountHandle(PHONE_ACCOUNT_HANDLE_2);
+ mControllerTest.add(mTestTelephonyConnectionA);
+ mControllerTest.add(mTestTelephonyConnectionB);
+
+ mTestTelephonyConnectionA.setActive();
+ mTestTelephonyConnectionB.setTelephonyConnectionOnHold();
+
+ assertFalse(mTestTelephonyConnectionA.getConferenceables()
+ .contains(mTestTelephonyConnectionB));
+ assertFalse(mTestTelephonyConnectionB.getConferenceables()
+ .contains(mTestTelephonyConnectionA));
+ }
+
+ /**
* Behavior: add telephony connection B and A to conference controller,
* set status for merged connections
* Assumption: after performing the behaviors, the status of Connection A is STATE_ACTIVE;
diff --git a/tests/src/com/android/services/telephony/ImsConferenceTest.java b/tests/src/com/android/services/telephony/ImsConferenceTest.java
index 9d2f5ac..5123858 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceTest.java
@@ -590,7 +590,7 @@
ImsConference imsConference = new ImsConference(mMockTelecomAccountRegistry,
mMockTelephonyConnectionServiceProxy, mConferenceHost,
- null /* phoneAccountHandle */, () -> false /* featureFlagProxy */,
+ null /* phoneAccountHandle */, () -> true /* isUsingSinglePartyCallEmulation */,
new ImsConference.CarrierConfiguration.Builder()
.setShouldLocalDisconnectEmptyConference(true)
.build());
@@ -622,6 +622,109 @@
}
/**
+ * Preconditions: both single party emulation and local disconnect of empty conferences is
+ * enabled.
+ * Tests the case where we receive a repeat with the same single-party data that caused a
+ * conference to be treated as a single party; we need to verify that we do not disconnect the
+ * conference locally in this case.
+ * @throws Exception
+ */
+ @Test
+ @SmallTest
+ public void testNoLocalDisconnectSinglePartyConferenceOnRepeatedCep() throws Exception {
+ when(mMockTelecomAccountRegistry.isUsingSimCallManager(any(PhoneAccountHandle.class)))
+ .thenReturn(false);
+
+ ImsConference imsConference = new ImsConference(mMockTelecomAccountRegistry,
+ mMockTelephonyConnectionServiceProxy, mConferenceHost,
+ null /* phoneAccountHandle */, () -> true /* isUsingSinglePartyCallEmulation */,
+ new ImsConference.CarrierConfiguration.Builder()
+ .setShouldLocalDisconnectEmptyConference(true)
+ .build());
+
+ ConferenceParticipant participant1 = new ConferenceParticipant(
+ Uri.parse("tel:6505551212"),
+ "A",
+ Uri.parse("sip:[email protected]"),
+ Connection.STATE_ACTIVE,
+ Call.Details.DIRECTION_INCOMING);
+ ConferenceParticipant participant2 = new ConferenceParticipant(
+ Uri.parse("tel:6505551213"),
+ "A",
+ Uri.parse("sip:[email protected]"),
+ Connection.STATE_ACTIVE,
+ Call.Details.DIRECTION_INCOMING);
+ imsConference.handleConferenceParticipantsUpdate(mConferenceHost,
+ Arrays.asList(participant1, participant2));
+ assertEquals(2, imsConference.getNumberOfParticipants());
+
+ // Drop to 1 participant which enters single party mode.
+ imsConference.handleConferenceParticipantsUpdate(mConferenceHost,
+ Arrays.asList(participant1));
+ assertEquals(0, imsConference.getNumberOfParticipants());
+
+ // Get a repeat CEP with the same participant data; we should still be in single party mode
+ // but we should NOT disconnect the conference.
+ imsConference.handleConferenceParticipantsUpdate(mConferenceHost,
+ Arrays.asList(participant1));
+ assertEquals(0, imsConference.getNumberOfParticipants());
+ verify(mConferenceHost.mMockCall, never()).hangup();
+ }
+
+ /**
+ * An extension of {@link #testNoLocalDisconnectSinglePartyConferenceOnRepeatedCep()} where we
+ * get a repeated CEP with the same single party state, but then finally get a CEP with no
+ * participants anymore. In this case we do expect a local disconnect as the final state.
+ * @throws Exception
+ */
+ @Test
+ @SmallTest
+ public void testLocalDisconnectSinglePartyConferenceOnRepeatedCep() throws Exception {
+ when(mMockTelecomAccountRegistry.isUsingSimCallManager(any(PhoneAccountHandle.class)))
+ .thenReturn(false);
+
+ ImsConference imsConference = new ImsConference(mMockTelecomAccountRegistry,
+ mMockTelephonyConnectionServiceProxy, mConferenceHost,
+ null /* phoneAccountHandle */, () -> true /* isUsingSinglePartyCallEmulation */,
+ new ImsConference.CarrierConfiguration.Builder()
+ .setShouldLocalDisconnectEmptyConference(true)
+ .build());
+
+ ConferenceParticipant participant1 = new ConferenceParticipant(
+ Uri.parse("tel:6505551212"),
+ "A",
+ Uri.parse("sip:[email protected]"),
+ Connection.STATE_ACTIVE,
+ Call.Details.DIRECTION_INCOMING);
+ ConferenceParticipant participant2 = new ConferenceParticipant(
+ Uri.parse("tel:6505551213"),
+ "A",
+ Uri.parse("sip:[email protected]"),
+ Connection.STATE_ACTIVE,
+ Call.Details.DIRECTION_INCOMING);
+ imsConference.handleConferenceParticipantsUpdate(mConferenceHost,
+ Arrays.asList(participant1, participant2));
+ assertEquals(2, imsConference.getNumberOfParticipants());
+
+ // Drop to 1 participant which enters single party mode.
+ imsConference.handleConferenceParticipantsUpdate(mConferenceHost,
+ Arrays.asList(participant1));
+ assertEquals(0, imsConference.getNumberOfParticipants());
+
+ // Get a repeat CEP with the same participant data; we should still be in single party mode
+ // but we should NOT disconnect the conference.
+ imsConference.handleConferenceParticipantsUpdate(mConferenceHost,
+ Arrays.asList(participant1));
+ assertEquals(0, imsConference.getNumberOfParticipants());
+ verify(mConferenceHost.mMockCall, never()).hangup();
+
+ // Got another CEP that has no participants at all; we should disconnet in this case
+ imsConference.handleConferenceParticipantsUpdate(mConferenceHost, Collections.emptyList());
+ assertEquals(0, imsConference.getNumberOfParticipants());
+ verify(mConferenceHost.mMockCall).hangup();
+ }
+
+ /**
* Tests a scenario where a handover connection arrives via
* {@link TelephonyConnection#onOriginalConnectionRedialed(
* com.android.internal.telephony.Connection)}. During this process, the conference properties
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index efa906e..f115a43 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -16,6 +16,16 @@
package com.android.services.telephony;
+import static android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE;
+import static android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE;
+import static android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+import static android.telephony.DisconnectCause.NOT_DISCONNECTED;
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
+import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS;
+import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+import static android.telephony.emergency.EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE;
+import static android.telephony.ims.ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL;
+
import static com.android.internal.telephony.RILConstants.GSM_PHONE;
import static junit.framework.Assert.assertEquals;
@@ -25,6 +35,7 @@
import static junit.framework.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Matchers.eq;
@@ -33,7 +44,9 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
@@ -42,29 +55,45 @@
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
+import android.telecom.Conference;
+import android.telecom.Conferenceable;
import android.telecom.ConnectionRequest;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
+import android.telephony.DomainSelectionService;
import android.telephony.RadioAccessFamily;
import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsReasonInfo;
import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.TelephonyTestBase;
+import com.android.ims.ImsManager;
import com.android.internal.telecom.IConnectionService;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.PhoneInternalInterface.DialArgs;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.data.PhoneSwitcher;
+import com.android.internal.telephony.domainselection.DomainSelectionConnection;
+import com.android.internal.telephony.domainselection.DomainSelectionResolver;
+import com.android.internal.telephony.domainselection.EmergencyCallDomainSelectionConnection;
+import com.android.internal.telephony.domainselection.NormalCallDomainSelectionConnection;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
+import com.android.internal.telephony.emergency.EmergencyStateTracker;
import com.android.internal.telephony.gsm.SuppServiceNotification;
+import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.satellite.SatelliteSOSMessageRecommender;
import org.junit.After;
import org.junit.Before;
@@ -72,11 +101,16 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
/**
* Unit tests for TelephonyConnectionService.
@@ -90,6 +124,8 @@
*/
public static class SimpleTelephonyConnection extends TelephonyConnection {
public boolean wasDisconnected = false;
+ public boolean wasUnheld = false;
+ public boolean wasHeld = false;
@Override
public TelephonyConnection cloneConnection() {
@@ -100,6 +136,29 @@
public void hangup(int telephonyDisconnectCode) {
wasDisconnected = true;
}
+
+ @Override
+ public void onUnhold() {
+ wasUnheld = true;
+ }
+
+ @Override
+ public void onHold() {
+ wasHeld = true;
+ }
+ }
+
+ public static class SimpleConference extends Conference {
+ public boolean wasUnheld = false;
+
+ public SimpleConference(PhoneAccountHandle phoneAccountHandle) {
+ super(phoneAccountHandle);
+ }
+
+ @Override
+ public void onUnhold() {
+ wasUnheld = true;
+ }
}
private static final long TIMEOUT_MS = 100;
@@ -115,6 +174,8 @@
private static final PhoneAccountHandle PHONE_ACCOUNT_HANDLE_2 = new PhoneAccountHandle(
TEST_COMPONENT_NAME, TEST_ACCOUNT_ID2);
private static final Uri TEST_ADDRESS = Uri.parse("tel:+16505551212");
+ private static final String TELECOM_CALL_ID1 = "TC1";
+ private static final String TEST_EMERGENCY_NUMBER = "911";
private android.telecom.Connection mConnection;
@Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
@@ -134,6 +195,13 @@
@Mock Call mCall2;
@Mock com.android.internal.telephony.Connection mInternalConnection;
@Mock com.android.internal.telephony.Connection mInternalConnection2;
+ @Mock DomainSelectionResolver mDomainSelectionResolver;
+ @Mock EmergencyCallDomainSelectionConnection mEmergencyCallDomainSelectionConnection;
+ @Mock NormalCallDomainSelectionConnection mNormalCallDomainSelectionConnection;
+ @Mock ImsPhone mImsPhone;
+ @Mock
+ private SatelliteSOSMessageRecommender mSatelliteSOSMessageRecommender;
+ private EmergencyStateTracker mEmergencyStateTracker;
private Phone mPhone0;
private Phone mPhone1;
@@ -159,6 +227,7 @@
@Before
public void setUp() throws Exception {
super.setUp();
+ doReturn(Looper.getMainLooper()).when(mContext).getMainLooper();
mTestConnectionService = new TestTelephonyConnectionService(mContext);
mTestConnectionService.setPhoneFactoryProxy(mPhoneFactoryProxy);
mTestConnectionService.setSubscriptionManagerProxy(mSubscriptionManagerProxy);
@@ -179,6 +248,24 @@
mTestConnectionService.setDisconnectCauseFactory(mDisconnectCauseFactory);
mTestConnectionService.onCreate();
mTestConnectionService.setTelephonyManagerProxy(mTelephonyManagerProxy);
+ replaceInstance(TelephonyConnectionService.class, "mDomainSelectionResolver",
+ mTestConnectionService, mDomainSelectionResolver);
+ mEmergencyStateTracker = Mockito.mock(EmergencyStateTracker.class);
+ replaceInstance(TelephonyConnectionService.class, "mEmergencyStateTracker",
+ mTestConnectionService, mEmergencyStateTracker);
+ replaceInstance(TelephonyConnectionService.class, "mSatelliteSOSMessageRecommender",
+ mTestConnectionService, mSatelliteSOSMessageRecommender);
+ doNothing().when(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), any());
+ doNothing().when(mSatelliteSOSMessageRecommender).onEmergencyCallConnectionStateChanged(
+ anyString(), anyInt());
+ doReturn(CompletableFuture.completedFuture(NOT_DISCONNECTED))
+ .when(mEmergencyStateTracker)
+ .startEmergencyCall(any(), anyString(), eq(false));
+ replaceInstance(TelephonyConnectionService.class,
+ "mDomainSelectionMainExecutor", mTestConnectionService, getExecutor());
+ doReturn(false).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ doReturn(null).when(mDomainSelectionResolver).getDomainSelectionConnection(
+ any(), anyInt(), anyBoolean());
mBinderStub = (IConnectionService.Stub) mTestConnectionService.onBind(null);
}
@@ -191,6 +278,54 @@
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
+ * - Slot 0 is IN_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only)
+ * - Slot 1 is in Emergency SMS Mode
+ *
+ * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
+ */
+ @Test
+ @SmallTest
+ public void testEmergencySmsModeSimEmergencyOnly() {
+ Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
+ false /*isEmergencyOnly*/);
+ Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ true /*isEmergencyOnly*/);
+ setDefaultPhone(slot0Phone);
+ setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
+ setEmergencySmsMode(slot1Phone, true);
+
+ Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+ assertEquals(slot1Phone, resultPhone);
+ }
+
+ /**
+ * Prerequisites:
+ * - MSIM Device, two slots with SIMs inserted
+ * - Slot 0 is IN_SERVICE, Slot 1 is OUT_OF_SERVICE
+ * - Slot 1 is in Emergency SMS Mode
+ *
+ * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone
+ */
+ @Test
+ @SmallTest
+ public void testEmergencySmsModeSimOutOfService() {
+ Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
+ false /*isEmergencyOnly*/);
+ Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ setDefaultPhone(slot0Phone);
+ setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
+ setEmergencySmsMode(slot1Phone, true);
+
+ Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+ assertEquals(slot0Phone, resultPhone);
+ }
+
+ /**
+ * Prerequisites:
+ * - MSIM Device, two slots with SIMs inserted
* - Users default Voice SIM choice is IN_SERVICE
*
* Result: getFirstPhoneForEmergencyCall returns the default Voice SIM choice.
@@ -213,6 +348,52 @@
/**
* Prerequisites:
* - MSIM Device, two slots with SIMs inserted
+ * - Users default data SIM choice is OUT_OF_SERVICE (emergency calls only)
+ *
+ * Result: getFirstPhoneForEmergencyCall returns the default data SIM choice.
+ */
+ @Test
+ @SmallTest
+ public void testDefaultDataSimEmergencyOnly() {
+ Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
+ false /*isEmergencyOnly*/);
+ Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ true /*isEmergencyOnly*/);
+ setDefaultPhone(slot0Phone);
+ setupDeviceConfig(slot0Phone, slot1Phone, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ setDefaultDataPhoneId(SLOT_1_PHONE_ID);
+
+ Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+ assertEquals(slot1Phone, resultPhone);
+ }
+
+ /**
+ * Prerequisites:
+ * - MSIM Device, two slots with SIMs inserted
+ * - Users default data SIM choice is OUT_OF_SERVICE
+ *
+ * Result: getFirstPhoneForEmergencyCall does not return the default data SIM choice.
+ */
+ @Test
+ @SmallTest
+ public void testDefaultDataSimOutOfService() {
+ Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_IN_SERVICE,
+ false /*isEmergencyOnly*/);
+ Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ setDefaultPhone(slot0Phone);
+ setupDeviceConfig(slot0Phone, slot1Phone, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ setDefaultDataPhoneId(SLOT_1_PHONE_ID);
+
+ Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+ assertEquals(slot0Phone, resultPhone);
+ }
+
+ /**
+ * Prerequisites:
+ * - MSIM Device, two slots with SIMs inserted
* - Slot 0 is OUT_OF_SERVICE, Slot 1 is OUT_OF_SERVICE (emergency calls only)
*
* Result: getFirstPhoneForEmergencyCall returns the slot 1 phone
@@ -396,9 +577,6 @@
// Slot 1 has more capabilities
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
- // Slot 1 has SIM inserted.
- setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/);
- setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
@@ -511,9 +689,6 @@
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
- // Two SIMs inserted
- setSlotHasIccCard(SLOT_0_PHONE_ID, true /*isInserted*/);
- setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
@@ -542,9 +717,6 @@
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
- // Slot 0 has SIM inserted.
- setSlotHasIccCard(SLOT_0_PHONE_ID, true /*isInserted*/);
- setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
@@ -573,9 +745,35 @@
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
- // Slot 1 has SIM inserted.
- setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/);
- setSlotHasIccCard(SLOT_1_PHONE_ID, true /*isInserted*/);
+
+ Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+ assertEquals(slot1Phone, resultPhone);
+ }
+
+ /**
+ * Prerequisites:
+ * - MSIM Device with one ESIM, only slot 1 inserted has PSIM inserted
+ * - Both phones have the same capability
+ *
+ * Result: getFirstPhoneForEmergencyCall returns the slot 1 phone because it is the only one
+ * with a SIM inserted
+ */
+ @Test
+ @SmallTest
+ public void testEqualCapabilitySim1Inserted_WithOneEsim() {
+ Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ setDefaultPhone(slot0Phone);
+ setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
+ when(slot0Phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
+ setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
+ // Make Capability the same
+ setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_LTE);
+ setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
@@ -604,9 +802,6 @@
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_GSM);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_LTE);
- // No SIMs inserted
- setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/);
- setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
@@ -634,9 +829,63 @@
// Make Capability the same
setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN);
setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN);
- // No SIMs inserted
- setSlotHasIccCard(SLOT_0_PHONE_ID, false /*isInserted*/);
- setSlotHasIccCard(SLOT_1_PHONE_ID, false /*isInserted*/);
+
+ Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+ assertEquals(slot0Phone, resultPhone);
+ }
+
+ /**
+ * Prerequisites:
+ * - MSIM Device, no SIMs inserted (one ESIM)
+ * - Both SIMs have the same capability (Unknown)
+ *
+ * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot.
+ */
+ @Test
+ @SmallTest
+ public void testEqualCapabilityNoSimsInserted_WithOneESim() {
+ Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ setDefaultPhone(slot0Phone);
+ setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
+ setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_ABSENT);
+ when(slot1Phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
+ // Make Capability the samesvim
+ setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN);
+ setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN);
+
+ Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
+
+ assertEquals(slot0Phone, resultPhone);
+ }
+
+ /**
+ * Prerequisites:
+ * - MSIM Device, both ESIMS (no profile activated)
+ * - Both phones have the same capability (Unknown)
+ *
+ * Result: getFirstPhoneForEmergencyCall returns the slot 0 phone, since it is the first slot.
+ */
+ @Test
+ @SmallTest
+ public void testEqualCapabilityNoSimsInserted_WithTwoESims() {
+ Phone slot0Phone = makeTestPhone(SLOT_0_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ Phone slot1Phone = makeTestPhone(SLOT_1_PHONE_ID, ServiceState.STATE_OUT_OF_SERVICE,
+ false /*isEmergencyOnly*/);
+ setDefaultPhone(slot0Phone);
+ setupDeviceConfig(slot0Phone, slot1Phone, SLOT_0_PHONE_ID);
+ when(slot0Phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ setPhoneSlotState(SLOT_0_PHONE_ID, TelephonyManager.SIM_STATE_READY);
+ when(slot1Phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ setPhoneSlotState(SLOT_1_PHONE_ID, TelephonyManager.SIM_STATE_READY);
+ // Make Capability the sames
+ setPhoneRadioAccessFamily(slot0Phone, RadioAccessFamily.RAF_UNKNOWN);
+ setPhoneRadioAccessFamily(slot1Phone, RadioAccessFamily.RAF_UNKNOWN);
Phone resultPhone = mTestConnectionService.getFirstPhoneForEmergencyCall();
@@ -661,7 +910,8 @@
setPhones(phones);
c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
- mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), false /*isPermanentFailure*/);
// We never need to be notified in telecom that the PhoneAccount has changed, because it
// was redialed on the same slot
@@ -692,7 +942,8 @@
setPhones(phones);
c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
- mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), true /*isPermanentFailure*/);
// We never need to be notified in telecom that the PhoneAccount has changed, because it
// was never redialed
@@ -733,7 +984,8 @@
doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
slot1Phone);
- mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), false /*isPermanentFailure*/);
// The cache should still contain all of the Phones, since it was a temporary failure.
assertEquals(2, mTestConnectionService.mEmergencyRetryCache.second.size());
@@ -774,7 +1026,8 @@
doReturn(PHONE_ACCOUNT_HANDLE_2).when(mPhoneUtilsProxy).makePstnPhoneAccountHandle(
slot1Phone);
- mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), true /*isPermanentFailure*/);
// The cache should only contain the slot1Phone.
assertEquals(1, mTestConnectionService.mEmergencyRetryCache.second.size());
@@ -816,7 +1069,8 @@
slot1Phone);
// First Temporary failure
- mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), false /*isPermanentFailure*/);
// Set the Phone to the new phone that was just used to dial.
c.setMockPhone(slot1Phone);
// The cache should still contain all of the Phones, since it was a temporary failure.
@@ -824,7 +1078,8 @@
// Make sure slot 1 is next in the queue.
assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek());
// Second Temporary failure
- mTestConnectionService.retryOutgoingOriginalConnection(c, false /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), false /*isPermanentFailure*/);
// Set the Phone to the new phone that was just used to dial.
c.setMockPhone(slot0Phone);
// The cache should still contain all of the Phones, since it was a temporary failure.
@@ -871,7 +1126,8 @@
slot1Phone);
// First Permanent failure
- mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), true /*isPermanentFailure*/);
// Set the Phone to the new phone that was just used to dial.
c.setMockPhone(slot1Phone);
// The cache should only contain one phone
@@ -879,7 +1135,8 @@
// Make sure slot 1 is next in the queue.
assertEquals(slot1Phone, mTestConnectionService.mEmergencyRetryCache.second.peek());
// Second Permanent failure
- mTestConnectionService.retryOutgoingOriginalConnection(c, true /*isPermanentFailure*/);
+ mTestConnectionService.retryOutgoingOriginalConnection(c,
+ c.getPhone(), true /*isPermanentFailure*/);
// The cache should be empty
assertEquals(true, mTestConnectionService.mEmergencyRetryCache.second.isEmpty());
@@ -1022,6 +1279,7 @@
// This shouldn't happen
fail();
}
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), any());
}
/**
@@ -1055,7 +1313,7 @@
@Test
@SmallTest
public void testCreateOutgoingEmergencyConnection_delayDial_supportsuplondds() {
- // If the non-DDS supports SUPL, dont switch data
+ // If the non-DDS supports SUPL, don't switch data
doReturn(false).when(mDeviceState).isSuplDdsSwitchRequiredForEmergencyCall(any());
getTestContext().getCarrierConfig(0 /*subId*/).putStringArray(
CarrierConfigManager.Gps.KEY_ES_SUPL_DATA_PLANE_ONLY_ROAMING_PLMN_STRING_ARRAY,
@@ -1213,7 +1471,7 @@
}
/**
- * Verifies where there is another call on the same sub, we don't set
+ * Verifies where there is another call on a different sub, we set
* {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming call extras.
* @throws Exception
*/
@@ -1244,6 +1502,40 @@
.count());
}
+ /**
+ * For virtual DSDA-enabled devices, verifies where there is another call on the same sub, we
+ * don't set {@link android.telecom.Connection#EXTRA_ANSWERING_DROPS_FG_CALL} on the incoming
+ * call extras.
+ * @throws Exception
+ */
+ @Test
+ @SmallTest
+ public void testSecondCallDifferentSubWontDisconnectForDsdaDevice() throws Exception {
+ // Re-uses existing test for setup, then configures device as virtual DSDA for test duration
+ testIncomingDoesntRequestDisconnect();
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+
+ when(mCall.getState()).thenReturn(Call.State.ACTIVE);
+ when(mCall2.getState()).thenReturn(Call.State.WAITING);
+ when(mCall2.getLatestConnection()).thenReturn(mInternalConnection2);
+ // At this point the call is ringing on the second phone.
+ when(mPhone0.getRingingCall()).thenReturn(null);
+ when(mPhone1.getRingingCall()).thenReturn(mCall2);
+
+ mBinderStub.createConnection(PHONE_ACCOUNT_HANDLE_2, "TC@2",
+ new ConnectionRequest(PHONE_ACCOUNT_HANDLE_2, Uri.parse("tel:16505551213"),
+ new Bundle()),
+ true, false, null);
+ waitForHandlerAction(mTestConnectionService.getHandler(), TIMEOUT_MS);
+ assertEquals(2, mTestConnectionService.getAllConnections().size());
+
+ // None of the connections should have the extra set.
+ assertEquals(0, mTestConnectionService.getAllConnections().stream()
+ .filter(c -> c.getExtras() != null && c.getExtras().containsKey(
+ android.telecom.Connection.EXTRA_ANSWERING_DROPS_FG_CALL))
+ .count());
+ }
+
private static final PhoneAccountHandle SUB1_HANDLE = new PhoneAccountHandle(
new ComponentName("test", "class"), "1");
private static final PhoneAccountHandle SUB2_HANDLE = new PhoneAccountHandle(
@@ -1255,7 +1547,8 @@
ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
tcs.add(tc1);
- TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB1_HANDLE);
+ TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
+ tcs, SUB1_HANDLE, mTelephonyManagerProxy);
// Would've preferred to use mockito, but can't mock out TelephonyConnection/Connection
// easily.
assertFalse(tc1.wasDisconnected);
@@ -1267,7 +1560,8 @@
ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, true);
tcs.add(tc1);
- TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB2_HANDLE);
+ TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
+ tcs, SUB2_HANDLE, mTelephonyManagerProxy);
// Other call is an emergency call, so don't disconnect it.
assertFalse(tc1.wasDisconnected);
}
@@ -1279,7 +1573,8 @@
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE,
android.telecom.Connection.PROPERTY_IS_EXTERNAL_CALL, false);
tcs.add(tc1);
- TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB2_HANDLE);
+ TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
+ tcs, SUB2_HANDLE, mTelephonyManagerProxy);
// Other call is an external call, so don't disconnect it.
assertFalse(tc1.wasDisconnected);
}
@@ -1290,7 +1585,8 @@
ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
tcs.add(tc1);
- TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB2_HANDLE);
+ TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
+ tcs, SUB2_HANDLE, mTelephonyManagerProxy);
assertTrue(tc1.wasDisconnected);
}
@@ -1303,11 +1599,951 @@
tcs.add(tc1);
tcs.add(tc2);
- TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(tcs, SUB2_HANDLE);
+ TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
+ tcs, SUB2_HANDLE, mTelephonyManagerProxy);
assertTrue(tc1.wasDisconnected);
assertTrue(tc2.wasDisconnected);
}
+ /**
+ * Verifies that DSDA or virtual DSDA-enabled devices can support active non-emergency calls on
+ * separate subs.
+ */
+ @Test
+ @SmallTest
+ public void testDontDisconnectDifferentSubForVirtualDsdaDevice() {
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+
+ ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
+ SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
+ tcs.add(tc1);
+ TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
+ tcs, SUB2_HANDLE, mTelephonyManagerProxy);
+ assertFalse(tc1.wasDisconnected);
+ }
+
+
+ /**
+ * For calls on the same sub, the Dialer implements the 'swap' functionality to perform hold and
+ * unhold, so we do not additionally unhold when 'hold' button is pressed.
+ */
+ @Test
+ @SmallTest
+ public void testDontUnholdOnSameSubForVirtualDsdaDevice() {
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+
+ ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
+ Collection<Conference> conferences = new ArrayList<>();
+ SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
+ tcs.add(tc1);
+ TelephonyConnectionService.maybeUnholdCallsOnOtherSubs(
+ tcs, conferences, SUB1_HANDLE, mTelephonyManagerProxy);
+ assertFalse(tc1.wasUnheld);
+ }
+
+ /**
+ * Triggering 'Hold' on 1 call will unhold the other call for DSDA or Virtual DSDA
+ * enabled devices, effectively constituting 'swap' functionality.
+ */
+ @Test
+ @SmallTest
+ public void testUnholdOnOtherSubForVirtualDsdaDevice() {
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+
+ ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
+ SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
+ tcs.add(tc1);
+ TelephonyConnectionService.maybeUnholdCallsOnOtherSubs(
+ tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
+ assertTrue(tc1.wasUnheld);
+ }
+
+ /**
+ * Verifies hold/unhold behavior for a conference on the other sub. It does not disturb the
+ * individual connections that participate in the conference.
+ */
+ @Test
+ @SmallTest
+ public void testUnholdConferenceOnOtherSubForVirtualDsdaDevice() {
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+ SimpleTelephonyConnection tc1 =
+ createTestConnection(SUB1_HANDLE, 0, false);
+ SimpleTelephonyConnection tc2 =
+ createTestConnection(SUB1_HANDLE, 0, false);
+ List<android.telecom.Connection> conferenceParticipants = Arrays.asList(tc1, tc2);
+
+ SimpleConference testConference = createTestConference(SUB1_HANDLE, 0);
+ List<Conference> conferences = Arrays.asList(testConference);
+
+ TelephonyConnectionService.maybeUnholdCallsOnOtherSubs(
+ conferenceParticipants, conferences, SUB2_HANDLE, mTelephonyManagerProxy);
+
+ assertTrue(testConference.wasUnheld);
+ assertFalse(tc1.wasUnheld);
+ assertFalse(tc2.wasUnheld);
+ }
+
+ /**
+ * For DSDA devices, placing an outgoing call on a 2nd sub will hold the existing connection on
+ * the first sub.
+ */
+ @Test
+ @SmallTest
+ public void testHoldOnOtherSubForVirtualDsdaDevice() {
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+
+ ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
+ SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
+ tcs.add(tc1);
+ Conferenceable c = TelephonyConnectionService.maybeHoldCallsOnOtherSubs(
+ tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
+ assertTrue(c.equals(tc1));
+ assertTrue(tc1.wasHeld);
+ }
+
+ /**
+ * Verifies that TelephonyManager is used to determine whether a connection is Emergency when
+ * creating an outgoing connection.
+ */
+ @Test
+ @SmallTest
+ public void testIsEmergencyDeterminedByTelephonyManager() {
+ ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
+ .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
+ .setAddress(TEST_ADDRESS)
+ .build();
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(
+ PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+
+ verify(mTelephonyManagerProxy)
+ .isCurrentEmergencyNumber(TEST_ADDRESS.getSchemeSpecificPart());
+ }
+
+ @Test
+ public void testDomainSelectionCs() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(selectedDomain,
+ dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testDomainSelectionPs() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_PS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(selectedDomain,
+ dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testDomainSelectionCsForTty() throws Exception {
+ setupForCallTest();
+
+ ImsManager imsManager = Mockito.mock(ImsManager.class);
+ doReturn(false).when(imsManager).isNonTtyOrTtyOnVolteEnabled();
+ replaceInstance(TelephonyConnectionService.class,
+ "mImsManager", mTestConnectionService, imsManager);
+
+ setupForDialForDomainSelection(mPhone0, DOMAIN_PS, true);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mEmergencyStateTracker, times(1))
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mDomainSelectionResolver, times(0))
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyCallDomainSelectionConnection, times(0))
+ .createEmergencyConnection(any(), any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(DOMAIN_CS, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testDomainSelectionRedialCs() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int selectedDomain = DOMAIN_CS;
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
+
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, preciseDisconnectCause, null));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ Connection nc = Mockito.mock(Connection.class);
+ doReturn(nc).when(mPhone0).dial(anyString(), any(), any());
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(selectedDomain,
+ dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testDomainSelectionRedialPs() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int selectedDomain = DOMAIN_PS;
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
+
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, preciseDisconnectCause, null));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ Connection nc = Mockito.mock(Connection.class);
+ doReturn(nc).when(mPhone0).dial(anyString(), any(), any());
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(selectedDomain,
+ dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testDomainSelectionNormalRoutingEmergencyNumber() throws Exception {
+ setupForCallTest();
+ int selectedDomain = DOMAIN_PS;
+
+ EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ Collections.emptyList(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, false);
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+ doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
+ verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(
+ selectedDomain, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testDomainSelectionNormalToEmergencyCs() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int eccCategory = EMERGENCY_SERVICE_CATEGORY_POLICE;
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+ doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
+ c.setEmergencyServiceCategory(eccCategory);
+ c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
+
+ ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
+ assertTrue(mTestConnectionService.maybeReselectDomain(c,
+ preciseDisconnectCause, reasonInfo));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(selectedDomain,
+ dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ assertTrue(dialArgs.isEmergency);
+ assertEquals(eccCategory, dialArgs.eccCategory);
+ }
+
+ @Test
+ public void testDomainSelectionNormalToEmergencyPs() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int eccCategory = EMERGENCY_SERVICE_CATEGORY_POLICE;
+ int selectedDomain = DOMAIN_PS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+ doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
+ c.setEmergencyServiceCategory(eccCategory);
+ c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
+
+ ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
+ assertTrue(mTestConnectionService.maybeReselectDomain(c,
+ preciseDisconnectCause, reasonInfo));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(selectedDomain,
+ dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ assertTrue(dialArgs.isEmergency);
+ assertEquals(eccCategory, dialArgs.eccCategory);
+ }
+
+ @Test
+ public void testOnSelectionTerminatedPerm() throws Exception {
+ setupForCallTest();
+
+ doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+ doReturn(mPhone0).when(mEmergencyCallDomainSelectionConnection).getPhone();
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ doReturn(mImsPhone).when(mPhone0).getImsPhone();
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionConnection.DomainSelectionConnectionCallback.class);
+
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
+ any(), callbackCaptor.capture());
+
+ DomainSelectionConnection.DomainSelectionConnectionCallback callback =
+ callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ EmergencyCallDomainSelectionConnection ecdsc =
+ Mockito.mock(EmergencyCallDomainSelectionConnection.class);
+ doReturn(ecdsc).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+
+ callback.onSelectionTerminated(EMERGENCY_PERM_FAILURE);
+
+ ArgumentCaptor<DomainSelectionService.SelectionAttributes> attrCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionService.SelectionAttributes.class);
+
+ verify(ecdsc).createEmergencyConnection(attrCaptor.capture(), any());
+
+ DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
+
+ assertEquals(mPhone1.getPhoneId(), attr.getSlotId());
+ }
+
+ @Test
+ public void testOnSelectionTerminatedTemp() throws Exception {
+ setupForCallTest();
+
+ doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+ doReturn(mPhone0).when(mEmergencyCallDomainSelectionConnection).getPhone();
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ doReturn(mImsPhone).when(mPhone0).getImsPhone();
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionConnection.DomainSelectionConnectionCallback.class);
+
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
+ any(), callbackCaptor.capture());
+
+ DomainSelectionConnection.DomainSelectionConnectionCallback callback =
+ callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ EmergencyCallDomainSelectionConnection ecdsc =
+ Mockito.mock(EmergencyCallDomainSelectionConnection.class);
+ doReturn(ecdsc).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+
+ callback.onSelectionTerminated(EMERGENCY_TEMP_FAILURE);
+
+ ArgumentCaptor<DomainSelectionService.SelectionAttributes> attrCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionService.SelectionAttributes.class);
+
+ verify(ecdsc).createEmergencyConnection(attrCaptor.capture(), any());
+
+ DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
+
+ assertEquals(mPhone1.getPhoneId(), attr.getSlotId());
+ }
+
+ @Test
+ public void testOnSelectionTerminatedUnspecified() throws Exception {
+ setupForCallTest();
+
+ doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+ doReturn(mPhone0).when(mEmergencyCallDomainSelectionConnection).getPhone();
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ doReturn(mImsPhone).when(mPhone0).getImsPhone();
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
+ ArgumentCaptor.forClass(
+ DomainSelectionConnection.DomainSelectionConnectionCallback.class);
+
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(
+ any(), callbackCaptor.capture());
+
+ DomainSelectionConnection.DomainSelectionConnectionCallback callback =
+ callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ callback.onSelectionTerminated(ERROR_UNSPECIFIED);
+
+ verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
+ verify(mEmergencyStateTracker).endCall(eq(TELECOM_CALL_ID1));
+ }
+
+ @Test
+ public void testDomainSelectionLocalHangupStartEmergencyCall() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ CompletableFuture<Integer> future = new CompletableFuture<>();
+ doReturn(future).when(mEmergencyStateTracker)
+ .startEmergencyCall(any(), anyString(), eq(false));
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+
+ TelephonyConnection c = new TestTelephonyConnection();
+ c.setTelecomCallId(TELECOM_CALL_ID1);
+
+ // dialing is canceled
+ mTestConnectionService.onLocalHangup(c);
+
+ // startEmergencyCall has completed
+ future.complete(NOT_DISCONNECTED);
+
+ // verify that createEmergencyConnection is discarded
+ verify(mEmergencyCallDomainSelectionConnection, times(0))
+ .createEmergencyConnection(any(), any());
+ }
+
+ @Test
+ public void testDomainSelectionLocalHangupCreateEmergencyConnection() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ CompletableFuture<Integer> future = new CompletableFuture<>();
+ doReturn(future).when(mEmergencyCallDomainSelectionConnection)
+ .createEmergencyConnection(any(), any());
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ TelephonyConnection c = new TestTelephonyConnection();
+ c.setTelecomCallId(TELECOM_CALL_ID1);
+
+ // dialing is canceled
+ mTestConnectionService.onLocalHangup(c);
+
+ // domain selection has completed
+ future.complete(selectedDomain);
+
+ // verify that dialing is discarded
+ verify(mPhone0, times(0)).dial(anyString(), any(), any());
+ }
+
+ @Test
+ public void testDomainSelectionRedialLocalHangupReselectDomain() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int selectedDomain = DOMAIN_CS;
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
+ c.setTelecomCallId(TELECOM_CALL_ID1);
+
+ CompletableFuture<Integer> future = new CompletableFuture<>();
+ doReturn(future).when(mEmergencyCallDomainSelectionConnection)
+ .reselectDomain(any());
+
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, preciseDisconnectCause, null));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+
+ // dialing is canceled
+ mTestConnectionService.onLocalHangup(c);
+
+ // domain selection has completed
+ future.complete(selectedDomain);
+
+ // verify that dialing is discarded
+ verify(mPhone0, times(0)).dial(anyString(), any(), any());
+ }
+
+ @Test
+ public void testDomainSelectionNormalToEmergencyLocalHangupStartEmergencyCall()
+ throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int eccCategory = EMERGENCY_SERVICE_CATEGORY_POLICE;
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+ doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
+ c.setEmergencyServiceCategory(eccCategory);
+ c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
+ c.setTelecomCallId(TELECOM_CALL_ID1);
+
+ CompletableFuture<Integer> future = new CompletableFuture<>();
+ doReturn(future).when(mEmergencyStateTracker)
+ .startEmergencyCall(any(), anyString(), eq(false));
+
+ ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
+ assertTrue(mTestConnectionService.maybeReselectDomain(c,
+ preciseDisconnectCause, reasonInfo));
+
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+
+ // dialing is canceled
+ mTestConnectionService.onLocalHangup(c);
+
+ // startEmergencyCall has completed
+ future.complete(NOT_DISCONNECTED);
+
+ // verify that createEmergencyConnection is discarded
+ verify(mEmergencyCallDomainSelectionConnection, times(0))
+ .createEmergencyConnection(any(), any());
+ }
+
+ @Test
+ public void testDomainSelectionNormalToEmergencyLocalHangupCreateEmergencyConnection()
+ throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause = com.android.internal.telephony.CallFailCause.ERROR_UNSPECIFIED;
+ int disconnectCause = android.telephony.DisconnectCause.ERROR_UNSPECIFIED;
+ int eccCategory = EMERGENCY_SERVICE_CATEGORY_POLICE;
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+ doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
+ c.setEmergencyServiceCategory(eccCategory);
+ c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
+ c.setTelecomCallId(TELECOM_CALL_ID1);
+
+ CompletableFuture<Integer> future = new CompletableFuture<>();
+ doReturn(future).when(mEmergencyCallDomainSelectionConnection)
+ .createEmergencyConnection(any(), any());
+
+ ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
+ assertTrue(mTestConnectionService.maybeReselectDomain(c,
+ preciseDisconnectCause, reasonInfo));
+
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ // dialing is canceled
+ mTestConnectionService.onLocalHangup(c);
+
+ // domain selection has completed
+ future.complete(selectedDomain);
+
+ // verify that dialing is discarded
+ verify(mPhone0, times(0)).dial(anyString(), any(), any());
+ }
+
+ @Test
+ public void testDomainSelectionListenOriginalConnectionConfigChange() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_PS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any(), eq(mPhone0));
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+ verify(mPhone0).dial(anyString(), any(), any());
+
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ c.setTelecomCallId(TELECOM_CALL_ID1);
+ c.setIsImsConnection(true);
+ Connection orgConn = c.getOriginalConnection();
+ doReturn(PhoneConstants.PHONE_TYPE_IMS).when(orgConn).getPhoneType();
+
+ TelephonyConnection.TelephonyConnectionListener connectionListener =
+ mTestConnectionService.getEmergencyConnectionListener();
+ TelephonyConnection.TelephonyConnectionListener connectionSatelliteListener =
+ mTestConnectionService.getEmergencyConnectionSatelliteListener();
+
+ connectionListener.onOriginalConnectionConfigured(c);
+
+ verify(mEmergencyStateTracker, times(1)).onEmergencyCallDomainUpdated(
+ eq(PhoneConstants.PHONE_TYPE_IMS), eq(TELECOM_CALL_ID1));
+
+ verify(mEmergencyStateTracker, times(0)).onEmergencyCallStateChanged(
+ any(), eq(TELECOM_CALL_ID1));
+ verify(mSatelliteSOSMessageRecommender, times(0))
+ .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
+
+ c.setActive();
+ doReturn(Call.State.ACTIVE).when(orgConn).getState();
+ connectionListener.onStateChanged(c, c.getState());
+ connectionSatelliteListener.onStateChanged(c, c.getState());
+
+ // ACTIVE sate is notified
+ verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
+ eq(Call.State.ACTIVE), eq(TELECOM_CALL_ID1));
+ verify(mSatelliteSOSMessageRecommender, times(1))
+ .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1),
+ eq(android.telecom.Connection.STATE_ACTIVE));
+
+ // state change to HOLDING
+ c.setOnHold();
+ doReturn(Call.State.HOLDING).when(orgConn).getState();
+ connectionListener.onStateChanged(c, c.getState());
+ connectionSatelliteListener.onStateChanged(c, c.getState());
+
+ // state change not notified any more after CONNECTED once
+ verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
+ any(), eq(TELECOM_CALL_ID1));
+ verify(mSatelliteSOSMessageRecommender, times(1))
+ .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
+
+ // state change to ACTIVE again
+ c.setActive();
+ doReturn(Call.State.ACTIVE).when(orgConn).getState();
+ connectionListener.onStateChanged(c, c.getState());
+ connectionSatelliteListener.onStateChanged(c, c.getState());
+
+ // state change not notified any more after CONNECTED once
+ verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
+ any(), eq(TELECOM_CALL_ID1));
+ verify(mSatelliteSOSMessageRecommender, times(1))
+ .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
+
+ // SRVCC happens
+ c.setIsImsConnection(false);
+ orgConn = c.getOriginalConnection();
+ doReturn(PhoneConstants.PHONE_TYPE_GSM).when(orgConn).getPhoneType();
+ connectionListener.onOriginalConnectionConfigured(c);
+
+ // domain change notified
+ verify(mEmergencyStateTracker, times(1)).onEmergencyCallDomainUpdated(
+ eq(PhoneConstants.PHONE_TYPE_GSM), eq(TELECOM_CALL_ID1));
+
+ // state change to DISCONNECTED
+ c.setDisconnected(null);
+ doReturn(Call.State.DISCONNECTED).when(orgConn).getState();
+ connectionListener.onStateChanged(c, c.getState());
+ connectionSatelliteListener.onStateChanged(c, c.getState());
+
+ // state change not notified
+ verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
+ any(), eq(TELECOM_CALL_ID1));
+ verify(mSatelliteSOSMessageRecommender, times(1))
+ .onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
+ }
+
+ @Test
+ public void testDomainSelectionTempFailure() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause =
+ com.android.internal.telephony.CallFailCause.EMERGENCY_TEMP_FAILURE;
+ int disconnectCause = android.telephony.DisconnectCause.EMERGENCY_TEMP_FAILURE;
+ int selectedDomain = DOMAIN_CS;
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
+
+ doReturn(new CompletableFuture()).when(mEmergencyCallDomainSelectionConnection)
+ .reselectDomain(any());
+
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, preciseDisconnectCause, null));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+ }
+
+ @Test
+ public void testDomainSelectionPermFailure() throws Exception {
+ setupForCallTest();
+
+ int preciseDisconnectCause =
+ com.android.internal.telephony.CallFailCause.EMERGENCY_PERM_FAILURE;
+ int disconnectCause = android.telephony.DisconnectCause.EMERGENCY_PERM_FAILURE;
+ int selectedDomain = DOMAIN_CS;
+
+ TestTelephonyConnection c = setupForReDialForDomainSelection(
+ mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
+
+ doReturn(new CompletableFuture()).when(mEmergencyCallDomainSelectionConnection)
+ .reselectDomain(any());
+
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, preciseDisconnectCause, null));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+ }
+
+ @Test
+ public void testDomainSelectionWithMmiCode() {
+ //UT domain selection should not be handled by new domain selector.
+ doNothing().when(mContext).startActivity(any());
+ setupForCallTest();
+ setupForDialForDomainSelection(mPhone0, 0, false);
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "*%2321%23", TELECOM_CALL_ID1));
+
+ verifyZeroInteractions(mNormalCallDomainSelectionConnection);
+ }
+
+ @Test
+ public void testNormalCallPsDomainSelection() throws Exception {
+ setupForCallTest();
+ int selectedDomain = DOMAIN_PS;
+ setupForDialForDomainSelection(mPhone0, selectedDomain, false);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
+ verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
+ verify(mSatelliteSOSMessageRecommender, never()).onEmergencyCallStarted(any(), any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(
+ selectedDomain, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ @Test
+ public void testNormalCallCsDomainSelection() throws Exception {
+ setupForCallTest();
+ int selectedDomain = DOMAIN_CS;
+ setupForDialForDomainSelection(mPhone0, selectedDomain, false);
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(false));
+ verify(mNormalCallDomainSelectionConnection).createNormalConnection(any(), any());
+ verify(mSatelliteSOSMessageRecommender, never()).onEmergencyCallStarted(any(), any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
+ DialArgs dialArgs = argsCaptor.getValue();
+ assertNotNull("DialArgs param is null", dialArgs);
+ assertNotNull("intentExtras is null", dialArgs.intentExtras);
+ assertTrue(dialArgs.intentExtras.containsKey(PhoneConstants.EXTRA_DIAL_DOMAIN));
+ assertEquals(
+ selectedDomain, dialArgs.intentExtras.getInt(PhoneConstants.EXTRA_DIAL_DOMAIN, -1));
+ }
+
+ private void setupForDialForDomainSelection(Phone mockPhone, int domain, boolean isEmergency) {
+ if (isEmergency) {
+ doReturn(mEmergencyCallDomainSelectionConnection).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), anyInt(), eq(true));
+ doReturn(CompletableFuture.completedFuture(domain))
+ .when(mEmergencyCallDomainSelectionConnection)
+ .createEmergencyConnection(any(), any());
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+ } else {
+ doReturn(mNormalCallDomainSelectionConnection).when(mDomainSelectionResolver)
+ .getDomainSelectionConnection(any(), eq(SELECTOR_TYPE_CALLING), eq(false));
+ doReturn(CompletableFuture.completedFuture(domain))
+ .when(mNormalCallDomainSelectionConnection)
+ .createNormalConnection(any(), any());
+ doReturn(false).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+ }
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ doReturn(mImsPhone).when(mockPhone).getImsPhone();
+ }
+
+ private TestTelephonyConnection setupForReDialForDomainSelection(
+ Phone mockPhone, int domain, int preciseDisconnectCause,
+ int disconnectCause, boolean fromEmergency) throws Exception {
+ try {
+ if (fromEmergency) {
+ doReturn(CompletableFuture.completedFuture(domain))
+ .when(mEmergencyCallDomainSelectionConnection)
+ .reselectDomain(any());
+ replaceInstance(TelephonyConnectionService.class,
+ "mEmergencyCallDomainSelectionConnection",
+ mTestConnectionService, mEmergencyCallDomainSelectionConnection);
+ replaceInstance(TelephonyConnectionService.class, "mEmergencyCallId",
+ mTestConnectionService, TELECOM_CALL_ID1);
+ } else {
+ doReturn(CompletableFuture.completedFuture(domain))
+ .when(mNormalCallDomainSelectionConnection).reselectDomain(any());
+ replaceInstance(TelephonyConnectionService.class, "mDomainSelectionConnection",
+ mTestConnectionService, mNormalCallDomainSelectionConnection);
+ }
+ } catch (Exception e) {
+ // This shouldn't happen
+ fail();
+ }
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ c.setTelecomCallId(TELECOM_CALL_ID1);
+ c.setMockPhone(mockPhone);
+ c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
+
+ Connection oc = c.getOriginalConnection();
+ doReturn(disconnectCause).when(oc).getDisconnectCause();
+ doReturn(preciseDisconnectCause).when(oc).getPreciseDisconnectCause();
+
+ return c;
+ }
+
private SimpleTelephonyConnection createTestConnection(PhoneAccountHandle handle,
int properties, boolean isEmergency) {
SimpleTelephonyConnection connection = new SimpleTelephonyConnection();
@@ -1317,6 +2553,12 @@
return connection;
}
+ private SimpleConference createTestConference(PhoneAccountHandle handle, int properties) {
+ SimpleConference conference = new SimpleConference(handle);
+ conference.setConnectionProperties(properties);
+ return conference;
+ }
+
/**
* Setup the mess of mocks for {@link #testSecondCallSameSubWontDisconnect()} and
* {@link #testIncomingDoesntRequestDisconnect()}.
@@ -1484,21 +2726,26 @@
// Setup 2 SIM device
private void setupDeviceConfig(Phone slot0Phone, Phone slot1Phone, int defaultVoicePhoneId) {
when(mTelephonyManagerProxy.getPhoneCount()).thenReturn(2);
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(false);
when(mSubscriptionManagerProxy.getDefaultVoicePhoneId()).thenReturn(defaultVoicePhoneId);
when(mPhoneFactoryProxy.getPhone(eq(SLOT_0_PHONE_ID))).thenReturn(slot0Phone);
when(mPhoneFactoryProxy.getPhone(eq(SLOT_1_PHONE_ID))).thenReturn(slot1Phone);
}
+ private void setDefaultDataPhoneId(int defaultDataPhoneId) {
+ when(mSubscriptionManagerProxy.getDefaultDataPhoneId()).thenReturn(defaultDataPhoneId);
+ }
+
private void setPhoneRadioAccessFamily(Phone phone, int radioAccessFamily) {
when(phone.getRadioAccessFamily()).thenReturn(radioAccessFamily);
}
- private void setPhoneSlotState(int slotId, int slotState) {
- when(mSubscriptionManagerProxy.getSimStateForSlotIdx(slotId)).thenReturn(slotState);
+ private void setEmergencySmsMode(Phone phone, boolean isInEmergencySmsMode) {
+ when(phone.isInEmergencySmsMode()).thenReturn(isInEmergencySmsMode);
}
- private void setSlotHasIccCard(int slotId, boolean isInserted) {
- when(mTelephonyManagerProxy.hasIccCard(slotId)).thenReturn(isInserted);
+ private void setPhoneSlotState(int slotId, int slotState) {
+ when(mSubscriptionManagerProxy.getSimStateForSlotIdx(slotId)).thenReturn(slotState);
}
private void setDefaultPhone(Phone phone) {
@@ -1518,4 +2765,18 @@
fail();
}
}
+
+ private ConnectionRequest createConnectionRequest(
+ PhoneAccountHandle accountHandle, String address, String callId) {
+ return new ConnectionRequest.Builder()
+ .setAccountHandle(accountHandle)
+ .setAddress(Uri.parse("tel:" + address))
+ .setExtras(new Bundle())
+ .setTelecomCallId(callId)
+ .build();
+ }
+
+ private Executor getExecutor() {
+ return Runnable::run;
+ }
}
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
index 388fd29..bf9fa01 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionTest.java
@@ -1,5 +1,10 @@
package com.android.services.telephony;
+import static android.telecom.Connection.STATE_DISCONNECTED;
+import static android.telephony.ims.ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED;
+import static android.telephony.ims.ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL;
+import static android.telephony.ims.ImsReasonInfo.EXTRA_CODE_CALL_RETRY_EMERGENCY;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -7,6 +12,9 @@
import static junit.framework.Assert.fail;
import static junit.framework.TestCase.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@@ -14,9 +22,12 @@
import static org.mockito.Mockito.when;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.telecom.Connection;
import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
+import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsReasonInfo;
import androidx.test.runner.AndroidJUnit4;
@@ -33,10 +44,14 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+
@RunWith(AndroidJUnit4.class)
public class TelephonyConnectionTest {
@Mock
private ImsPhoneConnection mImsPhoneConnection;
+ @Mock
+ private TelephonyConnectionService mTelephonyConnectionService;
@Before
public void setUp() throws Exception {
@@ -212,4 +227,144 @@
fail("refreshConferenceSupported threw ClassCastException");
}
}
+
+ /**
+ * Tests TelephonyConnection#getCarrierConfig never returns a null given all cases that can
+ * cause a potential null.
+ */
+ @Test
+ public void testGetCarrierConfigBehaviorWithNull() throws Exception {
+ TestTelephonyConnectionSimple c = new TestTelephonyConnectionSimple();
+
+ // case: return a valid carrier config (good case)
+ when(c.mPhoneGlobals.getCarrierConfigForSubId(c.getPhone().getSubId())).
+ thenReturn(CarrierConfigManager.getDefaultConfig());
+ assertNotNull(c.getCarrierConfig());
+
+ // case: PhoneGlobals.getInstance().getCarrierConfigForSubId(int) returns null
+ when(c.mPhoneGlobals.getCarrierConfigForSubId(c.getPhone().getSubId()))
+ .thenReturn(null);
+ assertNotNull(c.getCarrierConfig());
+
+ // case: phone is null
+ c.setMockPhone(null);
+ assertNull(c.getPhone());
+ assertNotNull(c.getCarrierConfig());
+ }
+
+ /**
+ * Tests the behavior of TelephonyConnection#isRttMergeSupported(@NonNull PersistableBundle).
+ * Note, the function should be able to handle an empty PersistableBundle and should NEVER
+ * receive a null object as denoted in by @NonNull annotation.
+ */
+ @Test
+ public void testIsRttMergeSupportedBehavior() {
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ // ensure isRttMergeSupported(PersistableBundle) does not throw NPE when given an Empty PB
+ assertFalse(c.isRttMergeSupported(new PersistableBundle()));
+
+ // simulate the passing situation
+ c.getCarrierConfigBundle().putBoolean(
+ CarrierConfigManager.KEY_ALLOW_MERGING_RTT_CALLS_BOOL,
+ true);
+ assertTrue(c.isRttMergeSupported(c.getCarrierConfig()));
+ }
+
+ @Test
+ public void testDomainSelectionDisconnected() {
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ c.setOriginalConnection(mImsPhoneConnection);
+ doReturn(Call.State.DISCONNECTED).when(mImsPhoneConnection)
+ .getState();
+ c.setTelephonyConnectionService(mTelephonyConnectionService);
+ c.updateState();
+
+ verify(mTelephonyConnectionService)
+ .maybeReselectDomain(any(), anyInt(), any());
+ }
+
+ @Test
+ public void testDomainSelectionDisconnected_NoRedial() {
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ c.setOriginalConnection(mImsPhoneConnection);
+ doReturn(Call.State.DISCONNECTED).when(mImsPhoneConnection)
+ .getState();
+ c.setTelephonyConnectionService(mTelephonyConnectionService);
+ doReturn(false).when(mTelephonyConnectionService)
+ .maybeReselectDomain(any(), anyInt(), any());
+ c.updateState();
+
+ assertEquals(STATE_DISCONNECTED, c.getState());
+ }
+
+ @Test
+ public void testDomainSelectionDisconnected_Redial() {
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ c.setOriginalConnection(mImsPhoneConnection);
+
+ doReturn(Call.State.DISCONNECTED).when(mImsPhoneConnection)
+ .getState();
+ c.setTelephonyConnectionService(mTelephonyConnectionService);
+ doReturn(true).when(mTelephonyConnectionService)
+ .maybeReselectDomain(any(), anyInt(), any());
+ c.resetOriginalConnectionCleared();
+ c.updateState();
+
+ assertNotEquals(STATE_DISCONNECTED, c.getState());
+ assertTrue(c.isOriginalConnectionCleared());
+ }
+
+ @Test
+ public void testDomainSelectionDisconnected_AlternateService() {
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ c.setOriginalConnection(mImsPhoneConnection);
+ c.setIsImsConnection(true);
+ doReturn(Call.State.DISCONNECTED).when(mImsPhoneConnection)
+ .getState();
+ doReturn(new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null))
+ .when(mImsPhoneConnection).getImsReasonInfo();
+ doReturn(getEmergencyNumber(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE))
+ .when(mImsPhoneConnection).getEmergencyNumberInfo();
+ c.setTelephonyConnectionService(mTelephonyConnectionService);
+ doReturn(true).when(mTelephonyConnectionService)
+ .maybeReselectDomain(any(), anyInt(), any());
+ c.updateState();
+
+ Integer serviceCategory = c.getEmergencyServiceCategory();
+
+ assertNotNull(serviceCategory);
+ assertEquals(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE,
+ serviceCategory.intValue());
+ }
+
+ @Test
+ public void testDomainSelectionDisconnected_SilentRedialEmergency() {
+ TestTelephonyConnection c = new TestTelephonyConnection();
+ c.setOriginalConnection(mImsPhoneConnection);
+ c.setIsImsConnection(true);
+ doReturn(Call.State.DISCONNECTED).when(mImsPhoneConnection)
+ .getState();
+ doReturn(new ImsReasonInfo(CODE_LOCAL_CALL_CS_RETRY_REQUIRED,
+ EXTRA_CODE_CALL_RETRY_EMERGENCY, null))
+ .when(mImsPhoneConnection).getImsReasonInfo();
+ doReturn(getEmergencyNumber(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE))
+ .when(mImsPhoneConnection).getEmergencyNumberInfo();
+ c.setTelephonyConnectionService(mTelephonyConnectionService);
+ doReturn(true).when(mTelephonyConnectionService)
+ .maybeReselectDomain(any(), anyInt(), any());
+ c.updateState();
+
+ Integer serviceCategory = c.getEmergencyServiceCategory();
+
+ assertNotNull(serviceCategory);
+ assertEquals(EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_FIRE_BRIGADE,
+ serviceCategory.intValue());
+ }
+
+ private EmergencyNumber getEmergencyNumber(int eccCategory) {
+ return new EmergencyNumber("", "", "", eccCategory,
+ new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
+ }
}
diff --git a/tests/src/com/android/services/telephony/TelephonyManagerTest.java b/tests/src/com/android/services/telephony/TelephonyManagerTest.java
index cf1ae8f..20c062f 100644
--- a/tests/src/com/android/services/telephony/TelephonyManagerTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyManagerTest.java
@@ -15,11 +15,16 @@
*/
package com.android.services.telephony;
-
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeFalse;
+import static org.junit.Assume.assumeTrue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -28,6 +33,8 @@
import android.app.PropertyInvalidatedCache;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
import android.telecom.PhoneAccountHandle;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -37,6 +44,8 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.IPhoneSubInfo;
+import com.android.internal.telephony.PhoneConstants;
import org.junit.After;
import org.junit.Before;
@@ -47,6 +56,10 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
/** Unit tests for {@link TelephonyManager}. */
@RunWith(AndroidJUnit4.class)
@@ -61,8 +74,10 @@
private static final int TEST_SUBID_2 = 2;
private ITelephony mMockITelephony;
+ private IPhoneSubInfo mMockIPhoneSubInfo;
private SubscriptionManager mMockSubscriptionManager;
private Context mMockContext;
+ private final PackageManager mPackageManager = mock(PackageManager.class);
private TelephonyManager mTelephonyManager;
@@ -89,18 +104,23 @@
}
return null;
}
+ @Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
};
@Before
public void setUp() throws Exception {
mMockITelephony = mock(ITelephony.class);
+ mMockIPhoneSubInfo = mock(IPhoneSubInfo.class);
mMockSubscriptionManager = mock(SubscriptionManager.class);
mMockContext = mock(Context.class);
when(mMockContext.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
.thenReturn(mMockSubscriptionManager);
-
mTelephonyManager = new TelephonyManager(mContext);
TelephonyManager.setupITelephonyForTest(mMockITelephony);
+ TelephonyManager.setupIPhoneSubInfoForTest(mMockIPhoneSubInfo);
TelephonyManager.enableServiceHandleCaching();
}
@@ -218,4 +238,61 @@
verify(mMockITelephony, times(1)).getSubIdForPhoneAccountHandle(eq(TEST_HANDLE2),
anyString(), anyString());
}
-}
+
+ @Test
+ public void testGetSimServiceTable_USIM() throws RemoteException {
+ assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, true));
+ when(mMockIPhoneSubInfo.getSimServiceTable(anyInt(), anyInt())).thenReturn("12345");
+ assertEquals("12345", mTelephonyManager.getSimServiceTable(PhoneConstants.APPTYPE_USIM));
+ verify(mMockIPhoneSubInfo, times(1)).getSimServiceTable(anyInt(), anyInt());
+ }
+
+ @Test
+ public void testGetSimServiceTable_ISIM() throws RemoteException {
+ when(mMockIPhoneSubInfo.getIsimIst(anyInt())).thenReturn("12345");
+ assertEquals("12345", mTelephonyManager.getSimServiceTable(PhoneConstants.APPTYPE_ISIM));
+ verify(mMockIPhoneSubInfo, times(1)).getIsimIst(anyInt());
+ }
+
+ @Test
+ public void testGetSimServiceTable_RUSIM() throws RemoteException {
+ assumeFalse(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, false));
+ assertEquals(null, mTelephonyManager.getSimServiceTable(PhoneConstants.APPTYPE_RUIM));
+ }
+
+ private boolean hasFeature(String feature, boolean status) {
+ doReturn(status)
+ .when(mPackageManager).hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION);
+ return mContext.getPackageManager().hasSystemFeature(feature);
+ }
+
+ @Test
+ public void getPrimaryImei() throws RemoteException {
+ assumeTrue(hasFeature(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, true));
+ when(mMockITelephony.getPrimaryImei(anyString(), anyString())).thenReturn(
+ "12345");
+ assertEquals("12345", mTelephonyManager.getPrimaryImei());
+ verify(mMockITelephony, times(1)).getPrimaryImei(anyString(), anyString());
+ }
+
+ /**
+ * Verify calling getCarrierRestrictionStatus() with out exception
+ */
+ @Test
+ public void getCarrierRestrictionStatus() {
+ int TIMEOUT = 2 * 60; // 2 minutes
+ LinkedBlockingQueue<Integer> carrierRestrictionStatusResult = new LinkedBlockingQueue<>(1);
+ Executor executor = Executors.newSingleThreadExecutor();
+ mTelephonyManager.getCarrierRestrictionStatus(executor,
+ carrierRestrictionStatusResult::offer);
+ executor.execute(() -> {
+ try {
+ carrierRestrictionStatusResult.poll(TIMEOUT, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ fail();
+ }
+ });
+
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index e149d3b..d91435c 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -50,8 +50,6 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import java.util.ArrayList;
import java.util.List;
@@ -107,6 +105,7 @@
private List<Bundle> mLastConnectionEventExtras = new ArrayList<>();
private Object mLock = new Object();
private PersistableBundle mCarrierConfig = new PersistableBundle();
+ private boolean mOriginalConnectionCleared;
@Override
public com.android.internal.telephony.Connection getOriginalConnection() {
@@ -211,7 +210,15 @@
@Override
void clearOriginalConnection() {
- // Do nothing since the original connection is mock object
+ mOriginalConnectionCleared = true;
+ }
+
+ boolean isOriginalConnectionCleared() {
+ return mOriginalConnectionCleared;
+ }
+
+ void resetOriginalConnectionCleared() {
+ mOriginalConnectionCleared = false;
}
@Override
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnectionSimple.java b/tests/src/com/android/services/telephony/TestTelephonyConnectionSimple.java
new file mode 100644
index 0000000..9dc2551
--- /dev/null
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnectionSimple.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.AttributionSource;
+import android.content.Context;
+import android.os.Process;
+import android.telephony.TelephonyManager;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneConstants;
+import com.android.phone.PhoneGlobals;
+
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class TestTelephonyConnectionSimple extends TelephonyConnection{
+
+ @Mock
+ Context mMockContext;
+
+ @Mock
+ PhoneGlobals mPhoneGlobals;
+
+ private Phone mMockPhone;
+
+ public TelephonyConnection cloneConnection() {
+ return this;
+ }
+
+ public TestTelephonyConnectionSimple(){
+ super(null, null, android.telecom.Call.Details.DIRECTION_INCOMING);
+ MockitoAnnotations.initMocks(this);
+
+ AttributionSource attributionSource = new AttributionSource.Builder(
+ Process.myUid()).build();
+
+ mMockPhone = mock(Phone.class);
+ mMockContext = mock(Context.class);
+ mPhoneGlobals = mock(PhoneGlobals.class);
+
+ when(mMockPhone.getSubId()).thenReturn(1);
+ }
+
+ public void setMockPhone(Phone newPhone) {
+ mMockPhone = newPhone;
+ }
+
+ @Override
+ public Phone getPhone() {
+ return mMockPhone;
+ }
+
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/CrossSimRedialingControllerTest.java b/tests/src/com/android/services/telephony/domainselection/CrossSimRedialingControllerTest.java
new file mode 100644
index 0000000..a32329d
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/CrossSimRedialingControllerTest.java
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2023 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.domainselection;
+
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.REDIAL_TIMER_DISABLED;
+import static android.telephony.PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
+import static android.telephony.PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE;
+
+import static com.android.services.telephony.domainselection.CrossSimRedialingController.MSG_CROSS_STACK_TIMEOUT;
+import static com.android.services.telephony.domainselection.CrossSimRedialingController.MSG_QUICK_CROSS_STACK_TIMEOUT;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.testing.TestableLooper;
+import android.util.Log;
+
+import com.android.TestContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for CrossSimRedialingController
+ */
+public class CrossSimRedialingControllerTest {
+ private static final String TAG = "CrossSimRedialingControllerTest";
+
+ private static final int SLOT_0 = 0;
+ private static final int SLOT_1 = 1;
+
+ private static final String TELECOM_CALL_ID1 = "TC1";
+ private static final String TEST_EMERGENCY_NUMBER = "911";
+
+ @Mock private CarrierConfigManager mCarrierConfigManager;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private EmergencyCallDomainSelector mEcds;
+ @Mock private CrossSimRedialingController.EmergencyNumberHelper mEmergencyNumberHelper;
+
+ private Context mContext;
+
+ private HandlerThread mHandlerThread;
+ private TestableLooper mLooper;
+ private CrossSimRedialingController mCsrController;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext() {
+ @Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (serviceClass == TelephonyManager.class) {
+ return Context.TELEPHONY_SERVICE;
+ } else if (serviceClass == CarrierConfigManager.class) {
+ return Context.CARRIER_CONFIG_SERVICE;
+ }
+ return super.getSystemServiceName(serviceClass);
+ }
+
+ @Override
+ public String getOpPackageName() {
+ return "";
+ }
+ };
+
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ mHandlerThread = new HandlerThread("CrossSimRedialingControllerTest");
+ mHandlerThread.start();
+
+ try {
+ mLooper = new TestableLooper(mHandlerThread.getLooper());
+ } catch (Exception e) {
+ logd("Unable to create looper from handler.");
+ }
+
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ when(mTelephonyManager.createForSubscriptionId(anyInt()))
+ .thenReturn(mTelephonyManager);
+ when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+ doReturn(TelephonyManager.SIM_STATE_READY)
+ .when(mTelephonyManager).getSimState(anyInt());
+
+ mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+ doReturn(getDefaultPersistableBundle()).when(mCarrierConfigManager)
+ .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
+
+ doReturn(true).when(mEmergencyNumberHelper).isEmergencyNumber(anyInt(), anyString());
+
+ doReturn(SLOT_0).when(mEcds).getSlotId();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mCsrController != null) {
+ mCsrController.destroy();
+ mCsrController = null;
+ }
+
+ if (mLooper != null) {
+ mLooper.destroy();
+ mLooper = null;
+ }
+ }
+
+ @Test
+ public void testDefaultStartTimerInService() throws Exception {
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
+ processAllMessages();
+
+ verify(mEcds).notifyCrossStackTimerExpired();
+ }
+
+ @Test
+ public void testDefaultStartTimerInServiceRoaming() throws Exception {
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = true;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testDefaultStartTimerOutOfService() throws Exception {
+ createController();
+
+ boolean inService = false;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testDefaultStartTimerOutOfServiceRoaming() throws Exception {
+ createController();
+
+ boolean inService = false;
+ boolean inRoaming = true;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testQuickStartTimerInService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
+ doReturn(bundle).when(mCarrierConfigManager)
+ .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
+
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.sendEmptyMessage(MSG_QUICK_CROSS_STACK_TIMEOUT);
+ processAllMessages();
+
+ verify(mEcds).notifyCrossStackTimerExpired();
+ }
+
+ @Test
+ public void testQuickStartTimerInServiceRoaming() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
+ doReturn(bundle).when(mCarrierConfigManager)
+ .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
+
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = true;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testQuickStartTimerOutOfService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
+ doReturn(bundle).when(mCarrierConfigManager)
+ .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
+
+ createController();
+
+ boolean inService = false;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testQuickStartTimerOutOfServiceRoaming() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
+ doReturn(bundle).when(mCarrierConfigManager)
+ .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
+
+ createController();
+
+ boolean inService = false;
+ boolean inRoaming = true;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testNoNormalStartTimerInService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);
+ doReturn(bundle).when(mCarrierConfigManager)
+ .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
+
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testQuickWhenInServiceStartTimerOutOfService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
+ bundle.putBoolean(KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL, true);
+ doReturn(bundle).when(mCarrierConfigManager)
+ .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
+
+ createController();
+
+ boolean inService = false;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertFalse(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testQuickNoNormalStartTimerInService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, 3);
+ bundle.putInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT, REDIAL_TIMER_DISABLED);
+ doReturn(bundle).when(mCarrierConfigManager)
+ .getConfigForSubId(anyInt(), ArgumentMatchers.<String>any());
+
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_QUICK_CROSS_STACK_TIMEOUT));
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testDefaultSlot0ThenSlot1() throws Exception {
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.removeMessages(MSG_CROSS_STACK_TIMEOUT);
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ doReturn(SLOT_1).when(mEcds).getSlotId();
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+ }
+
+ @Test
+ public void testDefaultSlot0PermThenSlot1Timeout() throws Exception {
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.notifyCallFailure(EMERGENCY_PERM_FAILURE);
+ mCsrController.stopTimer();
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ doReturn(SLOT_1).when(mEcds).getSlotId();
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
+ processAllMessages();
+
+ verify(mEcds, times(0)).notifyCrossStackTimerExpired();
+ }
+
+ @Test
+ public void testDefaultSlot0TempThenSlot1Timeout() throws Exception {
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.notifyCallFailure(EMERGENCY_TEMP_FAILURE);
+ mCsrController.stopTimer();
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ doReturn(SLOT_1).when(mEcds).getSlotId();
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
+ processAllMessages();
+
+ verify(mEcds).notifyCrossStackTimerExpired();
+ }
+
+ @Test
+ public void testDefaultSlot0TempThenSlot1TimeoutNotEmergencyNumber() throws Exception {
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.notifyCallFailure(EMERGENCY_TEMP_FAILURE);
+ mCsrController.stopTimer();
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ doReturn(SLOT_1).when(mEcds).getSlotId();
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ doReturn(false).when(mEmergencyNumberHelper).isEmergencyNumber(anyInt(), anyString());
+ mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
+ processAllMessages();
+
+ verify(mEcds, times(0)).notifyCrossStackTimerExpired();
+ }
+
+ @Test
+ public void testDefaultSlot0TempThenSlot1TimeoutPinLocked() throws Exception {
+ createController();
+
+ boolean inService = true;
+ boolean inRoaming = false;
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ mCsrController.notifyCallFailure(EMERGENCY_TEMP_FAILURE);
+ mCsrController.stopTimer();
+ assertFalse(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ doReturn(SLOT_1).when(mEcds).getSlotId();
+ mCsrController.startTimer(mContext, mEcds, TELECOM_CALL_ID1,
+ TEST_EMERGENCY_NUMBER, inService, inRoaming, 2);
+
+ assertTrue(mCsrController.hasMessages(MSG_CROSS_STACK_TIMEOUT));
+
+ doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+ .when(mTelephonyManager).getSimState(anyInt());
+ mCsrController.sendEmptyMessage(MSG_CROSS_STACK_TIMEOUT);
+ processAllMessages();
+
+ verify(mEcds, times(0)).notifyCrossStackTimerExpired();
+ }
+
+ private void createController() throws Exception {
+ mCsrController = new CrossSimRedialingController(mContext,
+ mHandlerThread.getLooper(), mEmergencyNumberHelper);
+ }
+
+ private static PersistableBundle getDefaultPersistableBundle() {
+ return getPersistableBundle(0, 120, false);
+ }
+
+ private static PersistableBundle getPersistableBundle(
+ int quickTimer, int timer, boolean startQuickInService) {
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putInt(KEY_QUICK_CROSS_STACK_REDIAL_TIMER_SEC_INT, quickTimer);
+ bundle.putInt(KEY_CROSS_STACK_REDIAL_TIMER_SEC_INT, timer);
+ bundle.putBoolean(KEY_START_QUICK_CROSS_STACK_REDIAL_TIMER_WHEN_REGISTERED_BOOL,
+ startQuickInService);
+
+ return bundle;
+ }
+
+ private void processAllMessages() {
+ while (!mLooper.getLooper().getQueue().isIdle()) {
+ mLooper.processAllMessages();
+ }
+ }
+
+ private static void logd(String str) {
+ Log.d(TAG, str);
+ }
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/DomainSelectorBaseTest.java b/tests/src/com/android/services/telephony/domainselection/DomainSelectorBaseTest.java
new file mode 100644
index 0000000..74c3311
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/DomainSelectorBaseTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.TransportSelectorCallback;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TestContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for DomainSelectorBase.
+ */
+@RunWith(AndroidJUnit4.class)
+public class DomainSelectorBaseTest {
+ public class TestDomainSelectorBase extends DomainSelectorBase {
+ public TestDomainSelectorBase(Context context, int slotId, int subId,
+ @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
+ @NonNull DomainSelectorBase.DestroyListener listener, String logTag) {
+ super(context, slotId, subId, looper, imsStateTracker, listener, logTag);
+ }
+
+ @Override
+ public void cancelSelection() {
+ // No operations.
+ }
+
+ @Override
+ public void reselectDomain(@NonNull SelectionAttributes attr) {
+ // No operations.
+ }
+
+ @Override
+ public void finishSelection() {
+ // No operations.
+ }
+
+ @Override
+ public void selectDomain(SelectionAttributes attr, TransportSelectorCallback callback) {
+ // No operations.
+ }
+ }
+
+ private static final String TAG = DomainSelectorBaseTest.class.getSimpleName();
+ private static final int SLOT_0 = 0;
+ private static final int SUB_1 = 1;
+
+ @Mock private DomainSelectorBase.DestroyListener mDomainSelectorDestroyListener;
+ @Mock private ImsStateTracker mImsStateTracker;
+
+ private Context mContext;
+ private Looper mLooper;
+ private TestDomainSelectorBase mDomainSelector;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext();
+
+ HandlerThread handlerThread = new HandlerThread(TAG);
+ handlerThread.start();
+ mLooper = handlerThread.getLooper();
+ mDomainSelector = new TestDomainSelectorBase(mContext, SLOT_0, SUB_1, mLooper,
+ mImsStateTracker, mDomainSelectorDestroyListener, TAG);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mDomainSelector != null) {
+ mDomainSelector.destroy();
+ mDomainSelector = null;
+ }
+
+ if (mLooper != null) {
+ mLooper.quit();
+ mLooper = null;
+ }
+
+ mDomainSelectorDestroyListener = null;
+ mImsStateTracker = null;
+ mContext = null;
+ }
+
+ @Test
+ @SmallTest
+ public void testInit() {
+ assertEquals(SLOT_0, mDomainSelector.getSlotId());
+ assertEquals(SUB_1, mDomainSelector.getSubId());
+ }
+
+ @Test
+ @SmallTest
+ public void testDestroy() {
+ mDomainSelector.destroy();
+ verify(mDomainSelectorDestroyListener).onDomainSelectorDestroyed(eq(mDomainSelector));
+ mDomainSelector = null;
+ }
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
new file mode 100644
index 0000000..0821943
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
@@ -0,0 +1,1915 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.GERAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.NGRAN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.UNKNOWN;
+import static android.telephony.AccessNetworkConstants.AccessNetworkType.UTRAN;
+import static android.telephony.BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY;
+import static android.telephony.BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_SCAN_TIMER_SEC_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT;
+import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL;
+import static android.telephony.CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE;
+import static android.telephony.CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE;
+import static android.telephony.CarrierConfigManager.ImsEmergency.SCAN_TYPE_NO_PREFERENCE;
+import static android.telephony.CarrierConfigManager.ImsEmergency.VOWIFI_REQUIRES_NONE;
+import static android.telephony.CarrierConfigManager.ImsEmergency.VOWIFI_REQUIRES_SETTING_ENABLED;
+import static android.telephony.CarrierConfigManager.ImsEmergency.VOWIFI_REQUIRES_VALID_EID;
+import static android.telephony.CarrierConfigManager.ImsWfc.KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL;
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
+import static android.telephony.NetworkRegistrationInfo.DOMAIN_CS;
+import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
+import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
+
+import static com.android.services.telephony.domainselection.EmergencyCallDomainSelector.MSG_NETWORK_SCAN_TIMEOUT;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkRequest;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IPowerManager;
+import android.os.IThermalService;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.os.PowerManager;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.BarringInfo;
+import android.telephony.CarrierConfigManager;
+import android.telephony.CellIdentityLte;
+import android.telephony.DisconnectCause;
+import android.telephony.DomainSelectionService;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.EmergencyRegResult;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PreciseDisconnectCause;
+import android.telephony.TelephonyManager;
+import android.telephony.TransportSelectorCallback;
+import android.telephony.WwanSelectorCallback;
+import android.telephony.ims.ImsManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ProvisioningManager;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableLooper;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.TestContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Unit tests for EmergencyCallDomainSelector
+ */
+public class EmergencyCallDomainSelectorTest {
+ private static final String TAG = "EmergencyCallDomainSelectorTest";
+
+ private static final int SLOT_0 = 0;
+ private static final int SLOT_0_SUB_ID = 1;
+
+ @Mock private CarrierConfigManager mCarrierConfigManager;
+ @Mock private ConnectivityManager mConnectivityManager;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private WwanSelectorCallback mWwanSelectorCallback;
+ @Mock private TransportSelectorCallback mTransportSelectorCallback;
+ @Mock private ImsMmTelManager mMmTelManager;
+ @Mock private ImsStateTracker mImsStateTracker;
+ @Mock private DomainSelectorBase.DestroyListener mDestroyListener;
+ @Mock private ProvisioningManager mProvisioningManager;
+ @Mock private CrossSimRedialingController mCsrdCtrl;
+
+ private Context mContext;
+
+ private HandlerThread mHandlerThread;
+ private TestableLooper mLooper;
+ private EmergencyCallDomainSelector mDomainSelector;
+ private SelectionAttributes mSelectionAttributes;
+ private @AccessNetworkConstants.RadioAccessNetworkType List<Integer> mAccessNetwork;
+ private PowerManager mPowerManager;
+ private ConnectivityManager.NetworkCallback mNetworkCallback;
+ private Consumer<EmergencyRegResult> mResultConsumer;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext() {
+ @Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (serviceClass == ImsManager.class) {
+ return Context.TELEPHONY_IMS_SERVICE;
+ } else if (serviceClass == TelephonyManager.class) {
+ return Context.TELEPHONY_SERVICE;
+ } else if (serviceClass == CarrierConfigManager.class) {
+ return Context.CARRIER_CONFIG_SERVICE;
+ } else if (serviceClass == PowerManager.class) {
+ return Context.POWER_SERVICE;
+ } else if (serviceClass == ConnectivityManager.class) {
+ return Context.CONNECTIVITY_SERVICE;
+ }
+ return super.getSystemServiceName(serviceClass);
+ }
+
+ @Override
+ public Object getSystemService(String name) {
+ switch (name) {
+ case (Context.POWER_SERVICE) : {
+ return mPowerManager;
+ }
+ case (Context.CONNECTIVITY_SERVICE) : {
+ return mConnectivityManager;
+ }
+ }
+ return super.getSystemService(name);
+ }
+
+ @Override
+ public String getOpPackageName() {
+ return "";
+ }
+ };
+
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ mHandlerThread = new HandlerThread("EmergencyCallDomainSelectorTest");
+ mHandlerThread.start();
+
+ try {
+ mLooper = new TestableLooper(mHandlerThread.getLooper());
+ } catch (Exception e) {
+ logd("Unable to create looper from handler.");
+ }
+
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ when(mTelephonyManager.createForSubscriptionId(anyInt()))
+ .thenReturn(mTelephonyManager);
+ when(mTelephonyManager.getNetworkCountryIso()).thenReturn("");
+
+ mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt()))
+ .thenReturn(getDefaultPersistableBundle());
+
+ mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ mNetworkCallback = (ConnectivityManager.NetworkCallback)
+ invocation.getArguments()[1];
+ return null;
+ }
+ }).when(mConnectivityManager).registerNetworkCallback(
+ any(NetworkRequest.class), any(ConnectivityManager.NetworkCallback.class));
+
+ IPowerManager powerManager = mock(IPowerManager.class);
+ mPowerManager = new PowerManager(mContext, powerManager, mock(IThermalService.class),
+ new Handler(mHandlerThread.getLooper()));
+
+ ImsManager imsManager = mContext.getSystemService(ImsManager.class);
+ when(imsManager.getImsMmTelManager(anyInt())).thenReturn(mMmTelManager);
+ when(mMmTelManager.isAdvancedCallingSettingEnabled()).thenReturn(true);
+ doReturn(mProvisioningManager).when(imsManager).getProvisioningManager(anyInt());
+ doReturn(null).when(mProvisioningManager).getProvisioningStringValue(anyInt());
+
+ when(mTransportSelectorCallback.onWwanSelected()).thenReturn(mWwanSelectorCallback);
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ Consumer<WwanSelectorCallback> consumer =
+ (Consumer<WwanSelectorCallback>) invocation.getArguments()[0];
+ consumer.accept(mWwanSelectorCallback);
+ return null;
+ }
+ }).when(mTransportSelectorCallback).onWwanSelected(any());
+
+ doAnswer(new Answer<Void>() {
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ mAccessNetwork = (List<Integer>) invocation.getArguments()[0];
+ mResultConsumer = (Consumer<EmergencyRegResult>) invocation.getArguments()[3];
+ return null;
+ }
+ }).when(mWwanSelectorCallback).onRequestEmergencyNetworkScan(
+ any(), anyInt(), any(), any());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mDomainSelector != null) {
+ mDomainSelector.destroy();
+ mDomainSelector = null;
+ }
+
+ if (mLooper != null) {
+ mLooper.destroy();
+ mLooper = null;
+ }
+ }
+
+ @SmallTest
+ @Test
+ public void testInit() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+
+ verify(mWwanSelectorCallback, times(0)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), any(), any());
+ verify(mWwanSelectorCallback, times(0)).onDomainSelected(anyInt(), eq(true));
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredBarredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredSelectPs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredSelectPsThenCsfb() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testNoCsCombinedImsNotRegisteredSelectPs() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ new int[0]);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredBarredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredEmsOffBarredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredEmsOffSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredEmsOffSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredEmsOffBarredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredVopsOffBarredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredVopsOffSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredVopsOffSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredVopsOffBarredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredVopsOffEmsOffBarredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredVopsOffEmsOffSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredVopsOffEmsOffSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredVopsOffEmsOffBarredSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultCsSelectCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredBarredScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredSelectPs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testDefaultEpsImsNotRegisteredSelectPs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testDefaultEpsImsNotRegisteredBarredSelectScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredEmsOffBarredScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredEmsOffScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsNotRegisteredEmsOffScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsNotRegisteredEmsOffBarredScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredVopsOffBarredScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredVopsOffScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsNotRegisteredVopsOffScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsNotRegisteredVopsOffBarredScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredVopsOffEmsOffBarredScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredVopsOffEmsOffScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsNotRegisteredVopsOffEmsOffScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsNotRegisteredVopsOffEmsOffBarredScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultOutOfServiceScanPsPreferred() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(
+ UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testVoLteOnEpsImsNotRegisteredSelectPs() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ // Requires VoLTE enabled and VoLTE is enabled.
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testVoLteOffEpsImsNotRegisteredScanCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ // Disable VoLTE.
+ when(mMmTelManager.isAdvancedCallingSettingEnabled()).thenReturn(false);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ // Requires VoLTE enabled but VoLTE is'nt enabled.
+ verifyScanCsPreferred();
+ }
+
+ @Test
+ public void testRequiresRegEpsImsNotRegisteredScanCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanCsPreferred();
+ }
+
+ @Test
+ public void testDefaultEpsImsRegisteredBarredScanTimeoutWifi() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService(true);
+
+ verifyScanPsPreferred();
+
+ assertTrue(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+
+ // Wi-Fi is not connected.
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // Wi-Fi is connected.
+ mNetworkCallback.onAvailable(null);
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ verify(mTransportSelectorCallback, times(1)).onWlanSelected(eq(true));
+ }
+
+ @Test
+ public void testVoWifiSosPdnRequiresSettingEnabled() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
+ bundle.putInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT, VOWIFI_REQUIRES_SETTING_ENABLED);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ assertTrue(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ // Wi-Fi is not connected.
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // Wi-Fi is connected. But Wi-Fi calling setting is disabled.
+ mNetworkCallback.onAvailable(null);
+ when(mMmTelManager.isVoWiFiRoamingSettingEnabled()).thenReturn(false);
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // Wi-Fi is connected and Wi-Fi calling setting is enabled.
+ when(mMmTelManager.isVoWiFiSettingEnabled()).thenReturn(true);
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ verify(mTransportSelectorCallback, times(1)).onWlanSelected(eq(true));
+ }
+
+ @Test
+ public void testVoWifiSosPdnRequiresValidEid() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
+ bundle.putInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT, VOWIFI_REQUIRES_VALID_EID);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ assertTrue(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ // Wi-Fi is not connected.
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // Wi-Fi is connected. But Wi-Fi calling s not activated.
+ mNetworkCallback.onAvailable(null);
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // Wi-Fi is connected and Wi-Fi calling is activated.
+ doReturn("1").when(mProvisioningManager).getProvisioningStringValue(anyInt());
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ verify(mTransportSelectorCallback, times(1)).onWlanSelected(eq(true));
+ }
+
+ @Test
+ public void testVoWifiImsPdnRequiresNone() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ assertTrue(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ // Wi-Fi is not connected.
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // Wi-Fi is connected but IMS is not registered over Wi-Fi.
+ mNetworkCallback.onAvailable(null);
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // IMS is registered over Wi-Fi.
+ bindImsService(true);
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ verify(mTransportSelectorCallback, times(1)).onWlanSelected(eq(false));
+ }
+
+ @Test
+ public void testIgnoreDuplicatedCallbacks() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService(true);
+
+ verify(mTransportSelectorCallback, times(1)).onWwanSelected(any());
+
+ // duplicated event
+ unsolBarringInfoChanged(true);
+
+ // ignore duplicated callback, no change in interaction
+ verify(mTransportSelectorCallback, times(1)).onWwanSelected(any());
+
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ verify(mTransportSelectorCallback, times(1)).onWlanSelected(eq(false));
+
+ // duplicated event
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
+
+ // ignore duplicated callback, no change in interaction
+ verify(mTransportSelectorCallback, times(1)).onWlanSelected(anyBoolean());
+ }
+
+ @Test
+ public void testDualSimInvalidSubscription() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+ doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+ .when(mTelephonyManager).getSimState(anyInt());
+ doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "", "jp");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(1))
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
+ }
+
+ @Test
+ public void testDualSimInvalidSubscriptionButNoOtherSlot() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+ doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+ .when(mTelephonyManager).getSimState(anyInt());
+ doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "", "jp");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(0))
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testEutranWithCsDomainOnly() throws Exception {
+ setupForHandleScanResult();
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ DOMAIN_CS, false, false, 0, 0, "", "");
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testFullService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_FULL_SERVICE);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ mResultConsumer = null;
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(UNKNOWN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), any(), any());
+ assertNotNull(mResultConsumer);
+
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(2)).onRequestEmergencyNetworkScan(
+ any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), any(), any());
+ }
+
+ @Test
+ public void testFullServiceThenLimtedService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT,
+ SCAN_TYPE_FULL_SERVICE_FOLLOWED_BY_LIMITED_SERVICE);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ mResultConsumer = null;
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(UNKNOWN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), any(), any());
+ assertNotNull(mResultConsumer);
+
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), eq(DomainSelectionService.SCAN_TYPE_LIMITED_SERVICE), any(), any());
+ }
+
+ @Test
+ public void testCsThenPsPreference() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+
+ setupForScanListTest(bundle);
+
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+ }
+
+ @Test
+ public void testPsThenCsPreference() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+
+ setupForScanListTest(bundle);
+
+ verifyPsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+ }
+
+ @Test
+ public void testPsOnlyPreference() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ bundle.putIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ new int[0]);
+
+ setupForScanListTest(bundle);
+
+ verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+ }
+
+ @Test
+ public void testCsOnlyPreference() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[0]);
+
+ setupForScanListTest(bundle);
+
+ verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+
+ }
+
+ @Test
+ public void testCsThenPsPreferenceCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+
+ setupForScanListTest(bundle);
+
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+ }
+
+ @Test
+ public void testPsThenCsPreferenceCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+
+ setupForScanListTest(bundle);
+
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+ }
+
+ @Test
+ public void testPsOnlyPreferenceCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ bundle.putIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ new int[0]);
+
+ setupForScanListTest(bundle);
+
+ verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+ }
+
+ @Test
+ public void testCsOnlyPreferenceCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[0]);
+
+ setupForScanListTest(bundle);
+
+ verifyCsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+ }
+
+ @Test
+ public void testCsThenPsPreferencePsFail() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+
+ setupForScanListTest(bundle, true);
+
+ bindImsService();
+ processAllMessages();
+
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+ }
+
+ @Test
+ public void testPsThenCsPreferencePsFail() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+
+ setupForScanListTest(bundle, true);
+
+ bindImsService();
+ processAllMessages();
+
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+ }
+
+ @Test
+ public void testPsOnlyPreferencePsFail() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ bundle.putIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ new int[0]);
+
+ setupForScanListTest(bundle, true);
+
+ bindImsService();
+ processAllMessages();
+
+ verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(false, false));
+ }
+
+ @Test
+ public void testCsThenPsPreferencePsFailCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+
+ setupForScanListTest(bundle, true);
+
+ bindImsService();
+ processAllMessages();
+
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+ }
+
+ @Test
+ public void testPsThenCsPreferencePsFailCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+
+ setupForScanListTest(bundle, true);
+
+ bindImsService();
+ processAllMessages();
+
+ verifyCsPreferredScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+ }
+
+ @Test
+ public void testPsOnlyPreferencePsFailCsPreferred() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ bundle.putIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ new int[0]);
+
+ setupForScanListTest(bundle, true);
+
+ bindImsService();
+ processAllMessages();
+
+ verifyPsOnlyScanList(mDomainSelector.getNextPreferredNetworks(true, false));
+ }
+
+ @Test
+ public void testEpsFallbackThenCsPreference() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[] { NGRAN, EUTRAN });
+
+ setupForScanListTest(bundle);
+
+ List<Integer> networks = mDomainSelector.getNextPreferredNetworks(false, true);
+
+ assertFalse(networks.isEmpty());
+ assertTrue(networks.contains(EUTRAN));
+ assertTrue(networks.contains(NGRAN));
+ assertTrue(networks.contains(UTRAN));
+ assertTrue(networks.contains(GERAN));
+ assertTrue(networks.indexOf(EUTRAN) < networks.indexOf(UTRAN));
+ assertTrue(networks.indexOf(UTRAN) < networks.indexOf(GERAN));
+ assertTrue(networks.indexOf(GERAN) < networks.indexOf(NGRAN));
+ }
+
+ @Test
+ public void testStartCrossStackTimer() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(
+ UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ processAllMessages();
+ verify(mCsrdCtrl).startTimer(any(), eq(mDomainSelector), any(),
+ any(), anyBoolean(), anyBoolean(), anyInt());
+ }
+
+ @Test
+ public void testStopCrossStackTimerOnCancel() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ mDomainSelector.cancelSelection();
+
+ verify(mCsrdCtrl).stopTimer();
+ }
+
+ @Test
+ public void testStopCrossStackTimerOnFinish() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ mDomainSelector.finishSelection();
+
+ verify(mCsrdCtrl).stopTimer();
+ }
+
+ @Test
+ public void testCrossStackTimerTempFailure() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+
+ attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setEmergency(true)
+ .setEmergencyRegResult(regResult)
+ .setCsDisconnectCause(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE)
+ .build();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE));
+ }
+
+ @Test
+ public void testCrossStackTimerPermFailure() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+
+ attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setEmergency(true)
+ .setEmergencyRegResult(regResult)
+ .setCsDisconnectCause(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE)
+ .build();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE));
+ }
+
+ @Test
+ public void testCrossStackTimerExpired() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(
+ UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+
+ mDomainSelector.notifyCrossStackTimerExpired();
+
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
+ }
+
+ @Test
+ public void testCrossStackTimerExpiredAfterDomainSelected() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+
+ mDomainSelector.notifyCrossStackTimerExpired();
+
+ verify(mTransportSelectorCallback, times(0))
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
+ }
+
+ private void setupForScanListTest(PersistableBundle bundle) throws Exception {
+ setupForScanListTest(bundle, false);
+ }
+
+ private void setupForScanListTest(PersistableBundle bundle, boolean psFailed) throws Exception {
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "");
+ if (psFailed) {
+ regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS, true, true, 0, 0, "", "");
+ }
+
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+ }
+
+ private void verifyCsPreferredScanList(List<Integer> networks) {
+ assertFalse(networks.isEmpty());
+ assertTrue(networks.contains(EUTRAN));
+ assertTrue(networks.contains(UTRAN));
+ assertTrue(networks.contains(GERAN));
+ assertTrue(networks.indexOf(UTRAN) < networks.indexOf(EUTRAN));
+ }
+
+ private void verifyPsPreferredScanList(List<Integer> networks) {
+ assertFalse(networks.isEmpty());
+ assertTrue(networks.contains(EUTRAN));
+ assertTrue(networks.contains(UTRAN));
+ assertTrue(networks.contains(GERAN));
+ assertTrue(networks.indexOf(EUTRAN) < networks.indexOf(UTRAN));
+ }
+
+ private void verifyPsOnlyScanList(List<Integer> networks) {
+ assertFalse(networks.isEmpty());
+ assertTrue(networks.contains(EUTRAN));
+ assertFalse(networks.contains(UTRAN));
+ assertFalse(networks.contains(GERAN));
+ }
+
+ private void verifyCsOnlyScanList(List<Integer> networks) {
+ assertFalse(networks.isEmpty());
+ assertFalse(networks.contains(EUTRAN));
+ assertTrue(networks.contains(UTRAN));
+ assertTrue(networks.contains(GERAN));
+ }
+
+ private void setupForHandleScanResult() throws Exception {
+ mResultConsumer = null;
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), any(), any());
+ assertNotNull(mResultConsumer);
+ }
+
+ private void createSelector(int subId) throws Exception {
+ mDomainSelector = new EmergencyCallDomainSelector(
+ mContext, SLOT_0, subId, mHandlerThread.getLooper(),
+ mImsStateTracker, mDestroyListener, mCsrdCtrl);
+
+ replaceInstance(DomainSelectorBase.class,
+ "mWwanSelectorCallback", mDomainSelector, mWwanSelectorCallback);
+ }
+
+ private void verifyCsDialed() {
+ processAllMessages();
+ verify(mWwanSelectorCallback, times(1)).onDomainSelected(eq(DOMAIN_CS), eq(false));
+ }
+
+ private void verifyPsDialed() {
+ processAllMessages();
+ verify(mWwanSelectorCallback, times(1)).onDomainSelected(eq(DOMAIN_PS), eq(true));
+ }
+
+ private void verifyScanPsPreferred() {
+ verifyScanPreferred(DomainSelectionService.SCAN_TYPE_NO_PREFERENCE, EUTRAN);
+ }
+
+ private void verifyScanCsPreferred() {
+ verifyScanPreferred(DomainSelectionService.SCAN_TYPE_NO_PREFERENCE, UTRAN);
+ }
+
+ private void verifyScanPreferred(int scanType, int expectedPreferredAccessNetwork) {
+ processAllMessages();
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), eq(scanType), any(), any());
+ assertEquals(expectedPreferredAccessNetwork, (int) mAccessNetwork.get(0));
+ }
+
+ private void unsolBarringInfoChanged(boolean barred) {
+ SparseArray<BarringInfo.BarringServiceInfo> serviceInfos = new SparseArray<>();
+ if (barred) {
+ serviceInfos.put(BARRING_SERVICE_TYPE_EMERGENCY,
+ new BarringInfo.BarringServiceInfo(BARRING_TYPE_UNCONDITIONAL, false, 0, 0));
+ }
+ mDomainSelector.onBarringInfoUpdated(new BarringInfo(new CellIdentityLte(), serviceInfos));
+ }
+
+ private void bindImsService() {
+ bindImsService(false);
+ }
+
+ private void bindImsService(boolean isWifi) {
+ doReturn(isWifi).when(mImsStateTracker).isImsRegisteredOverWlan();
+ doReturn(true).when(mImsStateTracker).isImsRegistered();
+ mDomainSelector.onImsRegistrationStateChanged();
+ doReturn(true).when(mImsStateTracker).isImsVoiceCapable();
+ mDomainSelector.onImsMmTelCapabilitiesChanged();
+ }
+
+ private void bindImsServiceUnregistered() {
+ doReturn(false).when(mImsStateTracker).isImsRegistered();
+ mDomainSelector.onImsRegistrationStateChanged();
+ doReturn(false).when(mImsStateTracker).isImsVoiceCapable();
+ mDomainSelector.onImsMmTelCapabilitiesChanged();
+ }
+
+ private static EmergencyRegResult getEmergencyRegResult(
+ @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork,
+ @NetworkRegistrationInfo.RegistrationState int regState,
+ @NetworkRegistrationInfo.Domain int domain,
+ boolean isVopsSupported, boolean isEmcBearerSupported, int emc, int emf,
+ @NonNull String mcc, @NonNull String mnc) {
+ return getEmergencyRegResult(accessNetwork, regState, domain, isVopsSupported,
+ isEmcBearerSupported, emc, emf, mcc, mnc, "");
+ }
+
+ private static EmergencyRegResult getEmergencyRegResult(
+ @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork,
+ @NetworkRegistrationInfo.RegistrationState int regState,
+ @NetworkRegistrationInfo.Domain int domain,
+ boolean isVopsSupported, boolean isEmcBearerSupported, int emc, int emf,
+ @NonNull String mcc, @NonNull String mnc, @NonNull String iso) {
+ return new EmergencyRegResult(accessNetwork, regState,
+ domain, isVopsSupported, isEmcBearerSupported,
+ emc, emf, mcc, mnc, iso);
+ }
+
+ private static PersistableBundle getDefaultPersistableBundle() {
+ int[] imsRats = new int[] { EUTRAN };
+ int[] csRats = new int[] { UTRAN, GERAN };
+ int[] imsRoamRats = new int[] { EUTRAN };
+ int[] csRoamRats = new int[] { UTRAN, GERAN };
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_NON_3GPP
+ };
+ int[] roamDomainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_NON_3GPP
+ };
+ boolean imsWhenVoiceOnCs = false;
+ int voWifiRequiresCondition = VOWIFI_REQUIRES_NONE;
+ int maxRetriesOverWiFi = 1;
+ int cellularScanTimerSec = 10;
+ boolean voWifiOverEmergencyPdn = false;
+ int scanType = SCAN_TYPE_NO_PREFERENCE;
+ boolean requiresImsRegistration = false;
+ boolean requiresVoLteEnabled = false;
+ boolean ltePreferredAfterNrFailed = false;
+ String[] cdmaPreferredNumbers = new String[] {};
+
+ return getPersistableBundle(imsRats, csRats, imsRoamRats, csRoamRats,
+ domainPreference, roamDomainPreference, imsWhenVoiceOnCs,
+ voWifiRequiresCondition, maxRetriesOverWiFi, cellularScanTimerSec,
+ scanType, voWifiOverEmergencyPdn, requiresImsRegistration,
+ requiresVoLteEnabled, ltePreferredAfterNrFailed, cdmaPreferredNumbers);
+ }
+
+ private static PersistableBundle getPersistableBundle(
+ @Nullable int[] imsRats, @Nullable int[] csRats,
+ @Nullable int[] imsRoamRats, @Nullable int[] csRoamRats,
+ @Nullable int[] domainPreference, @Nullable int[] roamDomainPreference,
+ boolean imsWhenVoiceOnCs, int voWifiRequiresCondition,
+ int maxRetriesOverWiFi, int cellularScanTimerSec, int scanType,
+ boolean voWifiOverEmergencyPdn, boolean requiresImsRegistration,
+ boolean requiresVoLteEnabled, boolean ltePreferredAfterNrFailed,
+ @Nullable String[] cdmaPreferredNumbers) {
+
+ PersistableBundle bundle = new PersistableBundle();
+ if (imsRats != null) {
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ imsRats);
+ }
+ if (imsRoamRats != null) {
+ bundle.putIntArray(
+ KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ imsRoamRats);
+ }
+ if (csRats != null) {
+ bundle.putIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ csRats);
+ }
+ if (csRoamRats != null) {
+ bundle.putIntArray(
+ KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ csRoamRats);
+ }
+ if (domainPreference != null) {
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ }
+ if (roamDomainPreference != null) {
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY,
+ roamDomainPreference);
+ }
+ bundle.putBoolean(KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL, imsWhenVoiceOnCs);
+ bundle.putInt(KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT, voWifiRequiresCondition);
+ bundle.putInt(KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT, maxRetriesOverWiFi);
+ bundle.putInt(KEY_EMERGENCY_SCAN_TIMER_SEC_INT, cellularScanTimerSec);
+ bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, voWifiOverEmergencyPdn);
+ bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, scanType);
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, requiresImsRegistration);
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, requiresVoLteEnabled);
+ bundle.putInt(KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT, 0);
+ bundle.putBoolean(KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL,
+ ltePreferredAfterNrFailed);
+ bundle.putStringArray(KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY,
+ cdmaPreferredNumbers);
+
+ return bundle;
+ }
+
+ public static SelectionAttributes getSelectionAttributes(int slotId, int subId,
+ EmergencyRegResult regResult) {
+ SelectionAttributes.Builder builder =
+ new SelectionAttributes.Builder(slotId, subId, SELECTOR_TYPE_CALLING)
+ .setEmergency(true)
+ .setEmergencyRegResult(regResult);
+ return builder.build();
+ }
+
+ private static void replaceInstance(final Class c,
+ final String instanceName, final Object obj, final Object newValue) throws Exception {
+ Field field = c.getDeclaredField(instanceName);
+ field.setAccessible(true);
+ field.set(obj, newValue);
+ }
+
+ private void processAllMessages() {
+ while (!mLooper.getLooper().getQueue().isIdle()) {
+ mLooper.processAllMessages();
+ }
+ }
+
+ private static void logd(String str) {
+ Log.d(TAG, str);
+ }
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelectorTest.java
new file mode 100644
index 0000000..1d89071
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelectorTest.java
@@ -0,0 +1,815 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_SMS;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
+import android.telephony.BarringInfo;
+import android.telephony.CarrierConfigManager;
+import android.telephony.DataSpecificRegistrationInfo;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.telephony.TransportSelectorCallback;
+import android.telephony.VopsSupportInfo;
+import android.telephony.WwanSelectorCallback;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableLooper;
+import android.util.SparseArray;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TestContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Consumer;
+
+/**
+ * Unit tests for EmergencySmsDomainSelector.
+ */
+@RunWith(AndroidJUnit4.class)
+public class EmergencySmsDomainSelectorTest {
+ private static final int SLOT_0 = 0;
+ private static final int SUB_1 = 1;
+
+ @Mock private ServiceState mServiceState;
+ @Mock private TransportSelectorCallback mTransportSelectorCallback;
+ @Mock private WwanSelectorCallback mWwanSelectorCallback;
+ @Mock private VopsSupportInfo mVopsSupportInfo;
+ @Mock private ImsStateTracker mImsStateTracker;
+ @Mock private DomainSelectorBase.DestroyListener mDomainSelectorDestroyListener;
+
+ private final SelectionAttributes mSelectionAttributes =
+ new SelectionAttributes.Builder(SLOT_0, SUB_1, SELECTOR_TYPE_SMS)
+ .setEmergency(true)
+ .build();
+ private Context mContext;
+ private Looper mLooper;
+ private TestableLooper mTestableLooper;
+ private CarrierConfigManager mCarrierConfigManager;
+ private NetworkRegistrationInfo mNetworkRegistrationInfo;
+ private boolean mCarrierConfigManagerNullTest = false;
+ private BarringInfo mBarringInfo = new BarringInfo();
+ private ImsStateTracker.ImsStateListener mImsStateListener;
+ private ImsStateTracker.BarringInfoListener mBarringInfoListener;
+ private ImsStateTracker.ServiceStateListener mServiceStateListener;
+ private EmergencySmsDomainSelector mDomainSelector;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext() {
+ @Override
+ public Object getSystemService(String name) {
+ if (name.equals(Context.CARRIER_CONFIG_SERVICE)) {
+ if (mCarrierConfigManagerNullTest) {
+ return null;
+ }
+ }
+
+ return super.getSystemService(name);
+ }
+ };
+
+ HandlerThread handlerThread = new HandlerThread(
+ EmergencySmsDomainSelectorTest.class.getSimpleName());
+ handlerThread.start();
+ mLooper = handlerThread.getLooper();
+ mTestableLooper = new TestableLooper(mLooper);
+ mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+
+ mDomainSelector = new EmergencySmsDomainSelector(mContext, SLOT_0, SUB_1,
+ mLooper, mImsStateTracker, mDomainSelectorDestroyListener);
+
+ ArgumentCaptor<ImsStateTracker.ServiceStateListener> serviceStateListenerCaptor =
+ ArgumentCaptor.forClass(ImsStateTracker.ServiceStateListener.class);
+ verify(mImsStateTracker).addServiceStateListener(serviceStateListenerCaptor.capture());
+ mServiceStateListener = serviceStateListenerCaptor.getValue();
+ assertNotNull(mServiceStateListener);
+
+ ArgumentCaptor<ImsStateTracker.BarringInfoListener> barringInfoListenerCaptor =
+ ArgumentCaptor.forClass(ImsStateTracker.BarringInfoListener.class);
+ verify(mImsStateTracker).addBarringInfoListener(barringInfoListenerCaptor.capture());
+ mBarringInfoListener = barringInfoListenerCaptor.getValue();
+ assertNotNull(mBarringInfoListener);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mTestableLooper != null) {
+ mTestableLooper.destroy();
+ mTestableLooper = null;
+ }
+
+ if (mDomainSelector != null) {
+ mDomainSelector.destroy();
+ verify(mImsStateTracker).removeImsStateListener(eq(mDomainSelector));
+ verify(mImsStateTracker).removeBarringInfoListener(eq(mDomainSelector));
+ verify(mImsStateTracker).removeServiceStateListener(eq(mDomainSelector));
+ }
+
+ if (mLooper != null) {
+ mLooper.quit();
+ mLooper = null;
+ }
+
+ mDomainSelector = null;
+ mNetworkRegistrationInfo = null;
+ mVopsSupportInfo = null;
+ mDomainSelectorDestroyListener = null;
+ mWwanSelectorCallback = null;
+ mTransportSelectorCallback = null;
+ mServiceState = null;
+ mCarrierConfigManager = null;
+ mCarrierConfigManagerNullTest = false;
+ }
+
+ @Test
+ @SmallTest
+ public void testFinishSelection() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+ mBarringInfoListener.onBarringInfoUpdated(mBarringInfo);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+ assertTrue(mDomainSelector.isDomainSelectionReady());
+
+ mDomainSelector.finishSelection();
+
+ assertFalse(mDomainSelector.isDomainSelectionReady());
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsDomainSelectionReady() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+
+ assertFalse(mDomainSelector.isDomainSelectionReady());
+
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+ mBarringInfoListener.onBarringInfoUpdated(mBarringInfo);
+
+ assertTrue(mDomainSelector.isDomainSelectionReady());
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsDomainSelectionReadyAndSelectDomain() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+ mBarringInfoListener.onBarringInfoUpdated(mBarringInfo);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+ assertTrue(mDomainSelector.isDomainSelectionReady());
+
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenImsRegistered() {
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+
+ assertTrue(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenImsRegisteredAndConfigEnabledAndLteAvailable() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, false);
+
+ assertTrue(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenImsRegisteredAndConfigEnabledAndLteNotAvailable() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, false, false, false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenCarrierConfigManagerIsNull() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ mCarrierConfigManagerNullTest = true;
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenCarrierConfigIsNull() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(null);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenCarrierConfigNotEnabled() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenMmTelFeatureUnavailable() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN, false, false);
+ setUpCarrierConfig(true);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenServiceStateIsNull() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenNoLte() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_UMTS)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfo(
+ anyInt(), eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(mNetworkRegistrationInfo);
+
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenLteNotRegisteredOrEmergencyNotEnabled() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfo(
+ anyInt(), eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(mNetworkRegistrationInfo);
+
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenLteInServiceAndNoDataSpecificRegistrationInfo() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpLteInService(true, true, true, true, false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenLteInServiceAndNoVopsSupportInfo() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpLteInService(false, true, true, true, false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenLteInServiceAndEmcBsNotSupported() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, false, true, false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenLteInServiceAndEmcBsSupportedAndNoBarringInfo() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, true, false);
+
+ assertTrue(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenLteInServiceAndEmcBsSupportedAndBarred() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, true);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenLteInServiceAndEmcBsSupportedAndNotBarred() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, false);
+
+ assertTrue(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenLteInLimitedService() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpLimitedLteService(false, false, true, false, false);
+
+ assertTrue(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhilePreviousRequestInProgress() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+ mBarringInfoListener.onBarringInfoUpdated(mBarringInfo);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ processAllMessages();
+
+ // onDomainSelected will be invoked only once
+ // even though the domain selection was requested twice.
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndConfigDisabled() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(false);
+ setUpLteInService(false, false, true, false, false);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndUmtsNetwork() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpNonLteService(TelephonyManager.NETWORK_TYPE_UMTS);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndUnknownNetwork() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpNonLteService(TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndLteInService() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, false);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: PS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndLteEmcBsNotSupported() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, false, false, false);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndLteEmergencyBarred() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, true);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndLimitedLteService() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLimitedLteService(false, false, true, false, false);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: PS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndLimitedLteEmcBsNotSupported() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLimitedLteService(false, false, false, false, false);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegisteredAndLimitedLteEmergencyBarred() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLimitedLteService(false, false, true, false, true);
+ setUpImsStateListener(true, false, false);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnLte() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, false);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: PS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnLteAndEmcBsNotSupported() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, false, false, false);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnLteAndEmergencyBarred() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, true);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnIwlanAndConfigDisabled() {
+ setUpImsStateTracker(AccessNetworkType.IWLAN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(false);
+ setUpLteInService(false, false, true, false, false);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: WLAN
+ verify(mTransportSelectorCallback).onWlanSelected(eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnIwlanAndLteNotAvailable() {
+ setUpImsStateTracker(AccessNetworkType.IWLAN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, false, false, false);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network - even though IMS is successfully registered over Wi-Fi,
+ // if the emergency SMS messages over IMS is enabled in the carrier configuration and
+ // the PS network does not allow the emergency service, this MO SMS should be routed to
+ // CS domain.
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnIwlanAndLteAvailable() {
+ setUpImsStateTracker(AccessNetworkType.IWLAN);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpLteInService(false, false, true, false, false);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: PS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ }
+
+ private void setUpCarrierConfig(boolean supported) {
+ PersistableBundle b = new PersistableBundle();
+ b.putBoolean(CarrierConfigManager.KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL, supported);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(b);
+ }
+
+ private void setUpNonLteService(int networkType) {
+ mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
+ .setAccessNetworkTechnology(networkType)
+ .setRegistrationState(networkType == TelephonyManager.NETWORK_TYPE_UNKNOWN
+ ? NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN
+ : NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfo(
+ anyInt(), eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(mNetworkRegistrationInfo);
+
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+ mBarringInfoListener.onBarringInfoUpdated(null);
+ }
+
+ private void setUpLteInService(boolean noDataSpecificRegistrationInfo,
+ boolean noVopsSupportInfo, boolean emcBsSupported,
+ boolean noBarringInfo, boolean barred) {
+ DataSpecificRegistrationInfo dsri = noDataSpecificRegistrationInfo
+ ? null : new DataSpecificRegistrationInfo(
+ 8, false, false, false, noVopsSupportInfo ? null : mVopsSupportInfo);
+
+ mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setDataSpecificInfo(dsri)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfo(
+ anyInt(), eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(mNetworkRegistrationInfo);
+ when(mVopsSupportInfo.isEmergencyServiceSupported()).thenReturn(emcBsSupported);
+
+ BarringInfo barringInfo = null;
+
+ if (!noBarringInfo) {
+ SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
+ barringServiceInfos.put(BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY,
+ new BarringInfo.BarringServiceInfo(
+ barred ? BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL :
+ BarringInfo.BarringServiceInfo.BARRING_TYPE_NONE, false, 0, 0));
+ barringInfo = new BarringInfo(null, barringServiceInfos);
+ }
+
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+ mBarringInfoListener.onBarringInfoUpdated(barringInfo);
+ }
+
+ private void setUpLimitedLteService(boolean noDataSpecificRegistrationInfo,
+ boolean noVopsSupportInfo, boolean emcBsSupported,
+ boolean noBarringInfo, boolean barred) {
+ DataSpecificRegistrationInfo dsri = noDataSpecificRegistrationInfo
+ ? null : new DataSpecificRegistrationInfo(
+ 8, false, false, false, noVopsSupportInfo ? null : mVopsSupportInfo);
+
+ mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_LTE)
+ .setEmergencyOnly(true)
+ .setDataSpecificInfo(dsri)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfo(
+ anyInt(), eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(mNetworkRegistrationInfo);
+ when(mVopsSupportInfo.isEmergencyServiceSupported()).thenReturn(emcBsSupported);
+
+ BarringInfo barringInfo = null;
+
+ if (!noBarringInfo) {
+ SparseArray<BarringInfo.BarringServiceInfo> barringServiceInfos = new SparseArray<>();
+ barringServiceInfos.put(BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY,
+ new BarringInfo.BarringServiceInfo(
+ barred ? BarringInfo.BarringServiceInfo.BARRING_TYPE_UNCONDITIONAL :
+ BarringInfo.BarringServiceInfo.BARRING_TYPE_NONE, false, 0, 0));
+ barringInfo = new BarringInfo(null, barringServiceInfos);
+ }
+
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+ mBarringInfoListener.onBarringInfoUpdated(barringInfo);
+ }
+
+ private void setUpImsStateTracker(@RadioAccessNetworkType int accessNetworkType) {
+ setUpImsStateTracker(accessNetworkType, true, true);
+ }
+
+ private void setUpImsStateTracker(@RadioAccessNetworkType int accessNetworkType,
+ boolean mmTelFeatureAvailable, boolean smsCapable) {
+ when(mImsStateTracker.isMmTelFeatureAvailable()).thenReturn(mmTelFeatureAvailable);
+ when(mImsStateTracker.isImsRegistered())
+ .thenReturn(accessNetworkType != AccessNetworkType.UNKNOWN);
+ when(mImsStateTracker.isImsRegisteredOverWlan())
+ .thenReturn(accessNetworkType == AccessNetworkType.IWLAN);
+ when(mImsStateTracker.getImsAccessNetworkType()).thenReturn(accessNetworkType);
+ when(mImsStateTracker.isImsSmsCapable()).thenReturn(smsCapable);
+ }
+
+ private void setUpWwanSelectorCallback() {
+ doAnswer((invocation) -> {
+ Object[] args = invocation.getArguments();
+ final Consumer<WwanSelectorCallback> callback =
+ (Consumer<WwanSelectorCallback>) args[0];
+ callback.accept(mWwanSelectorCallback);
+ return null;
+ }).when(mTransportSelectorCallback).onWwanSelected(any(Consumer.class));
+ }
+
+ private void setUpImsStateListener(boolean notifyMmTelFeatureAvailable,
+ boolean notifyImsRegState, boolean notifyMmTelCapability) {
+ doAnswer((invocation) -> {
+ Object[] args = invocation.getArguments();
+ final ImsStateTracker.ImsStateListener listener =
+ (ImsStateTracker.ImsStateListener) args[0];
+ mDomainSelector.post(() -> {
+ if (notifyMmTelFeatureAvailable) {
+ listener.onImsMmTelFeatureAvailableChanged();
+ }
+ if (notifyImsRegState) {
+ listener.onImsRegistrationStateChanged();
+ }
+ if (notifyMmTelCapability) {
+ listener.onImsMmTelCapabilitiesChanged();
+ }
+ });
+ return null;
+ }).when(mImsStateTracker).addImsStateListener(any(ImsStateTracker.ImsStateListener.class));
+ }
+
+ private void processAllMessages() {
+ while (!mTestableLooper.getLooper().getQueue().isIdle()) {
+ mTestableLooper.processAllMessages();
+ }
+ }
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java b/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java
new file mode 100644
index 0000000..430adea
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java
@@ -0,0 +1,774 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.BarringInfo;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsRegistrationAttributes;
+import android.telephony.ims.ImsStateCallback;
+import android.telephony.ims.RegistrationManager;
+import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TestContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit tests for ImsStateTracker.
+ */
+@RunWith(AndroidJUnit4.class)
+public class ImsStateTrackerTest {
+ private static final int SLOT_0 = 0;
+ private static final int SUB_1 = 1;
+ private static final int SUB_2 = 2;
+ private static final long TIMEOUT_MS = 100;
+
+ @Mock private ImsMmTelManager mMmTelManager;
+ @Mock private ImsMmTelManager mMmTelManager2;
+ @Mock private ImsStateTracker.BarringInfoListener mBarringInfoListener;
+ @Mock private ImsStateTracker.ServiceStateListener mServiceStateListener;
+ @Mock private ImsStateTracker.ImsStateListener mImsStateListener;
+ @Mock private ServiceState mServiceState;
+
+ private Context mContext;
+ private Looper mLooper;
+ private BarringInfo mBarringInfo = new BarringInfo();
+ private ImsStateTracker mImsStateTracker;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext() {
+ @Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (serviceClass == ImsManager.class) {
+ return Context.TELEPHONY_IMS_SERVICE;
+ }
+ return super.getSystemServiceName(serviceClass);
+ }
+ };
+
+ HandlerThread handlerThread = new HandlerThread(
+ ImsStateTrackerTest.class.getSimpleName());
+ handlerThread.start();
+ mLooper = handlerThread.getLooper();
+ mImsStateTracker = new ImsStateTracker(mContext, SLOT_0, mLooper);
+
+ ImsManager imsManager = mContext.getSystemService(ImsManager.class);
+ when(imsManager.getImsMmTelManager(eq(SUB_1))).thenReturn(mMmTelManager);
+ when(imsManager.getImsMmTelManager(eq(SUB_2))).thenReturn(mMmTelManager2);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mImsStateTracker.destroy();
+ mImsStateTracker = null;
+ mMmTelManager = null;
+
+ if (mLooper != null) {
+ mLooper.quit();
+ mLooper = null;
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void testInit() {
+ assertEquals(SLOT_0, mImsStateTracker.getSlotId());
+ assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, mImsStateTracker.getSubId());
+ }
+
+ @Test
+ @SmallTest
+ public void testStartWithInvalidSubId() {
+ mImsStateTracker.start(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+ assertEquals(SubscriptionManager.INVALID_SUBSCRIPTION_ID, mImsStateTracker.getSubId());
+ assertTrue(isImsStateUnavailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testStart() throws ImsException {
+ mImsStateTracker.start(SUB_1);
+
+ assertEquals(SUB_1, mImsStateTracker.getSubId());
+ assertTrue(isImsStateInit());
+ verify(mMmTelManager).registerImsStateCallback(
+ any(Executor.class), any(ImsStateCallback.class));
+ }
+
+ @Test
+ @SmallTest
+ public void testStartWithDifferentSubId() throws ImsException {
+ mImsStateTracker.start(SUB_1);
+
+ assertEquals(SUB_1, mImsStateTracker.getSubId());
+ assertTrue(isImsStateInit());
+
+ mImsStateTracker.start(SUB_2);
+
+ assertEquals(SUB_2, mImsStateTracker.getSubId());
+ assertTrue(isImsStateInit());
+ verify(mMmTelManager).registerImsStateCallback(
+ any(Executor.class), any(ImsStateCallback.class));
+ verify(mMmTelManager).unregisterImsStateCallback(
+ any(ImsStateCallback.class));
+ verify(mMmTelManager2).registerImsStateCallback(
+ any(Executor.class), any(ImsStateCallback.class));
+ }
+
+ @Test
+ @SmallTest
+ public void testStartWithSameSubId() throws ImsException {
+ mImsStateTracker.start(SUB_1);
+
+ assertEquals(SUB_1, mImsStateTracker.getSubId());
+ assertTrue(isImsStateInit());
+
+ mImsStateTracker.start(SUB_1);
+
+ assertEquals(SUB_1, mImsStateTracker.getSubId());
+ assertTrue(isImsStateInit());
+ verify(mMmTelManager).registerImsStateCallback(
+ any(Executor.class), any(ImsStateCallback.class));
+ verify(mMmTelManager, never()).unregisterImsStateCallback(
+ any(ImsStateCallback.class));
+ }
+
+ @Test
+ @SmallTest
+ public void testStartWhenRegisteringCallbacksThrowException() throws ImsException {
+ doAnswer((invocation) -> {
+ throw new ImsException("Intended exception for ImsStateCallback.");
+ }).when(mMmTelManager).registerImsStateCallback(
+ any(Executor.class), any(ImsStateCallback.class));
+
+ mImsStateTracker.start(SUB_1);
+
+ assertEquals(SUB_1, mImsStateTracker.getSubId());
+
+ mImsStateTracker.start(SUB_2);
+
+ assertEquals(SUB_2, mImsStateTracker.getSubId());
+
+ verify(mMmTelManager, never()).unregisterImsStateCallback(
+ any(ImsStateCallback.class));
+ }
+
+ @Test
+ @SmallTest
+ public void testStartAfterUnavailableWithReasonSubscriptionInactive() throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onUnavailable(ImsStateCallback.REASON_SUBSCRIPTION_INACTIVE);
+
+ mImsStateTracker.start(SUB_1);
+
+ assertTrue(isImsStateInit());
+ // One is invoked in setUpImsStateCallback and the other is invoked in start(int).
+ verify(mMmTelManager, times(2)).registerImsStateCallback(
+ any(Executor.class), any(ImsStateCallback.class));
+ // ImsStateCallback has already been set to null when onUnavailable is called.
+ verify(mMmTelManager, never()).unregisterImsStateCallback(
+ any(ImsStateCallback.class));
+ }
+
+ @Test
+ @SmallTest
+ public void testUpdateServiceStateBeforeAddingListener() {
+ mImsStateTracker.updateServiceState(mServiceState);
+ mImsStateTracker.addServiceStateListener(mServiceStateListener);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verify(mServiceStateListener).onServiceStateUpdated(eq(mServiceState));
+
+ mImsStateTracker.removeServiceStateListener(mServiceStateListener);
+ ServiceState ss = Mockito.mock(ServiceState.class);
+ mImsStateTracker.updateServiceState(ss);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verifyNoMoreInteractions(mServiceStateListener);
+ }
+
+ @Test
+ @SmallTest
+ public void testUpdateServiceStateAfterAddingListener() {
+ mImsStateTracker.addServiceStateListener(mServiceStateListener);
+ mImsStateTracker.updateServiceState(mServiceState);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verify(mServiceStateListener).onServiceStateUpdated(eq(mServiceState));
+
+ mImsStateTracker.removeServiceStateListener(mServiceStateListener);
+ ServiceState ss = Mockito.mock(ServiceState.class);
+ mImsStateTracker.updateServiceState(ss);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verifyNoMoreInteractions(mServiceStateListener);
+ }
+
+ @Test
+ @SmallTest
+ public void testAddAndRemoveServiceStateListener() {
+ mImsStateTracker.updateServiceState(mServiceState);
+ mImsStateTracker.addServiceStateListener(mServiceStateListener);
+ mImsStateTracker.removeServiceStateListener(mServiceStateListener);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verify(mServiceStateListener, never()).onServiceStateUpdated(eq(mServiceState));
+ }
+
+ @Test
+ @SmallTest
+ public void testUpdateBarringInfoBeforeAddingListener() {
+ mImsStateTracker.updateBarringInfo(mBarringInfo);
+ mImsStateTracker.addBarringInfoListener(mBarringInfoListener);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verify(mBarringInfoListener).onBarringInfoUpdated(eq(mBarringInfo));
+
+ mImsStateTracker.removeBarringInfoListener(mBarringInfoListener);
+ BarringInfo bi = new BarringInfo();
+ mImsStateTracker.updateBarringInfo(bi);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verifyNoMoreInteractions(mBarringInfoListener);
+ }
+
+ @Test
+ @SmallTest
+ public void testUpdateBarringInfoAfterAddingListener() {
+ mImsStateTracker.addBarringInfoListener(mBarringInfoListener);
+ mImsStateTracker.updateBarringInfo(mBarringInfo);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verify(mBarringInfoListener).onBarringInfoUpdated(eq(mBarringInfo));
+
+ mImsStateTracker.removeBarringInfoListener(mBarringInfoListener);
+ BarringInfo bi = new BarringInfo();
+ mImsStateTracker.updateBarringInfo(bi);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verifyNoMoreInteractions(mBarringInfoListener);
+ }
+
+ @Test
+ @SmallTest
+ public void testAddAndRemoveBarringInfoListener() {
+ mImsStateTracker.updateBarringInfo(mBarringInfo);
+ mImsStateTracker.addBarringInfoListener(mBarringInfoListener);
+ mImsStateTracker.removeBarringInfoListener(mBarringInfoListener);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verify(mBarringInfoListener, never()).onBarringInfoUpdated(eq(mBarringInfo));
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyImsStateCallbackOnAvailable() throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onAvailable();
+
+ assertTrue(mImsStateTracker.isMmTelFeatureAvailable());
+ assertFalse(mImsStateTracker.isImsStateReady());
+ verify(mMmTelManager).registerImsRegistrationCallback(
+ any(Executor.class), any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager).registerMmTelCapabilityCallback(
+ any(Executor.class), any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mImsStateListener).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyImsStateCallbackOnUnavailableWithReasonUnknownPermanentError()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onUnavailable(ImsStateCallback.REASON_UNKNOWN_PERMANENT_ERROR);
+
+ assertTrue(isImsStateUnavailable());
+ assertTrue(mImsStateTracker.isImsStateReady());
+ verify(mImsStateListener).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyImsStateCallbackOnUnavailableWithReasonNoImsServiceConfigured()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onUnavailable(ImsStateCallback.REASON_NO_IMS_SERVICE_CONFIGURED);
+
+ assertTrue(isImsStateUnavailable());
+ assertTrue(mImsStateTracker.isImsStateReady());
+ verify(mImsStateListener).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ public void testNotifyImsStateCallbackOnUnavailableWithReasonUnknownTemporaryError()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onUnavailable(ImsStateCallback.REASON_UNKNOWN_TEMPORARY_ERROR);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertFalse(isImsStateUnavailable());
+ assertFalse(mImsStateTracker.isImsStateReady());
+
+ waitForHandlerActionDelayed(mImsStateTracker.getHandler(),
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS,
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS + TIMEOUT_MS);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertTrue(isImsStateUnavailable());
+ assertTrue(mImsStateTracker.isImsStateReady());
+ verify(mImsStateListener).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ public void testNotifyImsStateCallbackOnUnavailableWithReasonImsServiceNotReady()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onUnavailable(ImsStateCallback.REASON_IMS_SERVICE_NOT_READY);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertFalse(isImsStateUnavailable());
+ assertFalse(mImsStateTracker.isImsStateReady());
+
+ waitForHandlerActionDelayed(mImsStateTracker.getHandler(),
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS,
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS + TIMEOUT_MS);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertTrue(isImsStateUnavailable());
+ assertTrue(mImsStateTracker.isImsStateReady());
+ verify(mImsStateListener).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ public void testNotifyImsStateCallbackOnUnavailableWithReasonImsServiceDisconnected()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onUnavailable(ImsStateCallback.REASON_IMS_SERVICE_DISCONNECTED);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertFalse(isImsStateUnavailable());
+ assertFalse(mImsStateTracker.isImsStateReady());
+
+ waitForHandlerActionDelayed(mImsStateTracker.getHandler(),
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS,
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS + TIMEOUT_MS);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertTrue(isImsStateUnavailable());
+ assertTrue(mImsStateTracker.isImsStateReady());
+ verify(mMmTelManager, never()).unregisterImsRegistrationCallback(
+ any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager, never()).unregisterMmTelCapabilityCallback(
+ any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mImsStateListener).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyImsStateCallbackOnUnavailableWithReasonSubscriptionInactive()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onUnavailable(ImsStateCallback.REASON_SUBSCRIPTION_INACTIVE);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertTrue(isImsStateUnavailable());
+ assertTrue(mImsStateTracker.isImsStateReady());
+ verify(mMmTelManager, never()).unregisterImsRegistrationCallback(
+ any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager, never()).unregisterMmTelCapabilityCallback(
+ any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mImsStateListener).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ public void testNotifyImsStateCallbackOnAvailableUnavailableWithReasonImsServiceDisconnected()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onAvailable();
+ callback.onUnavailable(ImsStateCallback.REASON_IMS_SERVICE_DISCONNECTED);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertFalse(isImsStateUnavailable());
+ assertFalse(mImsStateTracker.isImsStateReady());
+
+ waitForHandlerActionDelayed(mImsStateTracker.getHandler(),
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS,
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS + TIMEOUT_MS);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertTrue(isImsStateUnavailable());
+ assertTrue(mImsStateTracker.isImsStateReady());
+ verify(mMmTelManager).registerImsRegistrationCallback(
+ any(Executor.class), any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager).registerMmTelCapabilityCallback(
+ any(Executor.class), any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mMmTelManager).unregisterImsRegistrationCallback(
+ any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager).unregisterMmTelCapabilityCallback(
+ any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mImsStateListener, times(2)).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ public void testNotifyImsStateCallbackOnUnavailableAvailableWithReasonImsServiceDisconnected()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onUnavailable(ImsStateCallback.REASON_IMS_SERVICE_DISCONNECTED);
+ callback.onAvailable();
+
+ assertTrue(mImsStateTracker.isMmTelFeatureAvailable());
+ assertFalse(isImsStateUnavailable());
+ assertFalse(mImsStateTracker.isImsStateReady());
+
+ waitForHandlerActionDelayed(mImsStateTracker.getHandler(),
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS,
+ ImsStateTracker.MMTEL_FEATURE_AVAILABLE_WAIT_TIME_MILLIS + TIMEOUT_MS);
+
+ assertTrue(mImsStateTracker.isMmTelFeatureAvailable());
+ assertFalse(isImsStateUnavailable());
+ assertFalse(mImsStateTracker.isImsStateReady());
+ verify(mMmTelManager).registerImsRegistrationCallback(
+ any(Executor.class), any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager).registerMmTelCapabilityCallback(
+ any(Executor.class), any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mMmTelManager, never()).unregisterImsRegistrationCallback(
+ any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager, never()).unregisterMmTelCapabilityCallback(
+ any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mImsStateListener).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyImsStateCallbackOnAvailableUnavailableWithReasonSubscriptionInactive()
+ throws ImsException {
+ ImsStateCallback callback = setUpImsStateCallback();
+ callback.onAvailable();
+ callback.onUnavailable(ImsStateCallback.REASON_SUBSCRIPTION_INACTIVE);
+
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ assertTrue(isImsStateUnavailable());
+ assertTrue(mImsStateTracker.isImsStateReady());
+ verify(mMmTelManager).registerImsRegistrationCallback(
+ any(Executor.class), any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager).registerMmTelCapabilityCallback(
+ any(Executor.class), any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mMmTelManager).unregisterImsRegistrationCallback(
+ any(RegistrationManager.RegistrationCallback.class));
+ verify(mMmTelManager).unregisterMmTelCapabilityCallback(
+ any(ImsMmTelManager.CapabilityCallback.class));
+ verify(mImsStateListener, times(2)).onImsMmTelFeatureAvailableChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyImsRegistrationCallbackOnRegistered() throws ImsException {
+ RegistrationManager.RegistrationCallback callback = setUpImsRegistrationCallback();
+ callback.onRegistered(new ImsRegistrationAttributes.Builder(
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE).build());
+
+ // It's false because the MMTEL capabilities are not updated yet.
+ assertFalse(mImsStateTracker.isImsStateReady());
+ assertTrue(mImsStateTracker.isImsRegistered());
+ assertFalse(mImsStateTracker.isImsRegisteredOverWlan());
+ assertFalse(mImsStateTracker.isImsRegisteredOverCrossSim());
+ assertEquals(AccessNetworkType.EUTRAN, mImsStateTracker.getImsAccessNetworkType());
+
+ callback.onRegistered(new ImsRegistrationAttributes.Builder(
+ ImsRegistrationImplBase.REGISTRATION_TECH_NR).build());
+
+ assertFalse(mImsStateTracker.isImsStateReady());
+ assertTrue(mImsStateTracker.isImsRegistered());
+ assertFalse(mImsStateTracker.isImsRegisteredOverWlan());
+ assertFalse(mImsStateTracker.isImsRegisteredOverCrossSim());
+ assertEquals(AccessNetworkType.NGRAN, mImsStateTracker.getImsAccessNetworkType());
+
+ callback.onRegistered(new ImsRegistrationAttributes.Builder(
+ ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN).build());
+
+ assertFalse(mImsStateTracker.isImsStateReady());
+ assertTrue(mImsStateTracker.isImsRegistered());
+ assertTrue(mImsStateTracker.isImsRegisteredOverWlan());
+ assertFalse(mImsStateTracker.isImsRegisteredOverCrossSim());
+ assertEquals(AccessNetworkType.IWLAN, mImsStateTracker.getImsAccessNetworkType());
+
+ callback.onRegistered(new ImsRegistrationAttributes.Builder(
+ ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM).build());
+
+ assertFalse(mImsStateTracker.isImsStateReady());
+ assertTrue(mImsStateTracker.isImsRegistered());
+ assertTrue(mImsStateTracker.isImsRegisteredOverWlan());
+ assertTrue(mImsStateTracker.isImsRegisteredOverCrossSim());
+ assertEquals(AccessNetworkType.IWLAN, mImsStateTracker.getImsAccessNetworkType());
+
+ callback.onRegistered(new ImsRegistrationAttributes.Builder(
+ ImsRegistrationImplBase.REGISTRATION_TECH_NONE).build());
+
+ assertFalse(mImsStateTracker.isImsStateReady());
+ assertTrue(mImsStateTracker.isImsRegistered());
+ assertFalse(mImsStateTracker.isImsRegisteredOverWlan());
+ assertFalse(mImsStateTracker.isImsRegisteredOverCrossSim());
+ assertEquals(AccessNetworkType.UNKNOWN, mImsStateTracker.getImsAccessNetworkType());
+
+ verify(mImsStateListener, times(5)).onImsRegistrationStateChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyImsRegistrationCallbackOnUnregistered() throws ImsException {
+ RegistrationManager.RegistrationCallback callback = setUpImsRegistrationCallback();
+ callback.onRegistered(new ImsRegistrationAttributes.Builder(
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE).build());
+
+ // It's false because the MMTEL capabilities are not updated yet.
+ assertFalse(mImsStateTracker.isImsStateReady());
+ assertTrue(mImsStateTracker.isImsRegistered());
+ assertFalse(mImsStateTracker.isImsRegisteredOverWlan());
+ assertEquals(AccessNetworkType.EUTRAN, mImsStateTracker.getImsAccessNetworkType());
+
+ callback.onUnregistered(new ImsReasonInfo(ImsReasonInfo.CODE_REGISTRATION_ERROR, 0, null));
+
+ // When IMS is unregistered, the MMTEL capability is also reset.
+ assertTrue(mImsStateTracker.isImsStateReady());
+ assertFalse(mImsStateTracker.isImsRegistered());
+ assertFalse(mImsStateTracker.isImsRegisteredOverWlan());
+ assertEquals(AccessNetworkType.UNKNOWN, mImsStateTracker.getImsAccessNetworkType());
+
+ verify(mImsStateListener, times(2)).onImsRegistrationStateChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testNotifyMmTelCapabilityCallbackOnCapabilitiesStatusChanged() throws ImsException {
+ ImsMmTelManager.CapabilityCallback callback = setUpMmTelCapabilityCallback();
+
+ assertFalse(mImsStateTracker.isImsVoiceCapable());
+ assertFalse(mImsStateTracker.isImsVideoCapable());
+ assertFalse(mImsStateTracker.isImsSmsCapable());
+ assertFalse(mImsStateTracker.isImsUtCapable());
+
+ MmTelCapabilities capabilities = new MmTelCapabilities(
+ MmTelCapabilities.CAPABILITY_TYPE_VOICE
+ | MmTelCapabilities.CAPABILITY_TYPE_VIDEO
+ | MmTelCapabilities.CAPABILITY_TYPE_SMS
+ | MmTelCapabilities.CAPABILITY_TYPE_UT
+ );
+ callback.onCapabilitiesStatusChanged(capabilities);
+
+ assertTrue(mImsStateTracker.isImsStateReady());
+ assertTrue(mImsStateTracker.isImsVoiceCapable());
+ assertTrue(mImsStateTracker.isImsVideoCapable());
+ assertTrue(mImsStateTracker.isImsSmsCapable());
+ assertTrue(mImsStateTracker.isImsUtCapable());
+
+ capabilities = new MmTelCapabilities();
+ callback.onCapabilitiesStatusChanged(capabilities);
+
+ assertTrue(mImsStateTracker.isImsStateReady());
+ assertFalse(mImsStateTracker.isImsVoiceCapable());
+ assertFalse(mImsStateTracker.isImsVideoCapable());
+ assertFalse(mImsStateTracker.isImsSmsCapable());
+ assertFalse(mImsStateTracker.isImsUtCapable());
+
+ verify(mImsStateListener, times(2)).onImsMmTelCapabilitiesChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testAddImsStateListenerWhenImsStateReady() throws ImsException {
+ ImsMmTelManager.CapabilityCallback callback = setUpMmTelCapabilityCallback();
+
+ MmTelCapabilities capabilities = new MmTelCapabilities(
+ MmTelCapabilities.CAPABILITY_TYPE_VOICE
+ | MmTelCapabilities.CAPABILITY_TYPE_VIDEO
+ | MmTelCapabilities.CAPABILITY_TYPE_SMS
+ | MmTelCapabilities.CAPABILITY_TYPE_UT
+ );
+ callback.onCapabilitiesStatusChanged(capabilities);
+
+ ImsStateTracker.ImsStateListener listener =
+ Mockito.mock(ImsStateTracker.ImsStateListener.class);
+ mImsStateTracker.addImsStateListener(listener);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verify(listener).onImsMmTelFeatureAvailableChanged();
+ verify(listener).onImsRegistrationStateChanged();
+ verify(listener).onImsMmTelCapabilitiesChanged();
+ }
+
+ @Test
+ @SmallTest
+ public void testAddAndRemoveImsStateListenerWhenImsStateReady() throws ImsException {
+ ImsMmTelManager.CapabilityCallback callback = setUpMmTelCapabilityCallback();
+
+ MmTelCapabilities capabilities = new MmTelCapabilities(
+ MmTelCapabilities.CAPABILITY_TYPE_VOICE
+ | MmTelCapabilities.CAPABILITY_TYPE_VIDEO
+ | MmTelCapabilities.CAPABILITY_TYPE_SMS
+ | MmTelCapabilities.CAPABILITY_TYPE_UT
+ );
+ callback.onCapabilitiesStatusChanged(capabilities);
+
+ Handler handler = new Handler(mLooper);
+ ImsStateTracker.ImsStateListener listener =
+ Mockito.mock(ImsStateTracker.ImsStateListener.class);
+ handler.post(() -> {
+ mImsStateTracker.addImsStateListener(listener);
+ mImsStateTracker.removeImsStateListener(listener);
+ });
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ verify(listener, never()).onImsMmTelFeatureAvailableChanged();
+ verify(listener, never()).onImsRegistrationStateChanged();
+ verify(listener, never()).onImsMmTelCapabilitiesChanged();
+ }
+
+ private ImsStateCallback setUpImsStateCallback() throws ImsException {
+ mImsStateTracker.start(SUB_1);
+ mImsStateTracker.addImsStateListener(mImsStateListener);
+ waitForHandlerAction(mImsStateTracker.getHandler(), TIMEOUT_MS);
+
+ assertEquals(SUB_1, mImsStateTracker.getSubId());
+ assertFalse(mImsStateTracker.isMmTelFeatureAvailable());
+ ArgumentCaptor<ImsStateCallback> callbackCaptor =
+ ArgumentCaptor.forClass(ImsStateCallback.class);
+ verify(mMmTelManager).registerImsStateCallback(
+ any(Executor.class), callbackCaptor.capture());
+
+ ImsStateCallback imsStateCallback = callbackCaptor.getValue();
+ assertNotNull(imsStateCallback);
+ return imsStateCallback;
+ }
+
+ private RegistrationManager.RegistrationCallback setUpImsRegistrationCallback()
+ throws ImsException {
+ ImsStateCallback imsStateCallback = setUpImsStateCallback();
+ imsStateCallback.onAvailable();
+
+ assertTrue(mImsStateTracker.isMmTelFeatureAvailable());
+ ArgumentCaptor<RegistrationManager.RegistrationCallback> callbackCaptor =
+ ArgumentCaptor.forClass(RegistrationManager.RegistrationCallback.class);
+ verify(mMmTelManager).registerImsRegistrationCallback(
+ any(Executor.class), callbackCaptor.capture());
+
+ RegistrationManager.RegistrationCallback registrationCallback = callbackCaptor.getValue();
+ assertNotNull(registrationCallback);
+ return registrationCallback;
+ }
+
+ private ImsMmTelManager.CapabilityCallback setUpMmTelCapabilityCallback()
+ throws ImsException {
+ RegistrationManager.RegistrationCallback registrationCallback =
+ setUpImsRegistrationCallback();
+ registrationCallback.onRegistered(new ImsRegistrationAttributes.Builder(
+ ImsRegistrationImplBase.REGISTRATION_TECH_LTE).build());
+
+ assertTrue(mImsStateTracker.isMmTelFeatureAvailable());
+ // It's false because the MMTEL capabilities are not updated.
+ assertFalse(mImsStateTracker.isImsStateReady());
+ assertTrue(mImsStateTracker.isImsRegistered());
+ assertFalse(mImsStateTracker.isImsRegisteredOverWlan());
+ assertEquals(AccessNetworkType.EUTRAN, mImsStateTracker.getImsAccessNetworkType());
+ ArgumentCaptor<ImsMmTelManager.CapabilityCallback> callbackCaptor =
+ ArgumentCaptor.forClass(ImsMmTelManager.CapabilityCallback.class);
+ verify(mMmTelManager).registerMmTelCapabilityCallback(
+ any(Executor.class), callbackCaptor.capture());
+
+ ImsMmTelManager.CapabilityCallback capabilityCallback = callbackCaptor.getValue();
+ assertNotNull(capabilityCallback);
+ return capabilityCallback;
+ }
+
+ private boolean isImsStateUnavailable() {
+ return mImsStateTracker.isImsStateReady()
+ && !mImsStateTracker.isImsRegistered()
+ && !mImsStateTracker.isMmTelFeatureAvailable()
+ && !mImsStateTracker.isImsVoiceCapable()
+ && !mImsStateTracker.isImsVideoCapable()
+ && !mImsStateTracker.isImsSmsCapable()
+ && !mImsStateTracker.isImsUtCapable()
+ && (AccessNetworkType.UNKNOWN == mImsStateTracker.getImsAccessNetworkType());
+ }
+
+ private boolean isImsStateInit() {
+ return !mImsStateTracker.isImsStateReady()
+ && !mImsStateTracker.isImsRegistered()
+ && !mImsStateTracker.isMmTelFeatureAvailable()
+ && !mImsStateTracker.isImsVoiceCapable()
+ && !mImsStateTracker.isImsVideoCapable()
+ && !mImsStateTracker.isImsSmsCapable()
+ && !mImsStateTracker.isImsUtCapable()
+ && (AccessNetworkType.UNKNOWN == mImsStateTracker.getImsAccessNetworkType());
+ }
+
+ private void waitForHandlerAction(Handler h, long timeoutMillis) {
+ waitForHandlerActionDelayed(h, 0, timeoutMillis);
+ }
+
+ private void waitForHandlerActionDelayed(Handler h, long delayMillis, long timeoutMillis) {
+ final CountDownLatch lock = new CountDownLatch(1);
+ h.postDelayed(lock::countDown, delayMillis);
+ while (lock.getCount() > 0) {
+ try {
+ lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+ }
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
new file mode 100644
index 0000000..4dd1f3c
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
@@ -0,0 +1,522 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_UT;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.CancellationSignal;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.telecom.TelecomManager;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.CarrierConfigManager;
+import android.telephony.DisconnectCause;
+import android.telephony.DomainSelectionService;
+import android.telephony.DomainSelector;
+import android.telephony.EmergencyRegResult;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TransportSelectorCallback;
+import android.telephony.WwanSelectorCallback;
+import android.telephony.ims.ImsManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsReasonInfo;
+import android.util.Log;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.function.Consumer;
+
+/**
+ * Unit tests for DomainSelectorBase.
+ */
+@RunWith(AndroidJUnit4.class)
+public class NormalCallDomainSelectorTest {
+ private static final String TAG = "NormalCallDomainSelectorTest";
+
+ private static final int SLOT_ID = 0;
+ private static final int SUB_ID_1 = 1;
+ private static final int SUB_ID_2 = 2;
+ private static final String TEST_CALLID = "01234";
+
+ private HandlerThread mHandlerThread;
+ private NormalCallDomainSelector mNormalCallDomainSelector;
+
+ @Mock private Context mMockContext;
+ @Mock private CarrierConfigManager mMockCarrierConfigMgr;
+ @Mock private ImsManager mMockImsManager;
+ @Mock private ImsMmTelManager mMockMmTelManager;
+ @Mock private ImsStateTracker mMockImsStateTracker;
+ @Mock private DomainSelectorBase.DestroyListener mMockDestroyListener;
+ @Mock private TelecomManager mMockTelecomManager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ doReturn(Context.TELEPHONY_IMS_SERVICE).when(mMockContext)
+ .getSystemServiceName(ImsManager.class);
+ doReturn(mMockImsManager).when(mMockContext)
+ .getSystemService(Context.TELEPHONY_IMS_SERVICE);
+
+ doReturn(Context.CARRIER_CONFIG_SERVICE).when(mMockContext)
+ .getSystemServiceName(CarrierConfigManager.class);
+ doReturn(mMockCarrierConfigMgr).when(mMockContext)
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+
+ doReturn(Context.TELECOM_SERVICE).when(mMockContext)
+ .getSystemServiceName(TelecomManager.class);
+ doReturn(mMockTelecomManager).when(mMockContext)
+ .getSystemService(Context.TELECOM_SERVICE);
+
+ doReturn(mMockMmTelManager).when(mMockImsManager).getImsMmTelManager(SUB_ID_1);
+ doReturn(mMockMmTelManager).when(mMockImsManager).getImsMmTelManager(SUB_ID_2);
+ doNothing().when(mMockImsStateTracker).removeServiceStateListener(any());
+ doNothing().when(mMockImsStateTracker).removeImsStateListener(any());
+ doReturn(true).when(mMockImsStateTracker).isMmTelFeatureAvailable();
+
+ // Set up the looper if it does not exist on the test thread.
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ mHandlerThread = new HandlerThread(
+ NormalCallDomainSelectorTest.class.getSimpleName());
+ mHandlerThread.start();
+
+ mNormalCallDomainSelector = new NormalCallDomainSelector(mMockContext, SLOT_ID, SUB_ID_1,
+ mHandlerThread.getLooper(), mMockImsStateTracker, mMockDestroyListener);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mHandlerThread != null) {
+ mHandlerThread.quit();
+ }
+ }
+
+ private void initialize(ServiceState serviceState, boolean isImsRegistered,
+ boolean isImsRegisteredOverWlan, boolean isImsVoiceCapable,
+ boolean isImsVideoCapable) {
+ if (serviceState != null) mNormalCallDomainSelector.onServiceStateUpdated(serviceState);
+ doReturn(isImsRegistered).when(mMockImsStateTracker).isImsStateReady();
+ doReturn(isImsRegistered).when(mMockImsStateTracker).isImsRegistered();
+ doReturn(isImsVoiceCapable).when(mMockImsStateTracker).isImsVoiceCapable();
+ doReturn(isImsVideoCapable).when(mMockImsStateTracker).isImsVideoCapable();
+ doReturn(isImsRegisteredOverWlan).when(mMockImsStateTracker).isImsRegisteredOverWlan();
+ mNormalCallDomainSelector.onImsRegistrationStateChanged();
+ mNormalCallDomainSelector.onImsMmTelCapabilitiesChanged();
+ }
+
+ @Test
+ public void testInit() {
+ assertEquals(SLOT_ID, mNormalCallDomainSelector.getSlotId());
+ assertEquals(SUB_ID_1, mNormalCallDomainSelector.getSubId());
+ }
+
+ @Test
+ public void testSelectDomainInputParams() {
+ MockTransportSelectorCallback transportSelectorCallback =
+ new MockTransportSelectorCallback();
+
+ DomainSelectionService.SelectionAttributes attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(true)
+ .setExitedFromAirplaneMode(false)
+ .build();
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+
+
+ // Case 1: null inputs
+ try {
+ mNormalCallDomainSelector.selectDomain(null, null);
+ } catch (Exception e) {
+ fail("Invalid input params not handled." + e.getMessage());
+ }
+
+ // Case 2: null TransportSelectorCallback
+ try {
+ mNormalCallDomainSelector.selectDomain(attributes, null);
+ } catch (Exception e) {
+ fail("Invalid params (SelectionAttributes) not handled." + e.getMessage());
+ }
+
+ // Case 3: null SelectionAttributes
+ transportSelectorCallback.mSelectionTerminated = false;
+ try {
+ mNormalCallDomainSelector.selectDomain(null, transportSelectorCallback);
+ } catch (Exception e) {
+ fail("Invalid params (SelectionAttributes) not handled." + e.getMessage());
+ }
+
+ assertTrue(transportSelectorCallback
+ .verifyOnSelectionTerminated(DisconnectCause.OUTGOING_FAILURE));
+
+ // Case 4: Invalid Subscription-id
+ attributes = new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID, SELECTOR_TYPE_CALLING)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(true)
+ .setExitedFromAirplaneMode(false)
+ .build();
+ try {
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ } catch (Exception e) {
+ fail("Invalid params (SelectionAttributes) not handled." + e.getMessage());
+ }
+
+ assertTrue(transportSelectorCallback
+ .verifyOnSelectionTerminated(DisconnectCause.OUTGOING_FAILURE));
+
+ // Case 5: Invalid SELECTOR_TYPE
+ attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_UT)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(true)
+ .setExitedFromAirplaneMode(false)
+ .build();
+ try {
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ } catch (Exception e) {
+ fail("Invalid params (SelectionAttributes) not handled." + e.getMessage());
+ }
+
+ assertTrue(transportSelectorCallback
+ .verifyOnSelectionTerminated(DisconnectCause.OUTGOING_FAILURE));
+
+ // Case 6: Emergency Call
+ attributes = new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setCallId(TEST_CALLID)
+ .setEmergency(true)
+ .setVideoCall(true)
+ .setExitedFromAirplaneMode(false)
+ .build();
+ try {
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ } catch (Exception e) {
+ fail("Invalid params (SelectionAttributes) not handled." + e.getMessage());
+ }
+
+ assertTrue(transportSelectorCallback
+ .verifyOnSelectionTerminated(DisconnectCause.OUTGOING_FAILURE));
+ }
+
+ @Test
+ public void testOutOfService() {
+ MockTransportSelectorCallback transportSelectorCallback =
+ new MockTransportSelectorCallback();
+ DomainSelectionService.SelectionAttributes attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(true)
+ .setExitedFromAirplaneMode(false)
+ .build();
+ ServiceState serviceState = new ServiceState();
+ serviceState.setStateOutOfService();
+ initialize(serviceState, false, false, false, false);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback
+ .verifyOnSelectionTerminated(DisconnectCause.OUT_OF_SERVICE));
+ }
+
+ @Test
+ public void testDomainSelection() {
+ MockTransportSelectorCallback transportSelectorCallback =
+ new MockTransportSelectorCallback();
+ DomainSelectionService.SelectionAttributes attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(false)
+ .setExitedFromAirplaneMode(false)
+ .build();
+
+ // Case 1: WLAN
+ ServiceState serviceState = new ServiceState();
+ serviceState.setState(ServiceState.STATE_IN_SERVICE);
+ initialize(serviceState, true, true, true, true);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWlanSelected());
+
+ // Case 2: 5G
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ initialize(serviceState, true, false, true, true);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+ assertTrue(transportSelectorCallback
+ .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_PS));
+
+ // Case 3: PS -> CS redial
+ ImsReasonInfo imsReasonInfo = new ImsReasonInfo();
+ imsReasonInfo.mCode = ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED;
+ attributes = new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(false)
+ .setExitedFromAirplaneMode(false)
+ .setPsDisconnectCause(imsReasonInfo)
+ .build();
+ mNormalCallDomainSelector.reselectDomain(attributes);
+ assertTrue(transportSelectorCallback
+ .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_CS));
+
+ // Case 4: CS call
+ NetworkRegistrationInfo nwRegistrationInfo = new NetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
+ AccessNetworkConstants.AccessNetworkType.UTRAN, 0, false,
+ null, null, null, false, 0, 0, 0);
+ serviceState.addNetworkRegistrationInfo(nwRegistrationInfo);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ initialize(serviceState, false, false, false, false);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+ assertTrue(transportSelectorCallback
+ .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_CS));
+
+ //Case 5: Backup calling
+ serviceState.setStateOutOfService();
+ initialize(serviceState, true, true, true, true);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWlanSelected());
+ }
+
+ @Test
+ public void testWPSCallDomainSelection() {
+ MockTransportSelectorCallback transportSelectorCallback =
+ new MockTransportSelectorCallback();
+ DomainSelectionService.SelectionAttributes attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setNumber("*272121")
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(false)
+ .setExitedFromAirplaneMode(false)
+ .build();
+
+ //Case 1: WPS not supported by IMS
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, false);
+ doReturn(config).when(mMockCarrierConfigMgr).getConfigForSubId(SUB_ID_1);
+ ServiceState serviceState = new ServiceState();
+ serviceState.setState(ServiceState.STATE_IN_SERVICE);
+ initialize(serviceState, true, true, true, true);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+ assertTrue(transportSelectorCallback
+ .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_CS));
+
+ //Case 2: WPS supported by IMS and WLAN registered
+ config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
+ serviceState.setState(ServiceState.STATE_IN_SERVICE);
+ initialize(serviceState, true, true, true, true);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWlanSelected());
+
+ //Case 2: WPS supported by IMS and LTE registered
+ config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, true);
+ serviceState.setState(ServiceState.STATE_IN_SERVICE);
+ initialize(serviceState, true, false, true, true);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+ assertTrue(transportSelectorCallback
+ .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_PS));
+ }
+
+ @Test
+ public void testTtyCallDomainSelection() {
+ MockTransportSelectorCallback transportSelectorCallback =
+ new MockTransportSelectorCallback();
+ DomainSelectionService.SelectionAttributes attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(false)
+ .setExitedFromAirplaneMode(false)
+ .build();
+
+ //Case 1: TTY not supported by IMS and TTY enabled
+ doReturn(TelecomManager.TTY_MODE_FULL).when(mMockTelecomManager).getCurrentTtyMode();
+ PersistableBundle config = new PersistableBundle();
+ config.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, false);
+ doReturn(config).when(mMockCarrierConfigMgr).getConfigForSubId(SUB_ID_1);
+ ServiceState serviceState = new ServiceState();
+ serviceState.setState(ServiceState.STATE_IN_SERVICE);
+ initialize(serviceState, true, false, true, true);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+ assertTrue(transportSelectorCallback
+ .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_CS));
+
+ //Case 2: TTY supported by IMS and TTY enabled
+ config.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, true);
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+ assertTrue(transportSelectorCallback
+ .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_PS));
+
+ //Case 3: TTY supported by IMS and TTY disabled
+ doReturn(TelecomManager.TTY_MODE_OFF).when(mMockTelecomManager).getCurrentTtyMode();
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertTrue(transportSelectorCallback.verifyOnWwanSelected());
+ assertTrue(transportSelectorCallback
+ .verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_PS));
+ }
+
+ static class MockTransportSelectorCallback implements TransportSelectorCallback,
+ WwanSelectorCallback {
+ public boolean mCreated;
+ public boolean mWlanSelected;
+ public boolean mWwanSelected;
+ public boolean mSelectionTerminated;
+ public boolean mDomainSelected;
+ int mCauseCode;
+ int mSelectedDomain;
+
+ @Override
+ public synchronized void onCreated(DomainSelector selector) {
+ Log.d(TAG, "onCreated");
+ mCreated = true;
+ notifyAll();
+ }
+
+ public boolean verifyOnCreated() {
+ mCreated = false;
+ Log.d(TAG, "verifyOnCreated");
+ waitForCallback(mCreated);
+ return mCreated;
+ }
+
+ @Override
+ public synchronized void onWlanSelected(boolean useEmergencyPdn) {
+ Log.d(TAG, "onWlanSelected");
+ mWlanSelected = true;
+ notifyAll();
+ }
+
+ public boolean verifyOnWlanSelected() {
+ Log.d(TAG, "verifyOnWlanSelected");
+ waitForCallback(mWlanSelected);
+ return mWlanSelected;
+ }
+
+ @Override
+ public synchronized WwanSelectorCallback onWwanSelected() {
+ mWwanSelected = true;
+ notifyAll();
+ return (WwanSelectorCallback) this;
+ }
+
+ @Override
+ public void onWwanSelected(final Consumer<WwanSelectorCallback> consumer) {
+ mWwanSelected = true;
+ Executors.newSingleThreadExecutor().execute(() -> {
+ consumer.accept(this);
+ });
+ }
+
+ public boolean verifyOnWwanSelected() {
+ waitForCallback(mWwanSelected);
+ return mWwanSelected;
+ }
+
+ @Override
+ public synchronized void onSelectionTerminated(int cause) {
+ Log.i(TAG, "onSelectionTerminated - called");
+ mCauseCode = cause;
+ mSelectionTerminated = true;
+ notifyAll();
+ }
+
+ public boolean verifyOnSelectionTerminated(int cause) {
+ Log.i(TAG, "verifyOnSelectionTerminated - called");
+ waitForCallback(mSelectionTerminated);
+ return (mSelectionTerminated && cause == mCauseCode);
+ }
+
+ private synchronized void waitForCallback(boolean condition) {
+ long now = System.currentTimeMillis();
+ long deadline = now + 1000;
+ try {
+ while (!condition && now < deadline) {
+ wait(deadline - now);
+ now = System.currentTimeMillis();
+ }
+ } catch (Exception e) {
+ Log.i(TAG, e.getMessage());
+ }
+ }
+
+ @Override
+ public void onRequestEmergencyNetworkScan(@NonNull List<Integer> preferredNetworks,
+ int scanType,
+ @NonNull CancellationSignal signal,
+ @NonNull Consumer<EmergencyRegResult> consumer) {
+ Log.i(TAG, "onRequestEmergencyNetworkScan - called");
+
+ }
+
+ public synchronized void onDomainSelected(@NetworkRegistrationInfo.Domain int domain,
+ boolean useEmergencyPdn) {
+ Log.i(TAG, "onDomainSelected - called");
+ mSelectedDomain = domain;
+ mDomainSelected = true;
+ notifyAll();
+ }
+
+ public boolean verifyOnDomainSelected(int domain) {
+ Log.i(TAG, "verifyOnDomainSelected - called");
+ mDomainSelected = false;
+ waitForCallback(mDomainSelected);
+ return (domain == mSelectedDomain);
+ }
+ }
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/SmsDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/SmsDomainSelectorTest.java
new file mode 100644
index 0000000..785127c
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/SmsDomainSelectorTest.java
@@ -0,0 +1,444 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_SMS;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.TransportSelectorCallback;
+import android.telephony.WwanSelectorCallback;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableLooper;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TestContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Consumer;
+
+/**
+ * Unit tests for SmsDomainSelector.
+ */
+@RunWith(AndroidJUnit4.class)
+public class SmsDomainSelectorTest {
+ private static final String LOG_TAG = "DomainSelector-SMS";
+ private static final int SLOT_0 = 0;
+ private static final int SUB_1 = 1;
+ private static final int SUB_2 = 2;
+
+ @Mock private TransportSelectorCallback mTransportSelectorCallback;
+ @Mock private WwanSelectorCallback mWwanSelectorCallback;
+ @Mock private ImsStateTracker mImsStateTracker;
+ @Mock private DomainSelectorBase.DestroyListener mDomainSelectorDestroyListener;
+
+ private final SelectionAttributes mSelectionAttributes =
+ new SelectionAttributes.Builder(SLOT_0, SUB_1, SELECTOR_TYPE_SMS).build();
+ private Context mContext;
+ private Looper mLooper;
+ private TestableLooper mTestableLooper;
+ private SmsDomainSelector mDomainSelector;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext();
+ HandlerThread handlerThread = new HandlerThread(
+ SmsDomainSelectorTest.class.getSimpleName());
+ handlerThread.start();
+ mLooper = handlerThread.getLooper();
+ mTestableLooper = new TestableLooper(mLooper);
+ mDomainSelector = new SmsDomainSelector(mContext, SLOT_0, SUB_1,
+ mLooper, mImsStateTracker, mDomainSelectorDestroyListener);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mTestableLooper != null) {
+ mTestableLooper.destroy();
+ mTestableLooper = null;
+ }
+
+ if (mDomainSelector != null) {
+ mDomainSelector.destroy();
+ verify(mImsStateTracker).removeImsStateListener(eq(mDomainSelector));
+ }
+
+ if (mLooper != null) {
+ mLooper.quit();
+ mLooper = null;
+ }
+
+ mDomainSelector = null;
+ mWwanSelectorCallback = null;
+ mTransportSelectorCallback = null;
+ mImsStateTracker = null;
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnEutran() {
+ selectDomain(AccessNetworkType.EUTRAN);
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnNgran() {
+ selectDomain(AccessNetworkType.NGRAN);
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsRegisteredOnIwlan() {
+ selectDomain(AccessNetworkType.IWLAN);
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenImsNotRegistered() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpImsStateListener(true, false, false);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenWwanSelectorCallbackNull() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ doAnswer((invocation) -> {
+ Object[] args = invocation.getArguments();
+ final Consumer<WwanSelectorCallback> callback =
+ (Consumer<WwanSelectorCallback>) args[0];
+ callback.accept(null);
+ return null;
+ }).when(mTransportSelectorCallback).onWwanSelected(any(Consumer.class));
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mTransportSelectorCallback).onSelectionTerminated(anyInt());
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhilePreviousRequestInProgress() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ processAllMessages();
+
+ // onDomainSelected will be invoked only once
+ // even though the domain selection was requested twice.
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testCancelSelection() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ mDomainSelector.cancelSelection();
+
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ verify(mDomainSelectorDestroyListener).onDomainSelectorDestroyed(eq(mDomainSelector));
+ }
+
+ @Test
+ @SmallTest
+ public void testFinishSelection() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ mDomainSelector.finishSelection();
+
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ verify(mDomainSelectorDestroyListener).onDomainSelectorDestroyed(eq(mDomainSelector));
+ }
+
+ @Test
+ @SmallTest
+ public void testReselectDomain() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN, AccessNetworkType.IWLAN);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+
+ mDomainSelector.reselectDomain(mSelectionAttributes);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mTransportSelectorCallback).onWlanSelected(eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testReselectDomainWhilePreviousRequestInProgress() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN, AccessNetworkType.IWLAN);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ mDomainSelector.reselectDomain(mSelectionAttributes);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ verify(mTransportSelectorCallback, never()).onWlanSelected(eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testOnImsRegistrationStateChangedWhenNotRegistered() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpImsStateListener(false, true, false);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testOnImsRegistrationStateChangedWhenRegisteredAndSmsCapable() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN, true);
+ setUpImsStateListener(false, true, false);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testOnImsRegistrationStateChangedWhenRegisteredAndSmsIncapable() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN, false);
+ setUpImsStateListener(false, true, false);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testOnImsMmTelCapabilitiesChangedWhenSmsCapable() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN, true);
+ setUpImsStateListener(false, false, true);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ @Test
+ @SmallTest
+ public void testOnImsMmTelCapabilitiesChangedWhenSmsIncapable() {
+ setUpImsStateTracker(AccessNetworkType.EUTRAN, false);
+ setUpImsStateListener(false, false, true);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ private void selectDomain(@RadioAccessNetworkType int accessNetworkType) {
+ setUpImsStateTracker(accessNetworkType);
+ setUpWwanSelectorCallback();
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+
+ assertTrue(mDomainSelector.isDomainSelectionRequested());
+
+ processAllMessages();
+
+ if (accessNetworkType == AccessNetworkType.IWLAN) {
+ verify(mTransportSelectorCallback).onWlanSelected(eq(false));
+ } else {
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(false));
+ }
+ assertFalse(mDomainSelector.isDomainSelectionRequested());
+ }
+
+ private void setUpImsStateTracker(@RadioAccessNetworkType int accessNetworkType) {
+ setUpImsStateTracker(accessNetworkType, true);
+ }
+
+ private void setUpImsStateTracker(@RadioAccessNetworkType int accessNetworkType,
+ boolean smsCapable) {
+ when(mImsStateTracker.isMmTelFeatureAvailable()).thenReturn(true);
+ when(mImsStateTracker.isImsRegistered())
+ .thenReturn(accessNetworkType != AccessNetworkType.UNKNOWN);
+ when(mImsStateTracker.isImsRegisteredOverWlan())
+ .thenReturn(accessNetworkType == AccessNetworkType.IWLAN);
+ when(mImsStateTracker.getImsAccessNetworkType()).thenReturn(accessNetworkType);
+ when(mImsStateTracker.isImsSmsCapable()).thenReturn(smsCapable);
+ }
+
+ private void setUpImsStateTracker(@RadioAccessNetworkType int firstAccessNetworkType,
+ @RadioAccessNetworkType int secondAccessNetworkType) {
+ when(mImsStateTracker.isMmTelFeatureAvailable()).thenReturn(true);
+ when(mImsStateTracker.isImsRegistered()).thenReturn(
+ firstAccessNetworkType != AccessNetworkType.UNKNOWN,
+ secondAccessNetworkType != AccessNetworkType.UNKNOWN);
+ when(mImsStateTracker.isImsRegisteredOverWlan()).thenReturn(
+ firstAccessNetworkType == AccessNetworkType.IWLAN,
+ secondAccessNetworkType == AccessNetworkType.IWLAN);
+ when(mImsStateTracker.getImsAccessNetworkType()).thenReturn(
+ firstAccessNetworkType,
+ secondAccessNetworkType);
+ when(mImsStateTracker.isImsSmsCapable()).thenReturn(true);
+ }
+
+ private void setUpWwanSelectorCallback() {
+ doAnswer((invocation) -> {
+ Object[] args = invocation.getArguments();
+ final Consumer<WwanSelectorCallback> callback =
+ (Consumer<WwanSelectorCallback>) args[0];
+ callback.accept(mWwanSelectorCallback);
+ return null;
+ }).when(mTransportSelectorCallback).onWwanSelected(any(Consumer.class));
+ }
+
+ private void setUpImsStateListener(boolean notifyMmTelFeatureAvailable,
+ boolean notifyImsRegState, boolean notifyMmTelCapability) {
+ doAnswer((invocation) -> {
+ Object[] args = invocation.getArguments();
+ final ImsStateTracker.ImsStateListener listener =
+ (ImsStateTracker.ImsStateListener) args[0];
+ mDomainSelector.post(() -> {
+ if (notifyMmTelFeatureAvailable) {
+ listener.onImsMmTelFeatureAvailableChanged();
+ }
+ if (notifyImsRegState) {
+ listener.onImsRegistrationStateChanged();
+ }
+ if (notifyMmTelCapability) {
+ listener.onImsMmTelCapabilitiesChanged();
+ }
+ });
+ return null;
+ }).when(mImsStateTracker).addImsStateListener(any(ImsStateTracker.ImsStateListener.class));
+ }
+
+ private void processAllMessages() {
+ while (!mTestableLooper.getLooper().getQueue().isIdle()) {
+ mTestableLooper.processAllMessages();
+ }
+ }
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java b/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java
new file mode 100644
index 0000000..f340e94
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java
@@ -0,0 +1,366 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.services.telephony.domainselection;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.telephony.BarringInfo;
+import android.telephony.DomainSelectionService;
+import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.DomainSelectionService.SelectorType;
+import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
+import android.telephony.TransportSelectorCallback;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.TestableLooper;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.TestContext;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Unit tests for TelephonyDomainSelectionService.
+ */
+@RunWith(AndroidJUnit4.class)
+public class TelephonyDomainSelectionServiceTest {
+ private TelephonyDomainSelectionService.ImsStateTrackerFactory mImsStateTrackerFactory =
+ new TelephonyDomainSelectionService.ImsStateTrackerFactory() {
+ @Override
+ public ImsStateTracker create(Context context, int slotId,
+ @NonNull Looper looper) {
+ return mImsStateTracker;
+ }
+ };
+ private TelephonyDomainSelectionService.DomainSelectorFactory mDomainSelectorFactory =
+ new TelephonyDomainSelectionService.DomainSelectorFactory() {
+ @Override
+ public DomainSelectorBase create(Context context, int slotId, int subId,
+ @SelectorType int selectorType, boolean isEmergency,
+ @NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
+ @NonNull DomainSelectorBase.DestroyListener listener,
+ @NonNull CrossSimRedialingController crossSimRedialingController) {
+ switch (selectorType) {
+ case DomainSelectionService.SELECTOR_TYPE_CALLING: // fallthrough
+ case DomainSelectionService.SELECTOR_TYPE_SMS: // fallthrough
+ case DomainSelectionService.SELECTOR_TYPE_UT:
+ mDomainSelectorDestroyListener = listener;
+ if (subId == SUB_1) {
+ return mDomainSelectorBase1;
+ } else {
+ return mDomainSelectorBase2;
+ }
+ default:
+ return null;
+ }
+ }
+ };
+ private static final int SLOT_0 = 0;
+ private static final int SUB_1 = 1;
+ private static final int SUB_2 = 2;
+ private static final String CALL_ID = "Call_1";
+ private static final @SelectorType int TEST_SELECTOR_TYPE =
+ DomainSelectionService.SELECTOR_TYPE_CALLING;
+ private static final @SelectorType int INVALID_SELECTOR_TYPE = -1;
+
+ @Mock private DomainSelectorBase mDomainSelectorBase1;
+ @Mock private DomainSelectorBase mDomainSelectorBase2;
+ @Mock private TransportSelectorCallback mSelectorCallback1;
+ @Mock private TransportSelectorCallback mSelectorCallback2;
+ @Mock private ImsStateTracker mImsStateTracker;
+
+ private final ServiceState mServiceState = new ServiceState();
+ private final BarringInfo mBarringInfo = new BarringInfo();
+ private Context mContext;
+ private Handler mServiceHandler;
+ private TestableLooper mTestableLooper;
+ private SubscriptionManager mSubscriptionManager;
+ private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener;
+ private DomainSelectorBase.DestroyListener mDomainSelectorDestroyListener;
+ private TelephonyDomainSelectionService mDomainSelectionService;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ mContext = new TestContext();
+ mDomainSelectionService = new TelephonyDomainSelectionService(mContext,
+ mImsStateTrackerFactory, mDomainSelectorFactory);
+ mServiceHandler = new Handler(mDomainSelectionService.getLooper());
+ mTestableLooper = new TestableLooper(mDomainSelectionService.getLooper());
+
+ mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
+ ArgumentCaptor<OnSubscriptionsChangedListener> listenerCaptor =
+ ArgumentCaptor.forClass(OnSubscriptionsChangedListener.class);
+ verify(mSubscriptionManager).addOnSubscriptionsChangedListener(
+ any(Executor.class), listenerCaptor.capture());
+ mOnSubscriptionsChangedListener = listenerCaptor.getValue();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mTestableLooper != null) {
+ mTestableLooper.destroy();
+ mTestableLooper = null;
+ }
+ mServiceHandler = null;
+
+ if (mDomainSelectionService != null) {
+ mDomainSelectionService.onDestroy();
+ mDomainSelectionService = null;
+ }
+
+ mDomainSelectorBase1 = null;
+ mDomainSelectorBase2 = null;
+ mSelectorCallback1 = null;
+ mSelectorCallback2 = null;
+ mImsStateTracker = null;
+ mSubscriptionManager = null;
+ mOnSubscriptionsChangedListener = null;
+ mDomainSelectorDestroyListener = null;
+ }
+
+ @Test
+ @SmallTest
+ public void testGetExecutor() {
+ assertNotNull(mDomainSelectionService.getExecutor());
+ }
+
+ @Test
+ @SmallTest
+ public void testOnDomainSelection() {
+ SelectionAttributes attr1 = new SelectionAttributes.Builder(
+ SLOT_0, SUB_1, TEST_SELECTOR_TYPE)
+ .setCallId(CALL_ID)
+ .setEmergency(true)
+ .build();
+ mServiceHandler.post(() -> {
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
+ });
+ processAllMessages();
+
+ verify(mImsStateTracker).start(eq(SUB_1));
+ verify(mSelectorCallback1).onCreated(eq(mDomainSelectorBase1));
+ verifyNoMoreInteractions(mSelectorCallback1);
+ verify(mDomainSelectorBase1).selectDomain(eq(attr1), eq(mSelectorCallback1));
+ }
+
+ @Test
+ @SmallTest
+ public void testOnDomainSelectionWithInvalidSelectorType() {
+ SelectionAttributes attr1 = new SelectionAttributes.Builder(
+ SLOT_0, SUB_1, INVALID_SELECTOR_TYPE)
+ .setCallId(CALL_ID)
+ .setEmergency(true)
+ .build();
+ mServiceHandler.post(() -> {
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
+ });
+ processAllMessages();
+
+ verify(mImsStateTracker, never()).start(anyInt());
+ verify(mSelectorCallback1).onSelectionTerminated(anyInt());
+ verifyNoMoreInteractions(mSelectorCallback1);
+ verify(mDomainSelectorBase1, never()).selectDomain(eq(attr1), eq(mSelectorCallback1));
+ }
+
+ @Test
+ @SmallTest
+ public void testOnDomainSelectionTwiceWithDestroy() {
+ SelectionAttributes attr1 = new SelectionAttributes.Builder(
+ SLOT_0, SUB_1, TEST_SELECTOR_TYPE)
+ .setCallId(CALL_ID)
+ .setEmergency(true)
+ .build();
+ mServiceHandler.post(() -> {
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
+ });
+ processAllMessages();
+
+ verify(mImsStateTracker).start(eq(SUB_1));
+ verify(mSelectorCallback1).onCreated(eq(mDomainSelectorBase1));
+ verifyNoMoreInteractions(mSelectorCallback1);
+ verify(mDomainSelectorBase1).selectDomain(eq(attr1), eq(mSelectorCallback1));
+
+ // Notify the domain selection service that this domain selector is destroyed.
+ mDomainSelectorDestroyListener.onDomainSelectorDestroyed(mDomainSelectorBase1);
+
+ SelectionAttributes attr2 = new SelectionAttributes.Builder(
+ SLOT_0, SUB_2, TEST_SELECTOR_TYPE)
+ .setCallId(CALL_ID)
+ .setEmergency(true)
+ .build();
+ mServiceHandler.post(() -> {
+ mDomainSelectionService.onDomainSelection(attr2, mSelectorCallback2);
+ });
+ processAllMessages();
+
+ verify(mImsStateTracker).start(eq(SUB_2));
+ verify(mSelectorCallback2).onCreated(eq(mDomainSelectorBase2));
+ verifyNoMoreInteractions(mSelectorCallback2);
+ verify(mDomainSelectorBase2).selectDomain(eq(attr2), eq(mSelectorCallback2));
+ }
+
+ @Test
+ @SmallTest
+ public void testOnDomainSelectionTwiceWithoutDestroy() {
+ SelectionAttributes attr1 = new SelectionAttributes.Builder(
+ SLOT_0, SUB_1, TEST_SELECTOR_TYPE)
+ .setCallId(CALL_ID)
+ .setEmergency(true)
+ .build();
+ mServiceHandler.post(() -> {
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
+ });
+ processAllMessages();
+
+ verify(mImsStateTracker).start(eq(SUB_1));
+ verify(mSelectorCallback1).onCreated(eq(mDomainSelectorBase1));
+ verifyNoMoreInteractions(mSelectorCallback1);
+ verify(mDomainSelectorBase1).selectDomain(eq(attr1), eq(mSelectorCallback1));
+
+ SelectionAttributes attr2 = new SelectionAttributes.Builder(
+ SLOT_0, SUB_2, TEST_SELECTOR_TYPE)
+ .setCallId(CALL_ID)
+ .setEmergency(true)
+ .build();
+ mServiceHandler.post(() -> {
+ mDomainSelectionService.onDomainSelection(attr2, mSelectorCallback2);
+ });
+ processAllMessages();
+
+ verify(mImsStateTracker).start(eq(SUB_2));
+ verify(mSelectorCallback2).onCreated(eq(mDomainSelectorBase2));
+ verifyNoMoreInteractions(mSelectorCallback2);
+ verify(mDomainSelectorBase2).selectDomain(eq(attr2), eq(mSelectorCallback2));
+ }
+
+ @Test
+ @SmallTest
+ public void testOnServiceStateUpdated() {
+ mDomainSelectionService.onServiceStateUpdated(SLOT_0, SUB_1, mServiceState);
+
+ verify(mImsStateTracker).updateServiceState(eq(mServiceState));
+ }
+
+ @Test
+ @SmallTest
+ public void testOnBarringInfoUpdated() {
+ mDomainSelectionService.onBarringInfoUpdated(SLOT_0, SUB_1, mBarringInfo);
+
+ verify(mImsStateTracker).updateBarringInfo(eq(mBarringInfo));
+ }
+
+ @Test
+ @SmallTest
+ public void testOnDestroy() {
+ SelectionAttributes attr1 = new SelectionAttributes.Builder(
+ SLOT_0, SUB_1, TEST_SELECTOR_TYPE)
+ .setCallId(CALL_ID)
+ .setEmergency(true)
+ .build();
+ mServiceHandler.post(() -> {
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
+ });
+ processAllMessages();
+
+ mDomainSelectionService.onDestroy();
+
+ verify(mImsStateTracker).destroy();
+ verify(mDomainSelectorBase1).destroy();
+ verify(mSubscriptionManager).removeOnSubscriptionsChangedListener(any());
+ }
+
+ @Test
+ @SmallTest
+ public void testHandleSubscriptionsChangedWithEmptySubscriptionInfo() {
+ when(mSubscriptionManager.getActiveSubscriptionInfoList())
+ .thenReturn(null, new ArrayList<SubscriptionInfo>());
+
+ mOnSubscriptionsChangedListener.onSubscriptionsChanged();
+ mOnSubscriptionsChangedListener.onSubscriptionsChanged();
+
+ verify(mImsStateTracker, never()).start(anyInt());
+ }
+
+ @Test
+ @SmallTest
+ public void testHandleSubscriptionsChangedWithActiveSubscriptionInfoAndInvalidSlotIndex() {
+ SubscriptionInfo subsInfo = Mockito.mock(SubscriptionInfo.class);
+ List<SubscriptionInfo> subsInfoList = new ArrayList<>();
+ subsInfoList.add(subsInfo);
+ when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subsInfoList);
+ when(subsInfo.getSimSlotIndex()).thenReturn(SubscriptionManager.INVALID_SIM_SLOT_INDEX);
+
+ mOnSubscriptionsChangedListener.onSubscriptionsChanged();
+
+ verify(mImsStateTracker, never()).start(anyInt());
+ }
+
+ @Test
+ @SmallTest
+ public void testHandleSubscriptionsChangedWithActiveSubscriptionInfo() {
+ SubscriptionInfo subsInfo = Mockito.mock(SubscriptionInfo.class);
+ List<SubscriptionInfo> subsInfoList = new ArrayList<>();
+ subsInfoList.add(subsInfo);
+ when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(subsInfoList);
+ when(subsInfo.getSubscriptionId())
+ .thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID, SUB_1);
+ when(subsInfo.getSimSlotIndex()).thenReturn(SLOT_0);
+
+ mOnSubscriptionsChangedListener.onSubscriptionsChanged();
+ mOnSubscriptionsChangedListener.onSubscriptionsChanged();
+
+ verify(mImsStateTracker).start(eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID));
+ verify(mImsStateTracker).start(eq(SUB_1));
+ }
+
+ private void processAllMessages() {
+ while (!mTestableLooper.getLooper().getQueue().isIdle()) {
+ mTestableLooper.processAllMessages();
+ }
+ }
+}
diff --git a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
index 2a30e1a..07c9fd0 100644
--- a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -171,12 +172,13 @@
verify(mFeatureManager).registerImsRegistrationCallback(captor.capture());
assertNotNull(captor.getValue());
- captor.getValue().onDeregistered(REASON_DISCONNECTED);
+ captor.getValue().onDeregistered(REASON_DISCONNECTED, 0, 0);
controller.getRegistrationState(result -> {
assertNotNull(result);
assertEquals(RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED, result.intValue());
});
- verify(mRegistrationCallback).handleImsUnregistered(REASON_DISCONNECTED);
+ verify(mRegistrationCallback).handleImsUnregistered(eq(REASON_DISCONNECTED),
+ anyInt(), anyInt());
ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder(
ImsRegistrationImplBase.REGISTRATION_TECH_LTE).build();
@@ -193,8 +195,7 @@
assertNotNull(result);
assertEquals(RegistrationManager.REGISTRATION_STATE_REGISTERED, result.intValue());
});
- verify(mRegistrationCallback).handleImsRegistered(
- AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ verify(mRegistrationCallback).handleImsRegistered(attr);
}
@Test
diff --git a/tests/src/com/android/services/telephony/rcs/SipSessionTrackerTest.java b/tests/src/com/android/services/telephony/rcs/SipSessionTrackerTest.java
index 37abb83..3874321 100644
--- a/tests/src/com/android/services/telephony/rcs/SipSessionTrackerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/SipSessionTrackerTest.java
@@ -22,26 +22,44 @@
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
+import android.content.Context;
import android.net.Uri;
+import android.os.RemoteException;
+import android.telephony.BinderCacheManager;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.SipDelegateManager;
+import android.telephony.ims.SipDialogState;
+import android.telephony.ims.SipDialogStateCallback;
import android.telephony.ims.SipMessage;
+import android.telephony.ims.aidl.IImsRcsController;
+import android.util.ArraySet;
import android.util.Base64;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.internal.telephony.ISipDialogStateCallback;
+import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.metrics.RcsStats;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.nio.ByteBuffer;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -103,14 +121,29 @@
private static final String TEST_INVITE_SIP_METHOD = "INVITE";
private static final int TEST_SIP_RESPONSE_CODE = 200;
private static final int TEST_SIP_CLOSE_RESPONSE_CODE = 0;
- @Mock
- private RcsStats mRcsStats;
+
+ @Mock private RcsStats mRcsStats;
+ private boolean mUpdatedState = false;
+ private SipDialogStateCallback mCallback;
+ private SipDelegateManager mSipManager;
+ private ISipDialogStateCallback mCbBinder;
+ IImsRcsController mMockImsRcsInterface;
+ BinderCacheManager<ITelephony> mBinderCache;
+ BinderCacheManager<IImsRcsController> mRcsBinderCache;
@Before
- public void setUp() {
+ public void setUp() throws Exception {
mStringEntryCounter = 0;
MockitoAnnotations.initMocks(this);
mTrackerUT = new SipSessionTracker(TEST_SUB_ID, mRcsStats);
+ mMockImsRcsInterface = mock(IImsRcsController.class);
+ mBinderCache = mock(BinderCacheManager.class);
+ mRcsBinderCache = mock(BinderCacheManager.class);
+ doReturn(mMockImsRcsInterface).when(mRcsBinderCache)
+ .listenOnBinder(any(), any(Runnable.class));
+ doReturn(mMockImsRcsInterface).when(mRcsBinderCache)
+ .removeRunnable(any(SipDialogStateCallback.class));
+ doReturn(mMockImsRcsInterface).when(mRcsBinderCache).getBinder();
}
@Test
@@ -425,6 +458,143 @@
verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr);
}
+ @Test
+ public void testActiveDialogsChanged() throws ImsException {
+ sipDialogStateCallback();
+
+ // first dialog
+ DialogAttributes attr1 = new DialogAttributes();
+ createConfirmedDialog(attr1);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr1);
+
+ verifyConfirmedStates(true);
+
+ // add a second dialog
+ DialogAttributes attr2 = new DialogAttributes();
+ createConfirmedDialog(attr2);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr1, attr2);
+ verifyConfirmedStates(true);
+
+ // Send BYE request on first dialog
+ SipMessage byeRequest = generateSipRequest(SipMessageUtils.BYE_SIP_METHOD, attr1);
+ filterMessage(byeRequest, attr1);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr2);
+ verifyContainsCallIds(mTrackerUT.getClosedDialogs(), attr1);
+ mTrackerUT.cleanupSession(attr1.callId);
+ verifyConfirmedStates(true);
+
+ // Send BYE request on second dialog
+ byeRequest = generateSipRequest(SipMessageUtils.BYE_SIP_METHOD, attr2);
+ filterMessage(byeRequest, attr2);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getClosedDialogs(), attr2);
+ mTrackerUT.cleanupSession(attr2.callId);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ assertTrue(mTrackerUT.getClosedDialogs().isEmpty());
+ verifyConfirmedStates(false);
+ unRegisterCallback();
+ }
+
+ @Test
+ public void testActiveSipDialogsChangedClearAll() throws ImsException {
+ sipDialogStateCallback();
+
+ // first dialog
+ DialogAttributes attr1 = new DialogAttributes();
+ createConfirmedDialog(attr1);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr1);
+ verifyConfirmedStates(true);
+
+ // add a second dialog
+ DialogAttributes attr2 = new DialogAttributes();
+ createConfirmedDialog(attr2);
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ verifyContainsCallIds(mTrackerUT.getConfirmedDialogs(), attr1, attr2);
+ verifyConfirmedStates(true);
+
+ // cleanAllSessions
+ mTrackerUT.clearAllSessions();
+ assertTrue(mTrackerUT.getEarlyDialogs().isEmpty());
+ assertTrue(mTrackerUT.getConfirmedDialogs().isEmpty());
+ assertTrue(mTrackerUT.getClosedDialogs().isEmpty());
+ verifyConfirmedStates(false);
+ unRegisterCallback();
+ }
+
+ private void sipDialogStateCallback() throws ImsException {
+ mCallback = new SipDialogStateCallback() {
+ @Override
+ public void onActiveSipDialogsChanged(List<SipDialogState> dialogs) {
+ mUpdatedState = isSipDialogActiveState(dialogs);
+ }
+
+ @Override
+ public void onError() { }
+ };
+ registerCallback();
+ }
+
+ private void verifyConfirmedStates(boolean currentState) {
+ List<SipDialogState> dialogStates = new ArrayList<>();
+ for (SipDialog d : (ArraySet<SipDialog>) mTrackerUT.getTrackedDialogs()) {
+ SipDialogState dialog = new SipDialogState.Builder(d.getState()).build();
+ dialogStates.add(dialog);
+ }
+ try {
+ mCbBinder.onActiveSipDialogsChanged(dialogStates);
+ } catch (RemoteException e) {
+ //onActiveSipDialogsChanged error
+ }
+ assertEquals(currentState, mUpdatedState);
+ }
+
+ private void registerCallback() throws ImsException {
+ // Capture the Runnable that was registered.
+ ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class);
+ // Capture the ISipDialogStateCallback that was registered.
+ ArgumentCaptor<ISipDialogStateCallback> callbackCaptor =
+ ArgumentCaptor.forClass(ISipDialogStateCallback.class);
+
+ Context context = PhoneFactory.getDefaultPhone().getContext();
+ mSipManager = new SipDelegateManager(context,
+ TEST_SUB_ID, mRcsBinderCache, mBinderCache);
+
+ mSipManager.registerSipDialogStateCallback(Runnable::run, mCallback);
+
+ verify(mRcsBinderCache).listenOnBinder(any(), runnableCaptor.capture());
+ try {
+ verify(mMockImsRcsInterface).registerSipDialogStateCallback(
+ eq(TEST_SUB_ID), callbackCaptor.capture());
+ } catch (RemoteException e) {
+ //registerSipDialogStateCallback error
+ }
+ mCbBinder = callbackCaptor.getValue();
+ }
+
+ private void unRegisterCallback() {
+ try {
+ mSipManager.unregisterSipDialogStateCallback(mCallback);
+ } catch (ImsException e) {
+ //unregisterSipDialogStateCallback error
+ }
+ }
+
+ private boolean isSipDialogActiveState(List<SipDialogState> dialogs) {
+ int confirmedSize = dialogs.stream().filter(
+ d -> d.getState() == SipDialogState.STATE_CONFIRMED)
+ .collect(Collectors.toSet()).size();
+ if (confirmedSize > 0) {
+ return true;
+ }
+ return false;
+ }
+
private void filterMessage(SipMessage m, DialogAttributes attr) {
mTrackerUT.filterSipMessage(
SIP_TRANSPORT_SESSION__SIP_MESSAGE_DIRECTION__OUTGOING, m);
diff --git a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
index 39469b6..d575d77 100644
--- a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
+++ b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
@@ -25,17 +25,20 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.app.PropertyInvalidatedCache;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import androidx.test.runner.AndroidJUnit4;
import com.android.TelephonyTestBase;
import com.android.ims.FeatureConnector;
import com.android.ims.RcsFeatureManager;
+import com.android.internal.telephony.ISub;
import org.junit.After;
import org.junit.Before;
@@ -59,12 +62,26 @@
@Mock RcsFeatureController.FeatureConnectorFactory<RcsFeatureManager> mFeatureConnectorFactory;
@Mock FeatureConnector<RcsFeatureManager> mFeatureConnector;
+ @Mock
+ private ISub mISub;
+
+ @Mock
+ private TelephonyManager mTelephonyManager;
+
private RcsFeatureController mFeatureControllerSlot0;
private RcsFeatureController mFeatureControllerSlot1;
@Before
public void setUp() throws Exception {
super.setUp();
+ TelephonyManager.setupISubForTest(mISub);
+ TelephonyManager.enableServiceHandleCaching();
+ PropertyInvalidatedCache.disableForTestMode();
+
+ //set up default slot-> sub ID mappings.
+ setSlotToSubIdMapping(0 /*slotId*/, 1/*subId*/);
+ setSlotToSubIdMapping(1 /*slotId*/, 2/*subId*/);
+
doReturn(mFeatureConnector).when(mFeatureConnectorFactory).create(any(), anyInt(),
any(), any(), any());
mFeatureControllerSlot0 = createFeatureController(0 /*slotId*/, 1 /*subId*/);
@@ -82,9 +99,9 @@
doReturn(mMockSipTransportSlot1).when(mFeatureFactory).createSipTransportController(any(),
eq(1), anyInt());
doReturn(true).when(mResourceProxy).getDeviceUceEnabled(any());
- //set up default slot-> sub ID mappings.
- setSlotToSubIdMapping(0 /*slotId*/, 1/*subId*/);
- setSlotToSubIdMapping(1 /*slotId*/, 2/*subId*/);
+
+ replaceInstance(TelephonyManager.class, "sInstance", null, mTelephonyManager);
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
}
@After
@@ -341,11 +358,8 @@
bundle.putBoolean(key, value);
}
- private void setSlotToSubIdMapping(int slotId, int loadedSubId) {
- SubscriptionManager m = mContext.getSystemService(SubscriptionManager.class);
- int [] subIds = new int[1];
- subIds[0] = loadedSubId;
- doReturn(subIds).when(m).getSubscriptionIds(eq(slotId));
+ private void setSlotToSubIdMapping(int slotId, int loadedSubId) throws Exception {
+ doReturn(loadedSubId).when(mISub).getSubId(slotId);
}
private TelephonyRcsService createRcsService(int numSlots) {