Merge "Do not call close on onCreateIncomingConnectionFailed" into main am: b414473b2e am: 962c74e6f2
Original change: https://android-review.googlesource.com/c/platform/packages/services/Telephony/+/3027945
Change-Id: I07dede991fa20e0d40e45c533ee5b6fa2d0b0cc1
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 48222f1..3bbafc0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -49,6 +49,7 @@
"android.permission.flags-aconfig-java",
"satellite-s2storage-ro",
"s2-geometry-library-java",
+ "dropbox_flags_lib",
],
srcs: [
@@ -97,18 +98,6 @@
],
}
-// Used by satellite unit tests temporarily during the development phase.
-// TODO: Remove this once the satellite code is wired into Telephony code.
-java_library {
- name: "telephony-satellite",
- srcs: ["src/com/android/phone/satellite/**/*.java"],
- libs: [
- "satellite-s2storage-ro",
- "s2-geometry-library-java",
- "telephony-common",
- ],
-}
-
platform_compat_config {
name: "TeleService-platform-compat-config",
src: ":TeleService",
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 7e56e8b..1190d38 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -71,6 +71,7 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+ <uses-permission android:name="android.permission.LOCATION_BYPASS" />
<uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
<uses-permission android:name="android.permission.BROADCAST_SMS"/>
<uses-permission android:name="android.permission.BROADCAST_WAP_PUSH"/>
@@ -137,6 +138,7 @@
<uses-permission android:name="android.permission.BIND_TELEPHONY_DATA_SERVICE" />
<uses-permission android:name="android.permission.BIND_SATELLITE_GATEWAY_SERVICE" />
<uses-permission android:name="android.permission.BIND_SATELLITE_SERVICE" />
+ <uses-permission android:name="android.permission.SATELLITE_COMMUNICATION" />
<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" />
@@ -167,9 +169,17 @@
<!-- Needed to register for UWB state changes for satellite communication -->
<uses-permission android:name="android.permission.UWB_PRIVILEGED"/>
- <permission android:name="com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID"
- android:label="Access last known cell identity."
- android:protectionLevel="signature"/>
+ <!-- Needed to initiate configuration update -->
+ <uses-permission android:name="android.permission.UPDATE_CONFIG"/>
+
+ <!-- Needed to bind the domain selection service. -->
+ <uses-permission android:name="android.permission.BIND_DOMAIN_SELECTION_SERVICE" />
+
+ <!-- Needed to send safety center updates for cellular transparency features -->
+ <uses-permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE"/>
+
+ <!-- Needed because the DISPLAY_EMERGENCY_MESSAGE ConnectionEvent contains a PendingIntent to activate the satellite feature. -->
+ <uses-permission android:name="com.google.android.apps.stargate.permission.SEND_EMERGENCY_INTENTS"/>
<application android:name="PhoneApp"
android:persistent="true"
@@ -570,10 +580,29 @@
</intent-filter>
</receiver>
+ <!-- Update configuration data file -->
+ <receiver android:name="com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver"
+ android:exported="true"
+ android:permission="android.permission.UPDATE_CONFIG">
+ <intent-filter>
+ <action android:name="android.os.action.UPDATE_CONFIG" />
+ <data android:scheme="content" android:host="*" android:mimeType="*/*" />
+ </intent-filter>
+ </receiver>
+
<receiver
android:name="com.android.internal.telephony.uicc.ShowInstallAppNotificationReceiver"
android:exported="false"/>
+ <receiver
+ android:name=".security.SafetySourceReceiver"
+ android:exported="false"
+ androidprv:systemUserOnly="true">
+ <intent-filter>
+ <action android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES"/>
+ </intent-filter>
+ </receiver>
+
<activity
android:name="com.android.phone.settings.PickSmsSubscriptionActivity"
android:exported="false"
@@ -626,5 +655,13 @@
android:multiprocess="false"
android:singleUser="true"
android:writePermission="android.permission.MODIFY_PHONE_STATE"/>
+
+ <service android:name="com.android.services.telephony.domainselection.TelephonyDomainSelectionService"
+ android:exported="true"
+ android:permission="android.permission.BIND_DOMAIN_SELECTION_SERVICE">
+ <intent-filter>
+ <action android:name="android.telephony.DomainSelectionService"/>
+ </intent-filter>
+ </service>
</application>
</manifest>
diff --git a/assets/CarrierRestrictionOperatorDetails.json b/assets/CarrierRestrictionOperatorDetails.json
index f3da100..68d066e 100644
--- a/assets/CarrierRestrictionOperatorDetails.json
+++ b/assets/CarrierRestrictionOperatorDetails.json
@@ -1,5 +1,10 @@
{
- "_comment": "Operator should register with its application package name, carrierId and all the corresponding SHAIDs",
- "_comment": "Example format :: << \"packageName\" : {\"carrierId\":<int>, \"callerSHA1Id\":[<SHAID1>, <SHAID2>]} >>",
- "com.vzw.hss.myverizon":{"carrierId":1839,"callerSHA1Id":["C58EE7871896786F8BF70EBDB137DE10074043E9","AE23A03436DF07B0CD70FE881CDA2EC1D21215D7B7B0CC68E67B67F5DF89526A"]}
+ "_comment": "Operator should register with its application package name, carrierId and all the corresponding SHA256IDs",
+ "_comment": "Example format :: << \"packageName\" : {\"carrierId\":[<int>], \"callerSHA256Ids\":[<SHAID1>, <SHAID2>]} >>",
+ "com.vzw.hss.myverizon":{"carrierIds":[1839],"callerSHA256Ids":["AE23A03436DF07B0CD70FE881CDA2EC1D21215D7B7B0CC68E67B67F5DF89526A"]},
+ "com.google.android.apps.tycho":{"carrierIds":[1989],"callerSHA256Ids":["B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51465350","4C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859"]},
+ "com.comcast.mobile.mxs":{"carrierIds": [2032, 2532, 2556],"callerSHA256Ids":["914C26403B57D2D482359FC235CC825AD00D52B0121C18EF2B2B9D4DDA4B8996"]},
+ "com.xfinity.digitalhome": {"carrierIds": [2032],"callerSHA256Ids":["31b4c17315c2269040d535f7b6a79cf4d11517c664d9de8f1ddf4f8a785aad47"]},
+ "com.xfinity.digitalhome.debug":{"carrierIds": [2032],"callerSHA256Ids":["c9133e8168f97573c8c567f46777dff74ade0c015ecf2c5e91be3e4e76ddcae2"]},
+ "com.xfinity.dh.xm.app": {"carrierIds": [2032],"callerSHA256Ids":["c9133e8168f97573c8c567f46777dff74ade0c015ecf2c5e91be3e4e76ddcae2"]}
}
\ No newline at end of file
diff --git a/assets/google_us_san_sat_s2.dat b/assets/google_us_san_sat_s2.dat
new file mode 100644
index 0000000..60b00df
--- /dev/null
+++ b/assets/google_us_san_sat_s2.dat
Binary files differ
diff --git a/ecc/input/eccdata.txt b/ecc/input/eccdata.txt
index fe11383..c4edc9e 100644
--- a/ecc/input/eccdata.txt
+++ b/ecc/input/eccdata.txt
@@ -2359,77 +2359,6 @@
types: POLICE
types: AMBULANCE
types: FIRE
- routing: EMERGENCY
- }
- eccs {
- phone_number: "984"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
- }
- eccs {
- phone_number: "985"
- types: MOUNTAIN_RESCUE
- routing: EMERGENCY
- }
- eccs {
- phone_number: "986"
- types: POLICE
- routing: EMERGENCY
- }
- eccs {
- phone_number: "997"
- types: POLICE
- routing: EMERGENCY
- }
- eccs {
- phone_number: "998"
- types: FIRE
- routing: EMERGENCY
- }
- eccs {
- phone_number: "999"
- types: AMBULANCE
- routing: EMERGENCY
- }
- eccs {
- phone_number: "991"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
- }
- eccs {
- phone_number: "992"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
- }
- eccs {
- phone_number: "993"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
- }
- eccs {
- phone_number: "994"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
- }
- eccs {
- phone_number: "995"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
- }
- eccs {
- phone_number: "996"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
- }
- eccs {
- phone_number: "987"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
- }
- eccs {
- phone_number: "989"
- types: TYPE_UNSPECIFIED
- routing: EMERGENCY
}
ecc_fallback: "112"
}
diff --git a/ecc/output/eccdata b/ecc/output/eccdata
index 55d8151..482ed79 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 ffe63de..2665ea0 100644
--- a/res/layout/radio_info.xml
+++ b/res/layout/radio_info.xml
@@ -185,6 +185,12 @@
<TextView android:id="@+id/network_slicing_config" style="@style/info_value" />
</LinearLayout>
+ <!-- eUICC info -->
+ <LinearLayout style="@style/RadioInfo_entry_layout" android:orientation="horizontal">
+ <TextView android:id="@+id/euicc_info_label" android:text="@string/radio_info_euicc_info" style="@style/info_label" />
+ <TextView android:id="@+id/euicc_info" style="@style/info_value" />
+ </LinearLayout>
+
<!-- Horizontal Rule -->
<View
android:layout_width="fill_parent"
@@ -226,6 +232,14 @@
android:layout_height="wrap_content"
android:text="@string/simulate_out_of_service_string"/>
+ <!-- Simulate this SIM to be satellite -->
+ <Switch android:id="@+id/mock_carrier_roaming_satellite"
+ android:textSize="14sp"
+ android:layout_marginTop="8dip"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/mock_carrier_roaming_satellite_string"/>
+
<!-- VoLTE provisioned -->
<Switch android:id="@+id/volte_provisioned_switch"
android:textSize="14sp"
diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml
index dab1dfb..0dd1a73 100644
--- a/res/values-af/strings.xml
+++ b/res/values-af/strings.xml
@@ -486,7 +486,7 @@
<string name="simContacts_airplaneMode" msgid="4654884030631503808">"Skakel vliegtuigmodus af om kontakte van die SIM-kaart af in te voer."</string>
<string name="enable_pin" msgid="967674051730845376">"Aktiveer/deaktiveer SIM-PIN"</string>
<string name="change_pin" msgid="3657869530942905790">"Verander SIM-PIN"</string>
- <string name="enter_pin_text" msgid="3182311451978663356">"SIM PIN:"</string>
+ <string name="enter_pin_text" msgid="3182311451978663356">"SIM-PIN:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"Ou PIN"</string>
<string name="newPinLabel" msgid="3585899083055354732">"Nuwe PIN"</string>
<string name="confirmPinLabel" msgid="7783531218662473778">"Bevestig nuwe PIN"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Verlaat noodterugbelmodus om \'n nienoodoproep te maak."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Nie geregistreer op netwerk nie."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobiele netwerk nie beskikbaar nie."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Selnetwerk is nie beskikbaar nie.\n\nVerbind met ’n draadlose netwerk om ’n oproep te maak.\n\n2G is gedeaktiveer op hierdie toestel, wat dalk jou konnektiwiteit kan beïnvloed. Gaan na Instellings en aktiveer Laat 2G toe om voort te gaan."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobiele netwerk is nie beskikbaar nie. Koppel aan \'n draadlose netwerk om \'n oproep te maak."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Selnetwerk is nie beskikbaar nie.\n\nVerbind met ’n draadlose netwerk om ’n oproep te maak.\n\n2G is gedeaktiveer op hierdie toestel, wat jou konnektiwiteit kan beïnvloed. Gaan na Instellings en aktiveer Laat 2G toe om voort te gaan."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Voer \'n geldige nommer in om \'n oproep te maak."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Oproep het misluk."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Oproep kan nie op die oomblik bygevoeg word nie. Jy kan probeer in verbinding tree deur \'n boodskap te stuur."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Kan nie oproepe aanhou nie."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Koppel aan \'n draadlose netwerk om \'n oproep te maak."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Aktiveer Wi-Fi-oproepe om \'n oproep te maak."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Deaktiveer satellietmodus om ’n oproep te maak."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Om ’n oproep te maak, moet jy eers die satellietverbinding beëindig."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Jy kan boodskappe stuur en ontvang sonder ’n selfoon- of wi-fi-netwerk."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Noodinligting"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Eienaar"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tik weer om inligting te bekyk"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml
index 95437d5..f2090a6 100644
--- a/res/values-am/strings.xml
+++ b/res/values-am/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"አስቸኳይ ያልሆነ ጥሪ ለማድረግ ከአስቸኳይ መልሰህ ደውል ሁነታ ይውጡ።"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"በአውታረ መረቡ ላይ አልተመዘገበም።"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"የተንቀሳቃሽ አደራጅ የለም።"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"የተንቀሳቃሽ ስልክ አውታረ መረብ አይገኝም።\n\nጥሪ ለማድረግ ከሽቦ አልባ አውታር ጋር ያገናኙ።\n\n2G በዚህ መሣሪያ ላይ ተሰናክሏል፣ ይህም ግንኙነትዎ ላይ ተጽዕኖ እያሳደረ ይሆናል። ወደ ቅንብሮች ይሂዱ እና ለመቀጠል 2G ፍቀድ የሚለውን ያንቁ።"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"የተንቀሳቃሽ ስልክ አውታረ መረብ አይገኝም። ጥሪ ለማድረግ ከሽቦ አልባ አውታረ መረብ ጋር ያገናኙ።"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"የተንቀሳቃሽ ስልክ አውታረ መረብ አይገኝም።\n\nጥሪ ለማድረግ ከሽቦ አልባ አውታር ጋር ያገናኙ።\n\n2G እዚህ መሣሪያ ላይ ተሰናክሏል፣ ይህም ግንኙነትዎ ላይ ተጽዕኖ እያደረገ ይሆናል። ወደ ቅንብሮች ይሂዱ እና ለመቀጠል 2G ፍቀድ የሚለውን ያንቁ።"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"አንድ ጥሪ ለማድረግ የሚሰራ ቁጥር ያስገቡ።"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"ጥሪ አልተሳካም።"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ጥሪ አሁን መታከል አይችልም። መልዕክት በመላክ ለማግኘት መሞከር ይችላሉ።"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"ጥሪዎችን መያዝ አልተቻለም።"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ጥሪ ለማድረግ ወደ ሽቦ አልባ አውታረ መረብ ያገናኙ።"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"ጥሪ ለማድረግ Wi-Fi ጥሪን ያንቁ።"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"ጥሪ ለማድረግ የመንኩራኩር ሁነታን ያሰናክሉ።"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ጥሪ ለማድረግ፣ በመጀመሪያ የሳተላይት ግንኙነቱን ያብቁ።"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"ያለ ሞባይል ወይም የWi-Fi አውታረ መረብ መልዕክቶችን መላክ እና መቀበል ይችላሉ።"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"የአደጋ ጊዜ መረጃ"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"ባለቤት"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"መረጃ ለማየት እንደገና መታ ያድርጉ"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"የሲም አድራሻ ደብተር አሳይ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"በቋሚነት የሚደወልባቸው ቁጥሮች"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"የአገልግሎት መደወያ ቁጥሮችን ተመልከት"</string>
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
index 54eeb24..3d4a8ed 100644
--- a/res/values-ar/strings.xml
+++ b/res/values-ar/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"ينبغي الخروج من وضع معاودة الاتصال بالطوارئ لإجراء مكالمة غير طارئة."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"غير مسجل على الشبكة."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"شبكة الجوال غير متاحة."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"شبكة الجوّال غير متوفّرة.\n\nيُرجى الاتصال بشبكة لاسلكية لإجراء مكالمة.\n\nتم إيقاف شبكة الجيل الثاني على هذا الجهاز، ما قد يؤثر في إمكانية الاتصال بالإنترنت. انتقِل إلى \"الإعدادات\" وفعِّل خيار \"السماح بشبكة الجيل الثاني\" للمتابعة."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"شبكة الجوّال ليست متوفرة. اتصل بشبكة لاسلكية لإجراء مكالمة."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"شبكة الجوّال غير متوفّرة.\n\nيُرجى الاتصال بشبكة لاسلكية لإجراء مكالمة.\n\nتم إيقاف شبكة الجيل الثاني على هذا الجهاز، ما قد يؤثر في إمكانية الاتصال بالإنترنت. انتقِل إلى \"الإعدادات\" وفعِّل خيار \"السماح بشبكة الجيل الثاني\" للمتابعة."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"لإجراء مكالمة، أدخل رقمًا صالحًا."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"تعذّرت المكالمة."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"يتعذر إجراء المكالمة في الوقت الحالي. يمكنك محاولة التواصل من خلال إرسال رسالة."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"يتعذر وضع المكالمات قيد الانتظار."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"اتصل بشبكة لاسلكية لإجراء مكالمة."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"يمكنك تفعيل اتصال Wi-Fi لإجراء مكالمة."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"يجب إيقاف وضع القمر الصناعي لإجراء مكالمة."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"لإجراء مكالمة، عليك أولاً إنهاء اتصال القمر الصناعي."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"يمكنك إرسال الرسائل واستلامها بدون شبكة الجوّال أو شبكة Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"معلومات الطوارئ"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"المالك"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"انقر مجددًا لعرض المعلومات."</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
@@ -929,6 +934,6 @@
<string name="send_from_work_profile_title" msgid="7044759579507604732">"لا يمكن إرسال رسائل من تطبيق شخصي"</string>
<string name="send_from_work_profile_description" msgid="2174402508727161974">"تسمح لك مؤسستك بإرسال الرسائل من تطبيقات العمل فقط."</string>
<string name="send_from_work_profile_cancel" msgid="177746511030381711">"إلغاء"</string>
- <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"التبديل إلى الملف الشخصي للعمل"</string>
+ <string name="send_from_work_profile_action_str" msgid="6892775562934243337">"التبديل إلى ملف العمل"</string>
<string name="install_messages_on_work_profile_action_str" msgid="3773440996395152903">"تثبيت تطبيق لرسائل العمل"</string>
</resources>
diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml
index b68f32b..10baaac 100644
--- a/res/values-as/strings.xml
+++ b/res/values-as/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"সাধাৰণ কল কৰিবৰ কাৰণে জৰুৰীকালীন কলবেক ম\'ডৰ পৰা বাহিৰ হওক।"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"নেটৱৰ্কত পঞ্জীকৃত নহয়।"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"ম’বাইল নেটৱৰ্ক উপলব্ধ নহয়।"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"ম’বাইল নেটৱৰ্ক উপলব্ধ নহয়।\n\nকল কৰিবলৈ এটা ৱায়াৰলেছ নেটৱৰ্কৰ সৈতে সংযোগ কৰক।\n\nএই ডিভাইচটোত 2G অক্ষম কৰা হৈছে, যিটোৱে আপোনাৰ সংযোগত প্ৰভাৱ পেলাব পাৰে। অব্যাহত ৰাখিবলৈ ছেটিঙলৈ গৈ 2Gক অনুমতি দিয়ক সক্ষম কৰক।"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"ম’বাইল নেটৱৰ্ক উপলব্ধ নহয়। কল কৰিবৰ কাৰণে কোনো বেতাঁৰ নেটৱৰ্কৰ সৈতে সংযোগ কৰক।"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"ম’বাইল নেটৱৰ্ক উপলব্ধ নহয়।\n\nকল কৰিবলৈ এটা বেতাঁৰ নেটৱৰ্কৰ সৈতে সংযোগ কৰক।\n\nএই ডিভাইচটোত 2G অক্ষম কৰা হৈছে, যিটোৱে আপোনাৰ সংযোগত প্ৰভাৱ পেলাব পাৰে। অব্যাহত ৰাখিবলৈ ছেটিঙলৈ গৈ 2Gক অনুমতি দিয়ক সক্ষম কৰক।"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"কল কৰিবৰ কাৰণে এটা মান্য নম্বৰ দিয়ক।"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"কল বিফল হৈছে"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"এই মুহূৰ্তত কল যোগ কৰিব নোৱাৰি। আপুনি এটা বাৰ্তা পঠাই যোগাযোগ কৰিবলৈ চেষ্টা কৰি চাব পাৰে।"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"কলসমূহ হ\'ল্ডত ৰাখিব নোৱাৰি।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"কল কৰিবলৈ কোনো বেতাঁৰ নেটৱৰ্কৰ সৈতে সংযোগ কৰক।"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"কল কৰিবৰ কাৰণে ৱাই-ফাই কলিং সুবিধা সক্ষম কৰক।"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"কল কৰিবলৈ উপগ্ৰহ ম’ডটো অক্ষম কৰক।"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"কল কৰিবলৈ, প্ৰথমে উপগ্ৰহৰ সংযোগ বন্ধ কৰক।"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"আপুনি কোনো ম’বাইল বা ৱাই-ফাই নেটৱৰ্ক নোহোৱাকৈ বাৰ্তা পঠিয়াব আৰু লাভ কৰিব পাৰে।"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"জৰুৰীকালীন তথ্য"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"গৰাকী"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"তথ্য চাবলৈ পুনৰ টিপক"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ছিম ঠিকনা সূচী চাওক"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ফিক্সড্ ডায়েলিং নম্বৰসমূহ চাওক"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"সেৱা ডায়েলিং নম্বৰসমূহ চাওক"</string>
diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml
index 38a8f9f..e2b7ee9 100644
--- a/res/values-az/strings.xml
+++ b/res/values-az/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Qeyri-fövqəladə zəng etmək üçün fövqəladə zəng rejimindən çıxın."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Şəbəkədə qeydə alınmayıb."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobil şəbəkə əlçatımlı deyil."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobil şəbəkə əlçatan deyil.\n\nZəng etmək üçün simsiz şəbəkəyə qoşulun.\n\nBu cihazda 2G deaktiv edilib, bu da bağlantınıza təsir edə bilər. Davam etmək üçün Ayarlara keçib \"2G-yə icazə verin\" seçimini aktiv edin."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobil şəbəkə əlçatmazdır. Zəng etmək üçün Wi-Fi şəbəkəsinə qoşulun."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobil şəbəkə əlçatan deyil.\n\nZəng etmək üçün simsiz şəbəkəyə qoşulun.\n\nBu cihazda 2G deaktiv edilib, bu da bağlantınıza təsir edə bilər. Davam etmək üçün Ayarlara keçib \"2G-yə icazə verin\" seçimini aktiv edin."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Zəngi yerləşdirmək üçün düzgün nömrə daxil edin."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Zəng alınmadı."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Hazırda zəngi əlavə etmək mümkün deyil. Mesaj göndərərək təkrar əlaqə saxlaya bilərsiniz."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Zənglər saxlanıla bilməz."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Zəng etmək üçün Wi-Fi şəbəkəsinə qoşulun."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Zəng etmək üçün Wi-Fi zəngini dəyişdirin."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Zəng etmək üçün peyk rejimini deaktiv edin."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Zəng etmək üçün əvvəlcə peyk bağlantısını sonlandırın."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Mobil və ya Wi-Fi şəbəkəsi olmadan mesaj göndərə və ala bilərsiniz."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Təcili məlumat"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Sahib"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Məlumata baxmaq üçün yenidən klikləyin"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml
index 69a0f7b..19a49ff 100644
--- a/res/values-b+sr+Latn/strings.xml
+++ b/res/values-b+sr+Latn/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Izađite iz režima hitnog povratnog poziva da biste uputili poziv koji nije hitan."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Nije registrovano na mreži."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilna mreža nije dostupna."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilna mreža nije dostupna.\n\nPovežite se na bežičnu mrežu da biste uputili poziv.\n\n2G je onemogućen na ovom uređaju, što može da utiče na povezivanje. Idite u Podešavanja i omogućite opciju Dozvoli 2G da biste nastavili."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilna mreža nije dostupna. Povežite se na bežičnu da biste uputili poziv."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilna mreža nije dostupna.\n\nPovežite se na bežičnu mrežu da biste uputili poziv.\n\n2G je onemogućen na ovom uređaju, što može da utiče na povezivanje. Idite u Podešavanja i omogućite opciju Dozvoli 2G da biste nastavili."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Da biste uputili poziv, unesite važeći broj."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Poziv nije uspeo."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Dodavanje poziva trenutno nije moguće. Možete da pokušate da ostvarite kontakt pomoću poruke."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Nije moguće stavljati pozive na čekanje."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Povežite se na bežičnu mrežu da biste uputili poziv."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Omogućite pozivanje preko WiFi-a da biste uputili poziv."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Onemogućite satelitski režim da biste uputili poziv."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Da biste uputili poziv, prvo završite satelitsku vezu."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Možete da šaljete i primate poruke bez mobilne ili WiFi mreže."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informacije za hitne slučajeve"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Vlasnik"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Dodirnite ponovo da biste videli informacije"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml
index 0f7f46a..e7c6139 100644
--- a/res/values-be/strings.xml
+++ b/res/values-be/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Каб зрабіць звычайны выклік, выйдзіце з рэжыму экстранных зваротных выклікаў."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Не зарэгістраваны ў сетцы."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Мабільная сетка недаступная."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Мабільная сетка недаступная.\n\nКаб зрабіць выклік, падключыцеся да бесправадной сеткі.\n\nНа гэтай прыладзе адключана перадача даных у рэжыме 2G, што можа ўплываць на магчымасць падключэння. Каб працягнуць, перайдзіце ў налады і ўключыце параметр \"Дазволіць 2G\"."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Мабільная сетка недаступная. Падлучыцеся да бесправадной сеткі, каб зрабіць выклік."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Мабільная сетка недаступная.\n\nКаб зрабіць выклік, падключыцеся да бесправадной сеткі.\n\nНа гэтай прыладзе адключана перадача даных у рэжыме 2G, што можа ўплываць на магчымасць падключэння. Каб працягнуць, перайдзіце ў налады і ўключыце параметр \"Дазволіць 2G\"."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Каб зрабіць выклік, увядзіце сапраўдны нумар."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Збой выклiку."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Немагчыма зараз дадаць выклік. Можна выйсці на сувязь, адправіўшы паведамленне."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Немагчыма ўтрымліваць выклікі."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Падлучыцеся да бесправадной сеткі, каб зрабіць выклік."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Дазволіць выклік па Wi-Fi-тэлефаніі."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Адключыце рэжым спадарожніка, каб зрабіць выклік."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Каб зрабіць выклік, завяршыце спадарожнікавае падключэнне."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Вы можаце адпраўляць і атрымліваць паведамленні без доступу да мабільнай сеткі або Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Даныя для экстранных сітуацый"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Уладальнік"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Каб паглядзець інфармацыю, націсніце яшчэ раз"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml
index 97f086f..7157353 100644
--- a/res/values-bg/strings.xml
+++ b/res/values-bg/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Излезте от режима на обратно обаждане при спешност, за да можете да извършвате обаждания, които не са спешни."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Няма регистрация в мрежата."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Няма мобилна мрежа."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Не е налице мобилна мрежа.\n\nСвържете се с безжична мрежа, за да извършите обаждане.\n\nУслугата 2G е деактивирана на това устройство, което може да влияе на свързаността ви. За да продължите, отворете настройките и активирайте „Разрешаване на 2G“."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Няма мобилна мрежа. Свържете се с безжична, за да се обадите."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Не е налице мобилна мрежа.\n\nСвържете се с безжична мрежа, за да извършите обаждане.\n\nУслугата 2G е деактивирана на това устройство, което може да влияе на свързаността ви. За да продължите, отворете настройките и активирайте „Разрешаване на 2G“."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"За да извършите обаждане, въведете валиден номер."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Обаждането не бе успешно."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Обаждането не може да бъде добавено сега. Може да се опитате да се свържете чрез изпращане на съобщение."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Не може да се извършват обаждания."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Свържете се с безжична мрежа, за да осъществите обаждане."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"За да извършите обаждане, активирайте обажданията през Wi-Fi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Деактивирайте сателитния режим, за да извършите обаждане."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"За да извършите обаждане, първо прекратете сателитната връзка."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Можете да изпращате и получавате съобщения без мобилна или Wi-Fi мрежа."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Информация за спешни случаи"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Собственик"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Докоснете отново, за да видите информация"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml
index f1fefbc..0a91958 100644
--- a/res/values-bn/strings.xml
+++ b/res/values-bn/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"একটি সাধারণ কল করতে জরুরি কলব্যাক মোডের বাইরে আসুন৷"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"নেটওয়ার্কে নিবন্ধিত নয়৷"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"মোবাইল নেটওয়ার্ক উপলব্ধ নয়৷"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"মোবাইল নেটওয়ার্ক উপলভ্য নেই।\n\nকল করতে হলে ওয়্যারলেস নেটওয়ার্কের সাথে কানেক্ট করুন।\n\nএই ডিভাইসে 2G পরিষেবা বন্ধ করে দেওয়া হয়েছে, যার ফলে হয়ত আপনার কানেক্টিভিটি প্রভাবিত হচ্ছে। সেটিংসে যান এবং চালিয়ে যেতে \'2G পরিষেবার অনুমতি দিন\' বিকল্পটি চালু করুন।"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"মোবাইল নেটওয়ার্ক উপলব্ধ নেই৷ একটি কল করতে কোনো ওয়্যারলেস নেটওয়ার্কে সংযোগ করুন৷"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"মোবাইল নেটওয়ার্ক উপলভ্য নেই।\n\nকল করতে হলে ওয়্যারলেস নেটওয়ার্কের সাথে কানেক্ট করুন।\n\nএই ডিভাইসে 2G পরিষেবা বন্ধ করে দেওয়া হয়েছে, যার ফলে হয়ত আপনার কানেক্টিভিটি প্রভাবিত হচ্ছে। সেটিংসে যান এবং চালিয়ে যেতে \'2G পরিষেবার অনুমতি দিন\' বিকল্পটি চালু করুন।"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"কোনো কল স্থাপন করতে, একটি বৈধ নম্বর লিখুন৷"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"কল ব্যর্থ হয়েছে৷"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"এই সময়ে কলটি যোগ করা যাবে না। আপনি একটি মেসেজ পাঠিয়ে যোগাযোগ করার চেষ্টা করতে পারেন।"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"কলগুলি ধরে রাখা যাবে না।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"একটি কল করতে কোনো ওয়্যারলেস নেটওয়ার্কে সংযোগ করুন৷"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"কোনো কল করতে Wi-Fi কলিং সক্ষম করুন৷"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"কল করার জন্য \'উপগ্রহ\' মোড বন্ধ করুন।"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"কল করতে, প্রথমে স্যাটেলাইট কানেকশন বন্ধ করুন।"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"আপনি কোনও মেবাইল বা ওয়াই-ফাই নেটওয়ার্ক ছাড়াই মেসেজ পাঠাতে ও পেতে পারবেন।"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"জরুরি তথ্য"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"মালিক"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"তথ্য দেখার জন্য আবার ট্যাপ করুন"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"সিম অ্যাড্রেস বুক দেখুন"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"স্থায়ী ডায়াল নম্বরগুলি দেখুন"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"সার্ভিস ডায়াল নম্বরগুলি দেখুন"</string>
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 992f1b2..af0813a 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Izađite iz načina rada za hitni povratni poziv da uputite poziv koji nije hitan."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Nije registrirano na mreži."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilna mreža nije dostupna."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilna mreža nije dostupna.\n\nPovežite se s bežičnom mrežom da uputite poziv.\n\n2G je onemogućen na uređaju, što može uticati na povezivost. Da nastavite, idite u Postavke i omogućite Dozvoli 2G."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilna mreža nije dostupna. Povežite se na bežičnu mrežu da pozovete."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilna mreža nije dostupna.\n\nPovežite se s bežičnom mrežom da uputite poziv.\n\n2G je onemogućen na uređaju, što može uticati na povezivost. Da nastavite, idite u Postavke i omogućite Dozvoli 2G."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Da uputite poziv, upišite važeći broj."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Poziv nije uspio."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Trenutno nije moguće dodati poziv. Možete pokušati poslati poruku."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Nije moguće staviti pozive na čekanje."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Povežite se na bežičnu mrežu da pozovete."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Omogućite pozivanje putem WiFi-ja da pozovete."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Onemogućite način rada putem satelita da uputite poziv."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Da uputite poziv, prvo završite satelitsku vezu."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Možete slati i primati poruke bez mobilne ili WiFi mreže."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informacije za hitne slučajeve"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Vlasnik"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Dodirnite ponovo da pogledate informacije"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml
index 6557918..8a2a589 100644
--- a/res/values-ca/strings.xml
+++ b/res/values-ca/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Surt del mode de devolució de trucada d\'emergència per fer un altre tipus de trucada."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"No registrat a la xarxa."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"La xarxa mòbil no està disponible."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"La xarxa mòbil no està disponible.\n\nConnecta\'t a una xarxa sense fil per fer una trucada.\n\nEl 2G està desactivat en aquest dispositiu, cosa que pot afectar la connectivitat. Ves a Configuració i activa Permet 2G per continuar."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"La xarxa mòbil no està disponible. Per fer una trucada, connecta\'t a una xarxa sense fil."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"La xarxa mòbil no està disponible.\n\nConnecta\'t a una xarxa sense fil per fer una trucada.\n\nEl 2G està desactivat en aquest dispositiu, cosa que pot afectar la connectivitat. Ves a Configuració i activa Permet 2G per continuar."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Per realitzar una trucada, introdueix un número vàlid."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"No s\'ha pogut fer la trucada."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"En aquest moment no es pot afegir la trucada. Prova d\'enviar un missatge."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"No es poden posar les trucades en espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Per fer una trucada, connecta amb una xarxa sense fil."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Activa les trucades per Wi-Fi per fer una trucada."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Per fer una trucada, desactiva el mode de satèl·lit."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Per fer una trucada, primer finalitza la connexió per satèl·lit."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Pots enviar i rebre missatges sense una xarxa mòbil o Wi‑Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informació d\'emergència"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Propietari"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Torna a tocar per veure la informació"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml
index 660da5e..cca342f 100644
--- a/res/values-cs/strings.xml
+++ b/res/values-cs/strings.xml
@@ -283,8 +283,8 @@
<string name="data_enable_summary" msgid="696860063456536557">"Povolit používání dat"</string>
<string name="dialog_alert_title" msgid="5260471806940268478">"Pozor"</string>
<string name="roaming" msgid="1576180772877858949">"Roaming"</string>
- <string name="roaming_enable" msgid="6853685214521494819">"Používat datové služby při roamingu"</string>
- <string name="roaming_disable" msgid="8856224638624592681">"Používat datové služby při roamingu"</string>
+ <string name="roaming_enable" msgid="6853685214521494819">"Při roamingu používat datové služby"</string>
+ <string name="roaming_disable" msgid="8856224638624592681">"Při roamingu používat datové služby"</string>
<string name="roaming_reenable_message" msgid="1951802463885727915">"Datový roaming je vypnutý. Klepnutím ho zapnete."</string>
<string name="roaming_enabled_message" msgid="9022249120750897">"Mohou vám být účtovány poplatky za roaming. Upravte klepnutím."</string>
<string name="roaming_notification_title" msgid="3590348480688047320">"Mobilní datové připojení bylo ztraceno"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Chcete-li uskutečnit běžný hovor, opusťte režim tísňového volání."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Přihlášení k síti nebylo úspěšné."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilní síť je nedostupná."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilní síť není k dispozici.\n\nAbyste mohli uskutečnit hovor, připojte se k bezdrátové síti.\n\nV tomto zařízení není aktivní připojení 2G, což může ovlivňovat možnosti připojení. Přejděte do nastavení a zapněte volbu Povolit 2G."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilní síť není k dispozici. Pokud chcete provést hovor, připojte se k bezdrátové síti."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilní síť není k dispozici.\n\nAbyste mohli uskutečnit hovor, připojte se k bezdrátové síti.\n\nV tomto zařízení není aktivní připojení 2G, což může ovlivňovat možnosti připojení. Přejděte do nastavení a zapněte volbu Povolit 2G."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Chcete-li uskutečnit hovor, zadejte platné telefonní číslo."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Volání se nezdařilo."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Hovor momentálně není možné přidat. Můžete místo toho zkusit poslat zprávu."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Hovory nelze podržet."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Chcete-li provést hovor, připojte se k bezdrátové síti."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Pokud chcete provést hovor, povolte volání přes připojení Wi-Fi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Pokud chcete někomu zavolat, satelitní režim vypněte."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Pokud chcete někomu zavolat, nejdřív ukončete satelitní připojení."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Zprávy můžete odesílat a přijímat bez mobilní sítě nebo sítě Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Nouzové informace"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Vlastník"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Údaje zobrazíte dalším klepnutím"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml
index 58f2670..d2799b8 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Afslut nødtilbagekaldstilstand for at foretage et almindeligt opkald."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ikke registreret på netværk."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilnetværket er ikke tilgængeligt."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilnetværk er ikke tilgængeligt.\n\nOpret forbindelse til et trådløst netværk for at foretage et opkald.\n\n2G er deaktiveret på denne enhed, hvilket kan påvirke dine forbindelsesmuligheder. Gå til Indstillinger, og aktivér Tillad 2G for at fortsætte."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilnetværk er ikke tilgængeligt. Opret forbindelse til et trådløst netværk for at foretage et opkald."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilnetværk er ikke tilgængeligt.\n\nOpret forbindelse til et trådløst netværk for at foretage et opkald.\n\n2G er deaktiveret på denne enhed, hvilket kan påvirke dine forbindelsesmuligheder. Gå til Indstillinger, og aktivér Tillad 2G for at fortsætte."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Angiv et gyldigt nummer for at foretage et opkald."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Opkald mislykkedes."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Opkaldet kan ikke tilføjes lige nu. Du kan prøve at sende en besked i stedet."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Opkald kan ikke sættes i venteposition."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Opret forbindelse til et trådløst netværk for at foretage et opkald."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Aktivér Wi-Fi-opkald for at foretage et opkald."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Deaktiver satellit for at foretage et opkald."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Hvis du vil foretage et opkald, skal du først afslutte satellitforbindelsen."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Du kan sende og modtage beskeder uden et mobil- eller Wi-Fi-netværk."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Nødoplysninger"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Ejer"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tryk igen for at se oplysninger"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
@@ -862,7 +867,7 @@
<string name="radioInfo_phone_offhook" msgid="7564601639749936170">"Opkald i gang"</string>
<string name="radioInfo_data_disconnected" msgid="8085447971880814541">"Afbrudt"</string>
<string name="radioInfo_data_connecting" msgid="925092271092152472">"Forbindelsen oprettes"</string>
- <string name="radioInfo_data_connected" msgid="7637335645634239508">"Tilsluttet"</string>
+ <string name="radioInfo_data_connected" msgid="7637335645634239508">"Forbundet"</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>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
index 7378480..b142bcd 100644
--- a/res/values-de/strings.xml
+++ b/res/values-de/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Beende den Notfallrückrufmodus, um einen Anruf zu tätigen, bei dem es sich nicht um einen Notfall handelt."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Nicht in Netzwerk registriert."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilfunknetz ist nicht verfügbar."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilfunknetz nicht verfügbar.\n\nStelle eine Verbindung zu einem drahtlosen Netzwerk her, um zu telefonieren.\n\n2G ist auf diesem Gerät deaktiviert. Dies kann deine Verbindung beeinträchtigen. Gehe zu den Einstellungen und aktiviere „2G zulassen“, um fortzufahren."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Es ist kein Mobilfunknetz verfügbar. Stelle zum Telefonieren eine WLAN-Verbindung her."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilfunknetz nicht verfügbar.\n\nStelle eine Verbindung zu einem drahtlosen Netzwerk her, um zu telefonieren.\n\n2G ist auf diesem Gerät deaktiviert. Dies kann deine Verbindung beeinträchtigen. Gehe zu den Einstellungen und aktiviere „2G zulassen“, um fortzufahren."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Gib eine gültige Nummer ein."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Fehler beim Anruf."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Der Anruf kann momentan nicht hinzugefügt werden. Versuche stattdessen, eine Nachricht zu senden."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Anrufe können nicht gehalten werden."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Stelle zum Telefonieren eine WLAN-Verbindung her."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Aktiviere WLAN-Telefonie, um anzurufen."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Deaktiviere den Satellitenmodus, um einen Anruf zu tätigen."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Um einen Anruf zu tätigen, musst du zuerst die Satellitenverbindung beenden."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Du kannst Nachrichten ohne Mobilfunknetz oder WLAN senden und empfangen."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Notfallinformationen"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Eigentümer"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Noch einmal tippen, um Informationen anzuzeigen"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml
index 875ae61..ae3a890 100644
--- a/res/values-el/strings.xml
+++ b/res/values-el/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Πραγματοποιήστε έξοδο από τη λειτουργία επιστροφής κλήσης έκτακτης ανάγκης για να πραγματοποιήσετε μια κλήση μη έκτακτης ανάγκης."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Δεν έχετε εγγραφεί στο δίκτυο."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Το δίκτυο κινητής τηλεφωνίας δεν είναι διαθέσιμο."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Το δίκτυο κινητής τηλεφωνίας δεν είναι διαθέσιμο.\n\nΣυνδεθείτε σε ένα ασύρματο δίκτυο για να πραγματοποιήσετε μια κλήση.\n\nΤο 2G είναι απενεργοποιημένο σε αυτή τη συσκευή και αυτό ενδέχεται να επηρεάζει τη σύνδεσή σας. Μεταβείτε στις Ρυθμίσεις και ενεργοποιήστε το στοιχείο Να επιτρέπεται το 2G για να συνεχίσετε."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Το δίκτυο κινητής τηλεφωνίας δεν είναι διαθέσιμο. Συνδεθείτε σε ένα ασύρματο δίκτυο για να πραγματοποιήσετε μια κλήση."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Το δίκτυο κινητής τηλεφωνίας δεν είναι διαθέσιμο.\n\nΣυνδεθείτε σε ένα ασύρματο δίκτυο για να πραγματοποιήσετε μια κλήση.\n\nΤο δίκτυο 2G είναι απενεργοποιημένο σε αυτή τη συσκευή και αυτό ενδέχεται να επηρεάζει τη σύνδεσή σας. Μεταβείτε στις Ρυθμίσεις και ενεργοποιήστε το στοιχείο Να επιτρέπεται το 2G για να συνεχίσετε."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Για να πραγματοποιήσετε κλήση, εισαγάγετε έναν έγκυρο αριθμό."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Η κλήση απέτυχε."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Δεν είναι δυνατή η προσθήκη της κλήσης αυτήν τη στιγμή. Δοκιμάστε να επικοινωνήσετε με αποστολή μηνύματος."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Δεν είναι δυνατή η αναμονή κλήσεων."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Συνδεθείτε σε ασύρματο δίκτυο για να πραγματοποιήσετε μια κλήση."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Ενεργοποιήστε τη δυνατότητα κλήσεων μέσω Wi-Fi για να πραγματοποιήσετε μια κλήση."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Απενεργοποιήστε τη λειτουργία δορυφόρου για να πραγματοποιήσετε μια κλήση."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Για να πραγματοποιήσετε μια κλήση, τερματίστε πρώτα τη δορυφορική σύνδεση."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Μπορείτε να στέλνετε και να λαμβάνετε μηνύματα χωρίς δίκτυο κινητής τηλεφωνίας ή Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Πληροφορίες έκτακτης ανάγκης"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Κάτοχος"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Πατήστε ξανά για προβολή πληροφοριών"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml
index 9a7861f..765321b 100644
--- a/res/values-en-rAU/strings.xml
+++ b/res/values-en-rAU/strings.xml
@@ -542,7 +542,9 @@
<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_2g" msgid="904434080740846116">"Mobile network not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2G to continue."</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_2g_user" msgid="8218768986365299663">"Mobile network is not available.\n\nConnect to a wireless network to make a call.\n\n2 G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2 G to continue."</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>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Can\'t hold calls."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Connect to a wireless network to make a call."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Enable Wi-Fi calling to make a call."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Disable satellite mode to make a call."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"To make a call, first end the satellite connection."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"You can send and receive messages without a mobile or Wi-Fi network."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Emergency information"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Owner"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tap again to view info"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml
index 81942d0..5fb42ff 100644
--- a/res/values-en-rCA/strings.xml
+++ b/res/values-en-rCA/strings.xml
@@ -542,7 +542,9 @@
<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_2g" msgid="904434080740846116">"Mobile network not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2G to continue."</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_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobile network is not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2G to continue."</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 reach out by sending a message."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Can\'t hold calls."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Connect to a wireless network to make a call."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Enable Wi-Fi calling to make a call."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Disable satellite mode to make a call."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"To make a call, first end the satellite connection."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"You can send and receive messages without a mobile or Wi-Fi network."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Emergency information"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Owner"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tap again to view info"</string>
@@ -841,6 +844,7 @@
<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="mock_carrier_roaming_satellite_string" msgid="4796300252858292593">"Mock Carrier Satellite Mode (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>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index 9a7861f..765321b 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -542,7 +542,9 @@
<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_2g" msgid="904434080740846116">"Mobile network not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2G to continue."</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_2g_user" msgid="8218768986365299663">"Mobile network is not available.\n\nConnect to a wireless network to make a call.\n\n2 G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2 G to continue."</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>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Can\'t hold calls."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Connect to a wireless network to make a call."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Enable Wi-Fi calling to make a call."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Disable satellite mode to make a call."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"To make a call, first end the satellite connection."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"You can send and receive messages without a mobile or Wi-Fi network."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Emergency information"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Owner"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tap again to view info"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml
index 9a7861f..765321b 100644
--- a/res/values-en-rIN/strings.xml
+++ b/res/values-en-rIN/strings.xml
@@ -542,7 +542,9 @@
<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_2g" msgid="904434080740846116">"Mobile network not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2G to continue."</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_2g_user" msgid="8218768986365299663">"Mobile network is not available.\n\nConnect to a wireless network to make a call.\n\n2 G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2 G to continue."</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>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Can\'t hold calls."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Connect to a wireless network to make a call."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Enable Wi-Fi calling to make a call."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Disable satellite mode to make a call."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"To make a call, first end the satellite connection."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"You can send and receive messages without a mobile or Wi-Fi network."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Emergency information"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Owner"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tap again to view info"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml
index d275cc4..9af3f97 100644
--- a/res/values-en-rXC/strings.xml
+++ b/res/values-en-rXC/strings.xml
@@ -542,7 +542,9 @@
<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_2g" msgid="904434080740846116">"Mobile network not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2G to continue."</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_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobile network is not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable Allow 2G to continue."</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 reach out by sending a message."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Can\'t hold calls."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Connect to a wireless network to make a call."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Enable Wi-Fi calling to make a call."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Disable satellite mode to make a call."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"To make a call, first end the satellite connection."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"You can send and receive messages without a mobile or Wi-Fi network."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Emergency information"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Owner"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tap again to view info"</string>
@@ -841,6 +844,7 @@
<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="mock_carrier_roaming_satellite_string" msgid="4796300252858292593">"Mock Carrier Satellite Mode (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>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
index 2a25ded..f543a9a 100644
--- a/res/values-es-rUS/strings.xml
+++ b/res/values-es-rUS/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Para realizar una llamada que no sea de emergencia, sal del modo de devolución de llamada de emergencia."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"No registrado en la red."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"La red móvil no está disponible."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"La red móvil no está disponible.\n\nConéctate a una red inalámbrica para realizar una llamada.\n\nLa conexión 2G está inhabilitada en este dispositivo, lo que podría afectar la conectividad. Ve a Configuración y habilita Permitir 2G para continuar."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"La red móvil no está disponible. Conéctate a una red inalámbrica para realizar una llamada."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"La red móvil no está disponible.\n\nConéctate a una red inalámbrica para realizar una llamada.\n\nLa conexión 2G está inhabilitada en este dispositivo, lo que podría afectar la conectividad. Ve a Configuración y habilita Permitir 2G para continuar."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Para realizar una llamada, ingresa un número válido."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Error en la llamada"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"No se puede agregar la llamada en este momento. Para comunicarte, puedes enviar un mensaje."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"No es posible poner las llamadas en espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Conectarse a una red inalámbrica para hacer una llamada"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Habilita las llamadas con Wi-Fi para hacer una llamada."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Inhabilita el modo satelital para realizar una llamada."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Para realizar una llamada, primero finaliza la conexión satelital."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Puedes enviar y recibir mensajes incluso si no tienes conexión a una red móvil o Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Información de emergencia"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Propietario"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Vuelve a presionar para ver la información"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
index 26d5631..863a88d 100644
--- a/res/values-es/strings.xml
+++ b/res/values-es/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Sal del modo de devolución de llamada de emergencia para hacer otro tipo de llamada."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"No se ha podido conectar a la red"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"La red móvil no está disponible."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"La red móvil no está disponible.\n\nConéctate a una red inalámbrica para hacer una llamada.\n\nEl 2G está inhabilitado en este dispositivo, lo que puede afectar a tu conectividad. Ve a Ajustes y habilita Permitir 2G para continuar."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"La red móvil no está disponible. Conéctate a una para llamar."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"La red móvil no está disponible.\n\nConéctate a una red inalámbrica para hacer una llamada.\n\nEl 2G está inhabilitado en este dispositivo, lo que puede afectar a tu conectividad. Ve a Ajustes y habilita Permitir 2G para continuar."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Para realizar una llamada, introduce un número válido."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"No se ha podido llamar."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"No se puede realizar la llamada en estos momentos. Intenta ponerte en contacto mediante un mensaje."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"No se pueden retener llamadas."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Conéctate a una red inalámbrica para hacer llamadas."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Para llamar, tienes que habilitar las llamadas por Wi-Fi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Inhabilita el modo Satélite para hacer llamadas."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Para hacer una llamada, primero finaliza la conexión por satélite."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Puedes enviar y recibir mensajes sin una red móvil o Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Información de emergencia"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Propietario"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tocar de nuevo para ver la información"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml
index 60c4d40..4b3c466 100644
--- a/res/values-et/strings.xml
+++ b/res/values-et/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Muude kui hädaabikõne tegemiseks väljuge hädaabikõnede režiimist."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ei ole võrku registreeritud."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobiilsidevõrk pole saadaval."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobiilsidevõrk pole saadaval.\n\nHelistamiseks looge ühendus juhtmeta võrguga.\n\n2G on selles seadmes keelatud, mis võib teie ühenduvust mõjutada. Jätkamiseks avage Seaded ja lubage lüliti Luba 2G."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobiilsidevõrk pole saadaval. Helistamiseks looge ühendus traadita võrguga."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobiilsidevõrk pole saadaval.\n\nHelistamiseks looge ühendus juhtmeta võrguga.\n\n2G on selles seadmes keelatud, mis võib teie ühenduvust mõjutada. Jätkamiseks avage Seaded ja lubage lüliti Luba 2G."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Helistamiseks sisestage kehtiv number."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Kõne ebaõnnestus."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Kõnet ei saa praegu lisada. Proovige helistamise asemel sõnum saata."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Kõnesid ei saa ootele panna."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Helistamiseks looge ühendus traadita võrguga."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Lubage helistamiseks WiFi-kõned."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Helistamiseks keelake satelliidirežiim."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Helistamiseks katkestage esmalt satelliitühendus."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Teil on võimalik sõnumeid saata ja vastu võtta ilma mobiilside- ja WiFi-võrguta."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Hädaabiteave"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Omanik"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Teabe vaatamiseks puudutage uuesti"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml
index 4790caa..c5d795c 100644
--- a/res/values-eu/strings.xml
+++ b/res/values-eu/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Larrialdikoak ez diren deiak egiteko, irten larrialdi-zerbitzuen deiak jasotzeko modutik."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ez dago sarean erregistratuta."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Sare mugikorra ez dago erabilgarri."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Sare mugikorra ez dago erabilgarri.\n\nDeia egiteko, konektatu hari gabeko sare batera.\n\n2G desgaituta dago gailuan, eta baliteke horrek konexioan eragina izatea. Aurrera egiteko, joan ezarpenetara eta eman 2G erabiltzeko baimena."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Sare mugikorra ez dago erabilgarri. Deia egiteko, konektatu haririk gabeko sare batera."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Sare mugikorra ez dago erabilgarri.\n\nDeia egiteko, konektatu hari gabeko sare batera.\n\n2G desgaituta dago gailuan, eta baliteke horrek konexioan eragina izatea. Aurrera egiteko, joan ezarpenetara eta eman 2G erabiltzeko baimena."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Deitzeko, idatzi balio duen zenbaki bat."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Ezin izan da deitu."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Une honetan, ezin da egin deia. Deitu ordez, mezu bat bidaltzen saia zaitezke."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Ezin dira zain utzi deiak."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Deia egiteko, konektatu haririk gabeko sare batera."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Deia egiteko, gaitu wifi bidezko deiak."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Deiak egiteko, desgaitu satelite modua."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Dei bat egiteko, amaitu satelite bidezko konexioa."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Mezuak bidali eta jaso ditzakezu sare mugikorrik edo wifi-sarerik gabe."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Larrialdietarako informazioa"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Jabea"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Informazioa ikusteko, sakatu berriro"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
@@ -863,7 +868,7 @@
<string name="radioInfo_data_disconnected" msgid="8085447971880814541">"Deskonektatuta"</string>
<string name="radioInfo_data_connecting" msgid="925092271092152472">"Konektatzen"</string>
<string name="radioInfo_data_connected" msgid="7637335645634239508">"Konektatuta"</string>
- <string name="radioInfo_data_suspended" msgid="8695262782642002785">"Behin-behinean itxitakoak"</string>
+ <string name="radioInfo_data_suspended" msgid="8695262782642002785">"Aldi baterako 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>
diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml
index c52cb86..873e30e 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -453,7 +453,7 @@
<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_summary" msgid="3556460926168473346">"فعال کردن حالت رازداری پیشرفته"</string>
+ <string name="voice_privacy_summary" msgid="3556460926168473346">"فعال کردن حالت حریم خصوصی پیشرفته"</string>
<string name="tty_mode_option_title" msgid="3843817710032641703">"حالت TTY"</string>
<string name="tty_mode_option_summary" msgid="4770510287236494371">"تنظیم حالت TTY"</string>
<string name="auto_retry_mode_title" msgid="2985801935424422340">"سعی مجدد خودکار"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"برای برقراری تماس غیراضطراری از حالت پاسخ تماس اضطراری خارج شوید."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"در شبکه ثبت نشده است."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"شبکهٔ تلفن همراه موجود نیست."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"شبکه تلفن همراه دردسترس نیست.\n\nبرای تماس گرفتن به شبکه بیسیم متصل شوید.\n\nشبکه نسل دوم در این دستگاه غیرفعال است که ممکن است بر قابلیت اتصالتان تأثیر بگذارد. برای ادامه دادن به «تنظیمات» بروید و گزینه «اجازه دادن به شبکه نسل دوم» را فعال کنید."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"شبکه تلفن همراه دردسترس نیست. برای برقراری تماس به شبکه بیسیم متصل شوید."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"شبکه تلفن همراه دردسترس نیست.\n\nبرای تماس گرفتن به شبکه بیسیم متصل شوید.\n\nشبکه نسل دوم در این دستگاه غیرفعال است که ممکن است بر قابلیت اتصالتان تأثیر بگذارد. برای ادامه دادن به «تنظیمات» بروید و گزینه «اجازه دادن به شبکه نسل دوم» را فعال کنید."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"برای برقراری تماس، یک شماره معتبر وارد کنید."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"تماس ناموفق بود."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"درحال حاضر برقراری تماس امکانپذیر نیست. میتوانید با ارسال پیام ارتباط برقرار کنید."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"نگهداشتن تماسها ممکن نیست."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"برای برقراری تماس، به یک شبکه بیسیم وصل شوید"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"برای برقراری تماس، تماس Wi-Fi را فعال کنید."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"برای برقراری تماس، حالت ماهواره را غیرفعال کنید."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"برای برقراری تماس، ابتدا اتصال ماهواره را قطع کنید."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"میتوانید بدون شبکه تلفن همراه یا شبکه Wi-Fi پیام ارسال و دریافت کنید."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"اطلاعات اضطراری"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"مالک"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"برای دیدن اطلاعات، دوباره ضربه بزنید"</string>
@@ -661,7 +664,7 @@
<string name="description_dial_button" msgid="8614631902795087259">"شماره گیری"</string>
<string name="description_dialpad_button" msgid="7395114120463883623">"نمایش صفحه شماره گیری"</string>
<string name="pane_title_emergency_dialpad" msgid="3627372514638694401">"صفحه شمارهگیری اضطراری"</string>
- <string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"پست صوتی دیداری"</string>
+ <string name="voicemail_visual_voicemail_switch_title" msgid="6610414098912832120">"پست صوتی تصویری"</string>
<string name="voicemail_set_pin_dialog_title" msgid="7005128605986960003">"تنظیم پین"</string>
<string name="voicemail_change_pin_dialog_title" msgid="4633077715231764435">"تغییر پین"</string>
<string name="preference_category_ringtone" msgid="8787281191375434976">"آهنگ زنگ و لرزش"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"مشاهده دفترچه نشانی سیمکارت"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"مشاهده شمارههای شمارهگیری ثابت"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"مشاهده شمارههای شمارهگیری سرویس"</string>
diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml
index f24af53..b004972 100644
--- a/res/values-fi/strings.xml
+++ b/res/values-fi/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Poistu hätäpuhelujen takaisinsoittotilasta soittaaksesi muun kuin hätäpuhelun."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ei rekisteröity verkkoon."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobiiliverkko ei käytettävissä."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobiiliverkko ei ole käytettävissä.\n\nYhdistä langattomaan verkkoon, jos haluat soittaa puhelun.\n\n2G ei ole käytössä tällä laitteella, mikä saattaa vaikuttaa yhteyksiin. Jatka siirtymällä asetuksiin ja ottamalla \"Salli 2G\" käyttöön."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobiiliverkko ei ole käytettävissä. Yhdistä langattomaan verkkoon, jos haluat soittaa puhelun."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobiiliverkko ei ole käytettävissä.\n\nYhdistä langattomaan verkkoon, jos haluat soittaa puhelun.\n\n2G ei ole käytössä tällä laitteella, mikä saattaa vaikuttaa yhteyksiin. Jatka siirtymällä asetuksiin ja ottamalla \"Salli 2G\" käyttöön."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Soita antamalla kelvollinen numero."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Puhelu epäonnistui."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Puhelua ei voi lisätä juuri nyt. Voit sen sijaan yrittää lähettää viestin."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Puhelujen pito ei onnistu."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Yhdistä langattomaan verkkoon, jos haluat soittaa puhelun."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Ota Wi-Fi-puhelut käyttöön soittaaksesi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Poista satelliittitila käytöstä, jotta voit soittaa puhelun."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Lopeta satelliittiyhteys, jotta voit soittaa puhelun."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Voit lähettää ja vastaanottaa viestejä ilman mobiili‑ tai Wi-Fi-verkkoa."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Vaaratiedot"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Omistaja"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Katso tiedot napauttamalla uudelleen"</string>
@@ -617,7 +620,7 @@
<string name="ota_title_activate" msgid="4049645324841263423">"Aktivoi puhelin"</string>
<string name="ota_touch_activate" msgid="838764494319694754">"Sinun täytyy soittaa erityinen puhelu aktivoidaksesi puhelimesi palvelun. \n\nPaina Aktivoi ja aktivoi puhelimesi kuulemiesi ohjeiden avulla."</string>
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Aktivoidaan…"</string>
- <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Puhelimen mobiilitiedonsiirtopalvelua aktivoidaan.\n\nAktivointi voi kestää viisi minuuttia."</string>
+ <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Puhelimen mobiilidatapalvelua aktivoidaan.\n\nAktivointi voi kestää viisi minuuttia."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Ohitetaanko aktivointi?"</string>
<string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Jos ohitat aktivoinnin, et voi soittaa puheluita etkä muodostaa verkkoyhteyttä (voit tosin muodostaa yhteyden Wi-Fi-verkkoihin). Sinua pyydetään aktivoimaan puhelimesi aina kun käynnistät sen siihen saakka, että aktivoit sen."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Ohita"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml
index 95e6ae9..adfc9b3 100644
--- a/res/values-fr-rCA/strings.xml
+++ b/res/values-fr-rCA/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Quittez le mode de rappel d\'urgence pour effectuer un appel non urgent."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Non enregistré sur le réseau"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Réseau pour mobile non disponible"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Réseau mobile non disponible.\n\nConnectez-vous à un réseau sans fil pour passer un appel.\n\nLe réseau 2G est désactivé sur cet appareil, ce qui peut affecter votre connectivité. Accédez aux paramètres et activez Autoriser les réseaux 2G pour continuer."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Le réseau mobile n\'est pas accessible. Connectez-vous à un réseau sans fil pour effectuer un appel."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Le réseau mobile n\'est pas disponible.\n\nConnectez-vous à un réseau sans fil pour passer un appel.\n\nLe réseau 2G est désactivé sur cet appareil, ce qui peut affecter votre connectivité. Accédez aux paramètres et activez Autoriser les réseaux 2G pour continuer."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Pour faire un appel, entrez un numéro valide."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Échec de l\'appel."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Impossible d\'ajouter l\'appel pour le moment. Vous pouvez essayer de joindre la personne en lui envoyant un message."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Impossible de mettre les appels en attente."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Connectez-vous à un réseau Wi-Fi pour faire un appel."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Activez les appels Wi-Fi pour faire un appel."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Désactivez le mode Satellite pour passer un appel."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Pour passer un appel, mettez d\'abord fin à la connexion par satellite."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Vous pouvez envoyer et recevoir des messages sans avoir recours à un appareil mobile ni à un réseau Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Renseignements en cas d\'urgence"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Propriétaire"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Touchez à nouveau pour afficher les renseignements"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 85a5a93..e26f13b 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Veuillez quitter le mode de rappel d\'urgence pour passer un appel standard."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Non enregistré sur le réseau."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Réseau mobile non disponible"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Réseau mobile non disponible.\n\nConnectez-vous à un réseau sans fil pour passer un appel.\n\nLa 2G est désactivée sur cet appareil, ce qui peut affecter votre connectivité. Accédez aux paramètres et activez \"Autoriser la 2G\" pour continuer."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Le réseau mobile n\'est pas disponible. Connectez-vous à un réseau sans fil pour passer un appel."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Réseau mobile non disponible.\n\nConnectez-vous à un réseau sans fil pour passer un appel.\n\nLa 2G est désactivée sur cet appareil, ce qui peut affecter votre connectivité. Accédez aux paramètres et activez \"Autoriser la 2G\" pour continuer."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Pour émettre un appel, veuillez saisir un numéro valide."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Échec de l\'appel."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Impossible d\'ajouter un appel pour le moment. Essayez plutôt d\'envoyer un message."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Impossible de mettre les appels en attente."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Connectez-vous à un réseau sans fil pour passer un appel."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Pour passer un appel, veuillez activer les appels Wi-Fi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Désactivez le mode Satellite pour passer un appel."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Pour passer un appel, mettez d\'abord fin à la connexion satellite."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Vous pouvez envoyer et recevoir des messages sans connexion au réseau mobile ou Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informations d\'urgence"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Propriétaire"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Appuyer à nouveau pour afficher les informations"</string>
@@ -595,7 +598,7 @@
<string name="singleContactImportedMsg" msgid="3619804066300998934">"Contact importé"</string>
<string name="failedToImportSingleContactMsg" msgid="228095510489830266">"Échec de l\'importation du contact."</string>
<string name="hac_mode_title" msgid="4127986689621125468">"Assistance auditive"</string>
- <string name="hac_mode_summary" msgid="7774989500136009881">"Activer la compatibilité avec les prothèses auditives"</string>
+ <string name="hac_mode_summary" msgid="7774989500136009881">"Activer la compatibilité avec les appareils auditifs"</string>
<string name="rtt_mode_title" msgid="3075948111362818043">"Appel texte en temps réel"</string>
<string name="rtt_mode_summary" msgid="8631541375609989562">"Autoriser l\'échange de messages pendant les appels vocaux"</string>
<string name="rtt_mode_more_information" msgid="587500128658756318">"La fonctionnalité de texte en temps réel vient en aide aux personnes sourdes, malentendantes, qui ont un trouble de la parole, ou qui ont besoin d\'une transcription en plus de la voix.<br> <a href=<xliff:g id="URL">http://support.google.com/mobile?p=telephony_rtt</xliff:g>>En savoir plus</a>\n <br><br> - Les appels texte en temps réel sont enregistrés sous forme transcrite\n <br> - Le mode texte en temps réel n\'est pas disponible pour les appels vidéo"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml
index 5ce9ea3..44aa75d 100644
--- a/res/values-gl/strings.xml
+++ b/res/values-gl/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Sae do modo de devolución de chamada de emerxencia para facer unha chamada que non sexa de emerxencia."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Sen rexistro na rede"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"A rede móbil non está dispoñible."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"A rede de telefonía móbil non está dispoñible.\n\nConéctate a unha rede sen fíos para facer chamadas.\n\nA rede 2G está desactivada neste dispositivo, o que pode impedir que te conectes. Para continuar, vai a Configuración e activa a opción Permitir uso de 2G."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"A rede móbil non está dispoñible. Conéctate a unha rede sen fíos para facer unha chamada."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"A rede de telefonía móbil non está dispoñible.\n\nConéctate a unha rede sen fíos para facer chamadas.\n\nA rede 2G está desactivada neste dispositivo, o que pode impedir que te conectes. Para continuar, vai a Configuración e activa a opción Permitir uso de 2G."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Para realizar unha chamada, introduce un número válido."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Produciuse un erro na chamada."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Non se pode realizar a chamada neste momento. Podes tentar poñerte en contacto mediante unha mensaxe."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Non se poden poñer as chamadas en espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Conéctate a unha rede sen fíos para facer unha chamada."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Activa as chamadas por wifi para facer unha chamada."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Desactiva o modo Satélite para facer chamadas."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Para facer unha chamada, primeiro finaliza a conexión por satélite."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Podes enviar e recibir mensaxes sen unha rede de telefonía móbil ou wifi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Información de emerxencia"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Propietario"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Toca de novo para consultar a información"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml
index 99606a0..3b3ce6f 100644
--- a/res/values-gu/strings.xml
+++ b/res/values-gu/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"બિન-કટોકટીનો કૉલ કરવા માટે કટોકટી કૉલબૅક મોડમાંથી બહાર નીકળો."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"નેટવર્ક પર નોંધણી કરાયેલ નથી."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"મોબાઇલ નેટવર્ક ઉપલબ્ધ નથી."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"મોબાઇલ નેટવર્ક ઉપલબ્ધ નથી.\n\nકોઈ કૉલ કરવા માટે, વાયરલેસ નેટવર્કથી કનેક્ટ કરો.\n\nઆ ડિવાઇસ પર 2G સેવા બંધ છે, જે તમારી કનેક્ટિવિટીને અસર કરી શકે છે. સેટિંગમાં જાઓ અને આ સેવાને ચાલુ રાખવા માટે \'2Gને મંજૂરી આપો\' ચાલુ કરો."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"મોબાઇલ નેટવર્ક ઉપલબ્ધ નથી. કૉલ કરવા માટે વાયરલેસ નેટવર્ક સાથે કનેક્ટ કરો."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"મોબાઇલ નેટવર્ક ઉપલબ્ધ નથી.\n\nકોઈ કૉલ કરવા માટે, વાયરલેસ નેટવર્કથી કનેક્ટ કરો.\n\nઆ ડિવાઇસ પર 2G સેવા બંધ છે, જે તમારી કનેક્ટિવિટીને અસર કરી શકે છે. સેટિંગમાં જાઓ અને આ સેવાને ચાલુ રાખવા માટે \'2Gને મંજૂરી આપો\' ચાલુ કરો."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"કૉલ કરવા માટે, માન્ય નંબર દાખલ કરો."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"કૉલ નિષ્ફળ થયો."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"આ સમયે કૉલ ઉમેરી શકાતો નથી. તમે એક સંદેશ મોકલીને સંપર્ક કરવાનો પ્રયાસ કરી શકો છો."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"કૉલ્સને હોલ્ડ કરી શકતાં નથી."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"કૉલ કરવા માટે વાયરલેસ નેટવર્કથી કનેક્ટ કરો."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"કૉલ કરવા માટે Wi-Fi કૉલિંગ સક્ષમ કરો."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"કૉલ કરવા માટે ઉપગ્રહ મોડ બંધ કરો."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"કૉલ કરવા માટે, પહેલાં સૅટલાઇટ કનેક્શન સમાપ્ત કરો."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"તમે મોબાઇલ અથવા વાઇ-ફાઇ નેટવર્ક વિના મેસેજ મોકલી અને પ્રાપ્ત કરી શકો છો."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"ઇમર્જન્સીની માહિતી"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"માલિક"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"માહિતી જોવા માટે ફરીથી ટૅપ કરો"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"સિમમાં સરનામા પુસ્તિકા જુઓ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ફિક્સ્ડ ડાયલિંગ નંબર જુઓ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"સર્વિસ ડાયલિંગ નંબર જુઓ"</string>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 4f8e559..800ded0 100644
--- a/res/values-hi/strings.xml
+++ b/res/values-hi/strings.xml
@@ -165,7 +165,7 @@
<string name="voicemail_default" msgid="6427575113775462077">"आपको सेवा देने वाली कंपनी"</string>
<string name="vm_change_pin_old_pin" msgid="7154951790929009241">"पुराना पिन"</string>
<string name="vm_change_pin_new_pin" msgid="2656200418481288069">"नया पिन"</string>
- <string name="vm_change_pin_progress_message" msgid="626015184502739044">"कृपया प्रतीक्षा करें."</string>
+ <string name="vm_change_pin_progress_message" msgid="626015184502739044">"कृपया इंतज़ार करें."</string>
<string name="vm_change_pin_error_too_short" msgid="1789139338449945483">"नया पिन बहुत छोटा है."</string>
<string name="vm_change_pin_error_too_long" msgid="3634907034310018954">"नया पिन बहुत बड़ा है."</string>
<string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"नया पिन बहुत कमज़ोर है. किसी सशक्त पासवर्ड में निरंतर क्रम या अंकों का दोहराव नहीं होना चाहिए."</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"गैर-आपातकालीन कॉल करने के लिए आपातकालीन कॉलबैक मोड से बाहर निकलें."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"नेटवर्क पर पंजीकृत नहीं."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"मोबाइल नेटवर्क उपलब्ध नहीं."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"मोबाइल नेटवर्क उपलब्ध नहीं है.\n\nकॉल करने के लिए किसी वायरलेस नेटवर्क से कनेक्ट करें.\n\nइस डिवाइस पर 2G नेटवर्क इस्तेमाल करने की सुविधा बंद है. ऐसा हो सकता है कि इसका असर कनेक्टिविटी पर पड़ा हो. जारी रखने के लिए, Settings में जाकर ‘2G के इस्तेमाल की मंज़ूरी दें’ को चालू करें."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"मोबाइल नेटवर्क उपलब्ध नहीं है. कॉल करने के लिए किसी वायरलेस नेटवर्क से कनेक्ट करें."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"मोबाइल नेटवर्क उपलब्ध नहीं है.\n\nकॉल करने के लिए किसी वायरलेस नेटवर्क से कनेक्ट करें.\n\nइस डिवाइस पर 2G नेटवर्क इस्तेमाल करने की सुविधा बंद है, जिससे कनेक्टिविटी पर असर पड़ सकता है. जारी रखने के लिए, Settings में जाएं और ‘2G के इस्तेमाल की मंज़ूरी दें’ को चालू करें."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"कॉल करने के लिए, मान्य नंबर डालें."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"कॉल विफल."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"अभी कॉल जोड़ा नहीं जा सकता. आप संदेश भेजकर संपर्क करने की कोशिश कर सकते हैं."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"कॉल होल्ड नहीं किए जा सकते."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"कॉल करने के लिए किसी वायरलेस नेटवर्क से कनेक्ट करें."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"कॉल करने के लिए वाई-फ़ाई कॉलिंग सक्षम करें."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"कॉल करने के लिए, सैटलाइट मोड को बंद करें."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"कॉल करने के लिए, सैटलाइट कनेक्शन बंद करें."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"आपके पास, मोबाइल या वाई-फ़ाई नेटवर्क के बिना भी मैसेज भेजने और पाने की सुविधा है."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"आपातकाल में दिखने वाली जानकारी"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"मालिक"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"जानकारी देखने के लिए फिर से टैप करें"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"सिम में संपर्कों के पते की सूची देखें"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"फ़िक्स्ड डायलिंग नंबर देखें"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"सेवा के डायलिंग नंबर देखें"</string>
diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml
index 790b6be..2b8b9b6 100644
--- a/res/values-hr/strings.xml
+++ b/res/values-hr/strings.xml
@@ -305,7 +305,7 @@
<string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"mobilni operater, esim, sim, euicc, promjena mobilnog operatera, dodavanje mobilnog operatera"</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">"Mobilni podaci"</string>
- <string name="mobile_data_settings_summary" msgid="5012570152029118471">"Pristupi podacima pomoću mobilne mreže"</string>
+ <string name="mobile_data_settings_summary" msgid="5012570152029118471">"Pristupi podacima putem mobilne mreže"</string>
<string name="data_usage_disable_mobile" msgid="5669109209055988308">"Želite li isključiti mobilne podatke?"</string>
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Odabir je obvezan"</string>
<string name="sim_change_data_title" msgid="9142726786345906606">"Promijeniti podatkovni SIM?"</string>
@@ -485,7 +485,7 @@
<string name="simContacts_title" msgid="2714029230160136647">"Odabir kontakata za uvoz"</string>
<string name="simContacts_airplaneMode" msgid="4654884030631503808">"Isključite način rada u zrakoplovu da biste uvezli kontakte sa SIM kartice."</string>
<string name="enable_pin" msgid="967674051730845376">"Omogući/onemogući PIN za SIM"</string>
- <string name="change_pin" msgid="3657869530942905790">"Promijeni PIN za SIM"</string>
+ <string name="change_pin" msgid="3657869530942905790">"Promijenite PIN za SIM"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"PIN za SIM:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"Stari PIN"</string>
<string name="newPinLabel" msgid="3585899083055354732">"Novi PIN"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Isključite način hitnih poziva da biste uputili poziv koji nije hitan."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Nije registrirano na mreži."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilna mreža nije dostupna."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilna mreža nije dostupna.\n\nPovežite se s bežičnom mrežom da biste uputili poziv.\n\n2G je onemogućen na ovom uređaju, što možda utječe na povezivost. Za nastavak otvorite postavke i omogućite opciju Dopusti 2G."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilna mreža nije dostupna. Povežite se s bežičnom mrežom da biste uputili poziv."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilna mreža nije dostupna.\n\nPovežite se s bežičnom mrežom da biste uputili poziv.\n\n2G je onemogućen na ovom uređaju, što možda utječe na povezivost. Za nastavak otvorite postavke i omogućite opciju Dopusti 2G."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Unesite važeći broj da biste uspostavili poziv."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Poziv nije uspio."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Poziv se trenutačno ne može dodati. Pokušajte poslati poruku."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Pozivi se ne mogu stavljati na čekanje."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Povežite se s bežičnom mrežom da biste uputili poziv."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Omogućite pozivanje putem Wi-Fi veze da biste uspostavili poziv."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Onemogućite način satelita da biste uputili poziv."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Da biste uputili poziv, najprije prekinite satelitsku vezu."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Možete slati i primati poruke bez mobilne ili Wi-Fi mreže."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Podaci za hitne slučajeve"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Vlasnik"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Dodirnite ponovno da biste vidjeli informacije"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml
index 54c112b..bfd7472 100644
--- a/res/values-hu/strings.xml
+++ b/res/values-hu/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Lépjen ki a Segélykérő visszahívása módból nem vészjellegű hívás kezdeményezéséhez."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Nincs regisztrálva a hálózaton."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"A mobilhálózat nem érhető el."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Nem áll rendelkezésre mobilhálózat.\n\nHívás indításához csatlakozzon vezeték nélküli hálózathoz.\n\nA 2G le van tiltva ezen az eszközön, ami hatással lehet a kapcsolódásra. A folytatáshoz nyissa meg a beállításokat, és kapcsolja be a 2G engedélyezése lehetőséget."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"A mobilhálózat nem érhető el. Hívás indításához csatlakozzon egy vezeték nélküli hálózathoz."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Nem áll rendelkezésre mobilhálózat.\n\nHívás indításához csatlakozzon vezeték nélküli hálózathoz.\n\nA 2G le van tiltva ezen az eszközön, ami hatással lehet a kapcsolódásra. A folytatáshoz nyissa meg a beállításokat, és kapcsolja be a 2G engedélyezése lehetőséget."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Hívásindításhoz adjon meg egy érvényes számot."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Sikertelen hívás."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Jelenleg nem indítható hívás. Üzenet küldésével érheti el a másik felet."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"A hívások nem tarthatók."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Hívás indításához csatlakozzon egy vezeték nélküli hálózathoz."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Engedélyezze a Wi-Fi-hívást a hívásindításhoz."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Hívás indításához kapcsolja ki a műholdas módot."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Hívás indításához először szakítsa meg a műholdas kapcsolatot."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Küldhet és fogadhat üzeneteket mobil- és Wi-Fi-hálózat nélkül is."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Segélyhívási információk"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Tulajdonos"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Koppints újra az információk megtekintéséhez"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml
index 8e68a06..c8b1198 100644
--- a/res/values-hy/strings.xml
+++ b/res/values-hy/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Սովորական զանգ կատարելու համար դուրս եկեք շտապ կանչի ռեժիմից։"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ցանցում գրանցված չէ:"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Բջջային ցանցն անհասանելի է:"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Բջջային ցանցն անհասանելի է։\n\nԶանգելու համար միացեք անլար ցանցին։\n\n2G-ն անջատված է այս սարքում, ինչը կարող է ազդել կապի վրա։ Շարունակելու համար անցեք Կարգավորումներ և միացրեք «Թույլատրել 2G-ն»։"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Բջջային ցանցն անհասանելի է: Զանգելու համար միացեք Wi-Fi ցանցին:"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Բջջային ցանցն անհասանելի է։\n\nԶանգելու համար միացեք անլար ցանցին։\n\n2G-ն անջատված է այս սարքում, ինչը կարող է ազդել կապի վրա։ Շարունակելու համար անցեք Կարգավորումներ և միացրեք «Թույլատրել 2G-ն»։"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Զանգ կատարելու համար մուտքագրեք ճիշտ համար:"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Զանգը ձախողվեց:"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Զանգն այս պահին հնարավոր չէ ավելացնել: Փորձեք հաղորդագրություն ուղարկել:"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Հնարավոր չէ հետաձգել զանգերը:"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Զանգ կատարելու համար միացեք անլար ցանցին:"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Զանգ կատարելու համար միացրեք «Զանգեր Wi-Fi ցանցի միջոցով» գործառույթը:"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Զանգ կատարելու համար անջատեք արբանյակի ռեժիմը։"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Զանգ կատարելու համար նախ անջատեք արբանյակային կապը։"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Դուք կարող եք ուղարկել և ստանալ հաղորդագրություններ՝ առանց բջջային կամ Wi-Fi կապի։"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Անհետաձգելի բուժօգնության տվյալներ"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Սեփականատեր"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Կրկին հպեք՝ տեղեկությունները դիտելու համար"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml
index 9484f54..e4cbd31 100644
--- a/res/values-in/strings.xml
+++ b/res/values-in/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Keluar dari mode telepon balik darurat untuk melakukan panggilan non-darurat."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Tidak terdaftar pada jaringan."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Jaringan seluler tidak tersedia."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Jaringan seluler tidak tersedia.\n\nHubungkan ke jaringan nirkabel untuk melakukan panggilan.\n\n2G dinonaktifkan di perangkat ini, yang mungkin memengaruhi konektivitas Anda. Buka Setelan dan aktifkan Izinkan 2G untuk melanjutkan."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Jaringan seluler tidak tersedia. Sambungkan ke jaringan nirkabel untuk melakukan panggilan."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Jaringan seluler tidak tersedia.\n\nSambungkan ke jaringan nirkabel untuk melakukan panggilan.\n\n2G dinonaktifkan di perangkat ini, yang mungkin memengaruhi konektivitas Anda. Buka Setelan dan aktifkan Izinkan 2G untuk melanjutkan."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Untuk melakukan panggilan telepon, masukkan nomor yang valid."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Telepon gagal."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Panggilan tidak bisa ditambahkan saat ini. Anda bisa mencoba menghubungi dengan mengirim pesan."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Tidak dapat menahan panggilan."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Sambungkan ke jaringan nirkabel untuk melakukan panggilan"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Aktifkan panggilan Wi-Fi untuk melakukan panggilan."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Nonaktifkan mode satelit untuk melakukan panggilan."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Untuk melakukan panggilan, akhiri koneksi satelit terlebih dahulu."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Anda dapat mengirim dan menerima pesan tanpa jaringan seluler atau Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informasi darurat"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Pemilik"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Ketuk lagi untuk melihat info"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml
index 123519e..bd13872 100644
--- a/res/values-is/strings.xml
+++ b/res/values-is/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Hætta í stillingu fyrir svarhringingu neyðarsímtala til að hringja símtal sem ekki er neyðarsímtal."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ekki skráð á símkerfi."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Farsímakerfi ekki tiltækt."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Farsímakerfið er ekki tiltækt.\n\nTengstu þráðlausu neti til að hringja.\n\nSlökkt er á 2G í þessu tæki, sem kann að hafa áhrif á tenginguna. Opnaðu stillingar og virkjaðu Leyfa 2G til að halda áfram."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Farsímakerfi er ekki tiltækt. Tengstu þráðlausu neti til að hringja."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Farsímakerfið er ekki tiltækt.\n\nTengstu þráðlausu neti til að hringja.\n\nSlökkt er á 2G í þessu tæki, sem kann að hafa áhrif á tenginguna. Opnaðu stillingar og virkjaðu Leyfa 2G til að halda áfram."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Sláðu inn gilt númer til að hringja símtal."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Tókst ekki að hringja."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Ekki er hægt að bæta símtali við að svo stöddu. Þú getur reynt að hafa samband með því að senda skilaboð."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Getur ekki sett símtöl í bið."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Tengstu þráðlausu neti til að hringja."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Virkjaðu Wi-Fi símtöl til að hringja."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Slökktu á gervihnattarstillingu til að hringja símtal."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Byrjaðu á því að slökkva á gervihnattatengingunni til að hringja símtal."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Þú getur sent og móttekið skilaboð án tengingar við farsímakerfi eða Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Neyðarupplýsingar"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Eigandi"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Ýttu aftur til að skoða upplýsingar"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
index 2b8e870..8a70695 100644
--- a/res/values-it/strings.xml
+++ b/res/values-it/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Per effettuare chiamate non di emergenza, esci dalla modalità di richiamata di emergenza."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Non registrato sulla rete."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Rete cellulare non disponibile."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Rete mobile non disponibile.\n\nConnettiti a una rete wireless per effettuare una chiamata.\n\nIl 2G è disattivato su questo dispositivo, e questo potrebbe influire sulla tua connettività. Vai alle Impostazioni e attiva Consenti 2G per continuare."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"La rete cellulare non è disponibile. Connettiti a una rete wireless per effettuare una chiamata."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"La rete mobile non è disponibile.\n\nConnettiti a una rete wireless per effettuare una chiamata.\n\nIl 2G è disattivato su questo dispositivo, e questo potrebbe influire sulla tua connettività. Vai alle Impostazioni e attiva Consenti 2G per continuare."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Per effettuare una chiamata, inserisci un numero valido."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Chiamata non riuscita."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Impossibile aggiungere la chiamata al momento. Prova a inviare un messaggio."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Impossibile mettere in attesa le chiamate."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Connettiti a una rete wireless per effettuare una chiamata."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Attiva le chiamate tramite Wi-Fi per effettuare una chiamata."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Disattiva la modalità satellite per effettuare una chiamata."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Per effettuare una chiamata, devi prima terminare la connessione satellitare."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Puoi inviare e ricevere messaggi senza una rete mobile o Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informazioni d\'emergenza"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Proprietario"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tocca di nuovo per visualizzare le informazioni"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml
index a51c72d..0c3e818 100644
--- a/res/values-iw/strings.xml
+++ b/res/values-iw/strings.xml
@@ -321,9 +321,9 @@
<string name="throttle_help" msgid="2624535757028809735">"למידע נוסף"</string>
<string name="throttle_status_subtext" msgid="1110276415078236687">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>%%) מתוך התקופה המרבית של <xliff:g id="USED_2">%3$s</xliff:g>\nהתקופה הבאה מתחילה בעוד <xliff:g id="USED_3">%4$d</xliff:g> ימים (<xliff:g id="USED_4">%5$s</xliff:g>)"</string>
<string name="throttle_data_usage_subtext" msgid="3185429653996709840">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>??) מתוך התקופה המרבית של<xliff:g id="USED_2">%3$s</xliff:g>"</string>
- <string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> חריגה מהמקסימום\nקצב הנתונים ירד ל-<xliff:g id="USED_1">%2$d</xliff:g> Kb לשנייה"</string>
+ <string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> חריגה מהמקסימום\nקצב הנתונים ירד ל-<xliff:g id="USED_1">%2$d</xliff:g>Kb לשנייה"</string>
<string name="throttle_time_frame_subtext" msgid="6462089615392402127">"<xliff:g id="USED_0">%1$d</xliff:g>?? מהמחזור חלפו\nהתקופה הבאה מתחילה בעוד <xliff:g id="USED_1">%2$d</xliff:g> ימים (<xliff:g id="USED_2">%3$s</xliff:g>)"</string>
- <string name="throttle_rate_subtext" msgid="7221971817325779535">"קצב הנתונים יורד ל-<xliff:g id="USED">%1$d</xliff:g> Kb לשנייה במקרה של חריגה ממגבלת השימוש בנתונים"</string>
+ <string name="throttle_rate_subtext" msgid="7221971817325779535">"קצב הנתונים יורד ל-<xliff:g id="USED">%1$d</xliff:g>Kb לשנייה במקרה של חריגה ממגבלת השימוש בנתונים"</string>
<string name="throttle_help_subtext" msgid="2817114897095534807">"למידע נוסף על מדיניות השימוש בנתונים ברשת הסלולרית של הספק שלך"</string>
<string name="cell_broadcast_sms" msgid="4053449797289031063">"SMS בשידור סלולרי"</string>
<string name="enable_disable_cell_bc_sms" msgid="4759958924031721350">"SMS בשידור סלולרי"</string>
@@ -485,7 +485,7 @@
<string name="simContacts_title" msgid="2714029230160136647">"בחירת אנשי קשר לייבוא"</string>
<string name="simContacts_airplaneMode" msgid="4654884030631503808">"יש לבטל את מצב טיסה כדי לייבא אנשי קשר מכרטיס ה-SIM."</string>
<string name="enable_pin" msgid="967674051730845376">"הפעלה/השבתה של קוד האימות של SIM"</string>
- <string name="change_pin" msgid="3657869530942905790">"שינוי קוד אימות של SIM"</string>
+ <string name="change_pin" msgid="3657869530942905790">"שינוי קוד הגישה של ה-SIM"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"קוד אימות של SIM:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"קוד אימות ישן"</string>
<string name="newPinLabel" msgid="3585899083055354732">"קוד אימות חדש"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"עליך לצאת ממצב חירום של התקשרות חזרה כדי לבצע שיחות שאינן שיחות חירום."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"לא רשום ברשת."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"הרשת הסלולרית אינה זמינה."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"הרשת הסלולרית לא זמינה.\n\nצריך להתחבר לרשת אלחוטית כדי להתקשר.\n\nהחיבור ל-2G מושבת במכשיר, ויכול להיות שזה משפיע על הקישוריות. כדי להמשיך, צריך לפתוח את ההגדרות ולאפשר שימוש ב-2G."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"הרשת הסלולרית לא זמינה. עליך להתחבר לרשת אלחוטית כדי להתקשר."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"הרשת הסלולרית לא זמינה.\n\nצריך להתחבר לרשת אלחוטית כדי להתקשר.\n\nהחיבור ל-2G מושבת במכשיר, ויכול להיות שזה משפיע על הקישוריות. כדי להמשיך, צריך לפתוח את ההגדרות ולאפשר שימוש ב-2G."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"כדי להתקשר, יש להזין מספר טלפון חוקי."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"השיחה נכשלה."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"לא ניתן להוסיף את השיחה כרגע. אפשר לנסות לשלוח הודעה."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"לא ניתן להחזיק שיחות."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"יש להתחבר לרשת אלחוטית כדי לבצע שיחה."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"יש להפעיל את \'שיחות Wi-Fi\' כדי להתקשר."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"כדי להתקשר, צריך להפסיק את השימוש במצב לוויין."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"כדי להתקשר, צריך להתנתק מהחיבור הלווייני."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"אפשר לשלוח ולקבל הודעות ללא חיבור לרשת סלולרית או לרשת Wi-Fi"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"מידע למקרה חירום"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"בעלים"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"אפשר להקיש שוב כדי להציג את הפרטים"</string>
@@ -842,6 +845,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index 4127de8..941413a 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -485,7 +485,7 @@
<string name="simContacts_title" msgid="2714029230160136647">"インポートする連絡先の選択"</string>
<string name="simContacts_airplaneMode" msgid="4654884030631503808">"SIMカードから連絡先をインポートするには機内モードをオフにしてください。"</string>
<string name="enable_pin" msgid="967674051730845376">"SIM PINの有効/無効"</string>
- <string name="change_pin" msgid="3657869530942905790">"SIM PINの変更"</string>
+ <string name="change_pin" msgid="3657869530942905790">"SIM PIN を変更"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"SIM PIN:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"古いPIN"</string>
<string name="newPinLabel" msgid="3585899083055354732">"新しいPIN"</string>
@@ -538,11 +538,13 @@
<string name="incall_error_power_off" product="watch" msgid="7191184639454113633">"通話を発信するには、モバイル ネットワークを ON にし、機内モードまたはバッテリー セーバー モードを OFF にしてください。"</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>
+ <string name="incall_error_power_off_thermal" product="default" msgid="8695809601655300168"><b>"スマートフォンが熱くなっています"</b>\n\n"この通話を完了できません。スマートフォンの熱が冷めてから、もう一度お試しください。\n\n緊急通報は通常どおり発信できます。"</string>
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"緊急通報以外の通話を発信するには、緊急通報待機モードを終了してください。"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ご加入の通信サービスがありません"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"モバイルネットワークが利用できません。"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"モバイル ネットワークを利用できません。\n\n電話をかけるにはワイヤレス ネットワークに接続してください。\n\nこのデバイスでは 2G が無効になっており、接続性に影響している可能性があります。続行するには、[設定] に移動し、[2G の許可] を有効にしてください。"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"モバイル ネットワークを利用できません。電話をかけるにはワイヤレス ネットワークに接続してください。"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"モバイル ネットワークを利用できません。\n\n電話をかけるにはワイヤレス ネットワークに接続してください。\n\nこのデバイスでは 2G が無効になっており、接続性に影響している可能性があります。続行するには、[設定] に移動し、[2G の許可] を有効にしてください。"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"発信するには、有効な番号を入力してください。"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"発信できませんでした。"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"現在、通話を追加できません。連絡するには、メッセージを送信してみてください。"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"通話を保留にできません。"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"電話をかけるには無線ネットワークに接続してください。"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"電話をかけるには Wi-Fi 通話を有効にしてください。"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"電話をかけるには、衛星モードを無効にしてください。"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"通話を発信するには、まず衛星通信の接続を完了してください。"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"モバイル ネットワークや Wi-Fi ネットワークを使わずにメッセージを送受信できます。"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"緊急時情報"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"所有者"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"もう一度タップすると情報を確認できます"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml
index f4ca82e..9d89e60 100644
--- a/res/values-ka/strings.xml
+++ b/res/values-ka/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"გამოდით გადაუდებელი გადმორეკვის რეჟიმიდან არაგადაუდებელი ზარის განსახორციელებლად."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ქსელში რეგისტრირებული არ არის."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"მობილური ქსელი მიუწვდომელია."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"მობილური ქსელი მიუწვდომელია.\n\nდაუკავშირდით უსადენო ქსელს ზარის განსახორციელებლად.\n\n2G გამორთულია ამ მოწყობილობაზე, რამაც შეიძლება გავლენა მოახდინოს თქვენს კავშირზე. გასაგრძელებლად გადადით პარამეტრებზე და ჩართეთ „2G-ის დაშვება“."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"მობილური ქსელი მიუწვდომელია. ზარის განსახორციელებლად დაუკავშირდით უსადენო ქსელს."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"მობილური ქსელი მიუწვდომელია.\n\nდაუკავშირდით უსადენო ქსელს ზარის განსახორციელებლად.\n\n2G გამორთულია ამ მოწყობილობაზე, რამაც შეიძლება გავლენა მოახდინოს თქვენს კავშირზე. გასაგრძელებლად გადადით პარამეტრებზე და ჩართეთ „2G-ის დაშვება“."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ზარის განხორციელებისათვის, შეიყვანეთ მოქმედი ნომერი."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"ზარი ვერ განხორციელდა."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ამჟამად ზარის დამატება შეუძლებელია. შეგიძლიათ სცადოთ დაკავშირება შეტყობინების გაგზავნით."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"ზარების დაყოვნება ვერ ხერხდება."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ზარის განსახორციელებლად, დაუკავშირდით უსადენო ქსელს."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"ზარის განსახორციელებლად ჩართეთ Wi-Fi დარეკვა."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"დასარეკად გამორთეთ სატელიტის რეჟიმი."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"დასარეკად ჯერ დაასრულეთ სატელიტური კავშირი."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"შეგიძლიათ გაგზავნოთ და მიიღოთ შეტყობინებები მობილური ან Wi-Fi ქსელის გარეშე."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"საგანგებო ინფორმაცია"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"მფლობელი"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"ინფორმაციის სანახავად შეეხეთ ხელახლა"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml
index 72e9c7f..c6c01e0 100644
--- a/res/values-kk/strings.xml
+++ b/res/values-kk/strings.xml
@@ -194,7 +194,7 @@
<string name="choose_network_title" msgid="5335832663422653082">"Желі таңдау"</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_connecting" msgid="160901383582774987">"Қосылып жатыр…"</string>
<string name="network_could_not_connect" msgid="6547460848093727998">"Қосылмады"</string>
<string-array name="preferred_network_mode_choices">
<item msgid="4531933377509551889">"GSM/WCDMA таңдалған"</item>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Төтенше емес қоңырау шалу үшін төтенше қоңырауды кері шалу режимінен шығыңыз."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Желіде тіркелмеген."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Ұялы желі қол жетімсіз."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Мобильдік желі қолжетімді емес.\n\nҚоңырау шалу үшін сымсыз желіге қосылыңыз.\n\nОсы құрылғыдағы 2G функциясы өшірілген. Бұл байланыс жұмысына әсер етуі мүмкін. Жалғастыру үшін параметрлерге өтіп, \"2G қолдануға рұқсат беру\" опциясын қосыңыз."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Мобильдік желі қолжетімді емес. Қоңырау шалу үшін сымсыз желіге қосылыңыз."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Мобильдік желі қолжетімді емес.\n\nҚоңырау шалу үшін сымсыз желіге қосылыңыз.\n\nОсы құрылғыдағы 2G функциясы өшірілген. Бұл қосылу мүмкіндігіне әсер етуі мүмкін. Жалғастыру үшін \"Параметрлерге\" өтіп, \"2G қолдануға рұқсат беру\" опциясын қосыңыз."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Қоңырау шалу үшін жарамды нөмірді енгізіңіз."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Қоңырау шалынбады."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Қоңырауды қазір қосу мүмкін емес. Хабар жіберіп хабарласуға болады."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Қоңырауларды ұстау мүмкін емес."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Қоңырау шалу үшін сымсыз желіге қосылыңыз."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Қоңырау шалу үшін, Wi-Fi желісін қосыңыз."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Қоңырау шалу үшін жер серігі режимін өшіріңіз."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Қоңырау шалу үшін алдымен жерсерік байланысын аяқтаңыз."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Мобильдік не Wi-Fi желісіне қосылмастан хабар алмаса аласыз."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Төтенше жағдайға арналған ақпарат"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Иесі"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Ақпаратты көру үшін қайта түртіңіз"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml
index d42deb0..31ccb6d 100644
--- a/res/values-km/strings.xml
+++ b/res/values-km/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"ចាកចេញពីរបៀបហៅទៅវិញពេលមានអាសន្នដើម្បីធ្វើការហៅធម្មតា។"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"មិនបានចុះឈ្មោះនៅលើបណ្ដាញ។"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"បណ្ដាញឧបករណ៍ចល័តមិនអាចប្រើបាន។"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"មិនអាចប្រើបណ្ដាញទូរសព្ទចល័តបានទេ។\n\nសូមភ្ជាប់ទៅបណ្តាញឥតខ្សែ ដើម្បីហៅទូរសព្ទ។\n\n2G ត្រូវបានបិទនៅលើឧបករណ៍នេះ ដែលអាចប៉ះពាល់ដល់ការតភ្ជាប់របស់អ្នក។ សូមចូលទៅកាន់ការកំណត់ ហើយបើក \"អនុញ្ញាត 2G\" ដើម្បីបន្ត។"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"មិនមានបណ្តាញទូរសព្ទទេ។ ភ្ជាប់ទៅបណ្តាញឥតខ្សែ ដើម្បីអាចហៅទូរសព្ទបាន។"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"មិនអាចប្រើបណ្ដាញទូរសព្ទចល័តបានទេ។\n\nសូមភ្ជាប់ទៅបណ្តាញឥតខ្សែ ដើម្បីហៅទូរសព្ទ។\n\n2G ត្រូវបានបិទនៅលើឧបករណ៍នេះ ដែលអាចប៉ះពាល់ដល់ការតភ្ជាប់របស់អ្នក។ សូមចូលទៅកាន់ការកំណត់ ហើយបើក \"អនុញ្ញាត 2G\" ដើម្បីបន្ត។"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ដើម្បីធ្វើការហៅ បញ្ចូលលេខដែលមានសុពលភាព។"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"បានបរាជ័យការហៅ។"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"មិនអាចបញ្ចូលការហៅបានទេនៅពេលនេះ។ អ្នកអាចព្យាយាមទាក់ទងតាមរយៈការផ្ញើសារ។"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"មិនអាចរង់ចាំការហៅទេ"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ភ្ជាប់ទៅបណ្តាញឥតខ្សែដើម្បីធ្វើការហៅ។"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"បើកការហៅតាមវ៉ាយហ្វាយដើម្បីធ្វើការហៅ។"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"បិទមុខងារផ្កាយរណប ដើម្បីហៅទូរសព្ទ។"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ដើម្បីហៅទូរសព្ទ សូមបញ្ចប់ការតភ្ជាប់ផ្កាយរណបជាមុនសិន។"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"អ្នកអាចផ្ញើ និងទទួលសារដោយមិនប្រើបណ្ដាញទូរសព្ទចល័ត ឬ Wi-Fi។"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"ព័ត៌មានសង្គ្រោះបន្ទាន់"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"ម្ចាស់"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"ចុចម្ដងទៀត ដើម្បីមើលព័ត៌មាន"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"មើលសៀវភៅអាសយដ្ឋានក្នុងស៊ីមកាត"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"មើលលេខហៅថេរ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"មើលលេខហៅសេវាកម្ម"</string>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index fe39ede..b77b225 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -298,14 +298,14 @@
<string name="sip_accounts_removed_notification_title" msgid="3528076957535736095">"ತಡೆಹಿಡಿಯಲಾಗಿರುವ SIP ಖಾತೆಗಳನ್ನು ಪತ್ತೆಮಾಡಲಾಗಿದೆ ಮತ್ತು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
<string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Android ಪ್ಲ್ಯಾಟ್ಫಾರ್ಮ್ ಇನ್ನು ಮುಂದೆ SIP ಕರೆ ಮಾಡುವಿಕೆಯನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ.\nನಿಮ್ಮ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ SIP ಖಾತೆಗಳನ್ನು <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> ತೆಗೆದುಹಾಕಲಾಗಿದೆ.\nನಿಮ್ಮ ಡೀಫಾಲ್ಟ್ ಕರೆ ಮಾಡುವಿಕೆ ಖಾತೆ ಸೆಟ್ಟಿಂಗ್ ಅನ್ನು ಖಚಿತಪಡಿಸಿ."</string>
<string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ"</string>
- <string name="data_usage_title" msgid="8438592133893837464">"ಅಪ್ಲಿಕೇಶನ್ ಡೇಟಾ ಬಳಕೆ"</string>
+ <string name="data_usage_title" msgid="8438592133893837464">"ಆ್ಯಪ್ ಡೇಟಾ ಬಳಕೆ"</string>
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_1">%1$s</xliff:g> ಬಳಸಲಾದ ಮೊಬೈಲ್ ಡೇಟಾ <xliff:g id="ID_2">%2$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">"ವಾಹಕ, eSIM, ಸಿಮ್, 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_summary" msgid="5012570152029118471">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಬಳಸಿ ಡೇಟಾ ಪ್ರವೇಶಿಸಿ"</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>
<string name="sim_change_data_title" msgid="9142726786345906606">"ಡೇಟಾ ಸಿಮ್ ಬದಲಾಯಿಸುವುದೇ?"</string>
@@ -466,7 +466,7 @@
<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>
@@ -485,7 +485,7 @@
<string name="simContacts_title" msgid="2714029230160136647">"ಆಮದು ಮಾಡಲು ಸಂಪರ್ಕಗಳು"</string>
<string name="simContacts_airplaneMode" msgid="4654884030631503808">"ಸಿಮ್ ಕಾರ್ಡ್ನಿಂದ ಸಂಪರ್ಕಗಳನ್ನು ಆಮದು ಮಾಡಲು ಏರ್ಪ್ಲೇನ್ ಮೋಡ್ ಆಫ್ ಮಾಡಿ."</string>
<string name="enable_pin" msgid="967674051730845376">"ಸಿಮ್ ಪಿನ್ ಸಕ್ರಿಯಗೊಳಿಸಿ/ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="change_pin" msgid="3657869530942905790">"ಸಿಮ್ ಪಿನ್ ಬದಲಾಯಿಸಿ"</string>
+ <string name="change_pin" msgid="3657869530942905790">"SIM ಪಿನ್ ಬದಲಾಯಿಸಿ"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"ಸಿಮ್ ಪಿನ್:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"ಹಳೆಯ ಪಿನ್"</string>
<string name="newPinLabel" msgid="3585899083055354732">"ಹೊಸ ಪಿನ್"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"ತುರ್ತು ರಹಿತ ಕರೆಯನ್ನು ಮಾಡಲು ತುರ್ತು ಮರು ಕರೆಮಾಡುವಿಕೆ ಮೋಡ್ ಅನ್ನು ನಿರ್ಗಮಿಸಿ."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ನೆಟ್ವರ್ಕ್ನಲ್ಲಿ ಇನ್ನೂ ನೋಂದಣಿಯಾಗಿಲ್ಲ."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿಲ್ಲ."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿಲ್ಲ.\n\nಕರೆ ಮಾಡಲು ವೈರ್ಲೆಸ್ ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿ.\n\nಈ ಸಾಧನದಲ್ಲಿ 2G ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ, ಇದು ನಿಮ್ಮ ಕನೆಕ್ಟಿವಿಟಿ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು. ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ ಮತ್ತು ಮುಂದುವರಿಸಲು 2G ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿಲ್ಲ. ಕರೆ ಮಾಡಲು ವೈರ್ಲೆಸ್ ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿ."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"ಮೊಬೈಲ್ ನೆಟ್ವರ್ಕ್ ಲಭ್ಯವಿಲ್ಲ.\n\nಕರೆ ಮಾಡಲು ವೈರ್ಲೆಸ್ ನೆಟ್ವರ್ಕ್ಗೆ ಕನೆಕ್ಟ್ ಮಾಡಿ.\n\nಈ ಸಾಧನದಲ್ಲಿ 2G ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ, ಇದು ನಿಮ್ಮ ಕನೆಕ್ಟಿವಿಟಿ ಮೇಲೆ ಪರಿಣಾಮ ಬೀರಬಹುದು. ಸೆಟ್ಟಿಂಗ್ಗಳಿಗೆ ಹೋಗಿ ಮತ್ತು ಮುಂದುವರಿಸಲು 2G ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ಕರೆಯನ್ನು ಮಾಡಲು, ಮಾನ್ಯವಾದ ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"ಕರೆ ವಿಫಲವಾಗಿದೆ."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ಈ ಸಮಯದಲ್ಲಿ ಕರೆಯನ್ನು ಸೇರಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಸಂದೇಶವನ್ನು ಕಳುಹಿಸುವ ಮೂಲಕ ನೀವು ಸಂಪರ್ಕಿಸಲು ಪ್ರಯತ್ನಿಸಬಹುದು."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"ಕರೆಗಳನ್ನು ಹೋಲ್ಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ಕರೆ ಮಾಡಲು ವೈರ್ಲೆಸ್ ನೆಟ್ವರ್ಕ್ಗೆ ಸಂಪರ್ಕಿಸಿ."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"ಕರೆ ಮಾಡಲು ವೈ-ಫೈ ಕರೆ ಮಾಡುವಿಕೆಯನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"ಕರೆ ಮಾಡಲು ಸ್ಯಾಟಲೈಟ್ ಮೋಡ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ಕರೆ ಮಾಡಲು, ಮೊದಲು ಸ್ಯಾಟಲೈಟ್ ಕನೆಕ್ಷನ್ ಅನ್ನು ಕೊನೆಗೊಳಿಸಿ."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"ನೀವು ಮೊಬೈಲ್ ಅಥವಾ ವೈ-ಫೈ ನೆಟ್ವರ್ಕ್ ಇಲ್ಲದೆಯೇ ಸಂದೇಶಗಳನ್ನು ಕಳುಹಿಸಬಹುದು ಮತ್ತು ಸ್ವೀಕರಿಸಬಹುದು."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"ತುರ್ತು ಮಾಹಿತಿ"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"ಮಾಲೀಕರು"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"ಮಾಹಿತಿಯನ್ನು ವೀಕ್ಷಿಸಲು ಮತ್ತೆ ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
@@ -598,7 +601,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>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ಸಿಮ್ ವಿಳಾಸ ಪುಸ್ತಕವನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ಸ್ಥಿರ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ಸೇವಾ ಡಯಲಿಂಗ್ ಸಂಖ್ಯೆಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
index 6b403d9..cd705f4 100644
--- a/res/values-ko/strings.xml
+++ b/res/values-ko/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"일반 전화를 걸려면 긴급 콜백 모드를 해제하세요."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"네트워크에서 등록되지 않았습니다."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"모바일 네트워크를 사용할 수 없습니다."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"모바일 네트워크를 사용할 수 없습니다.\n\n전화를 걸려면 무선 네트워크에 연결하세요.\n\n기기에서 2G가 사용 중지되어 있어 연결 상태에 영향을 줄 수 있습니다. 계속하려면 \'설정\'으로 이동하여 \'2G 허용\'을 사용 설정하세요."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"모바일 네트워크를 사용할 수 없습니다. 전화를 걸려면 무선 네트워크에 연결하세요."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"모바일 네트워크를 사용할 수 없습니다.\n\n전화를 걸려면 무선 네트워크에 연결하세요.\n\n이 기기에서 2G가 사용 중지되어 있으므로 연결에 영향을 미칠 수 있습니다. 계속하려면 \'설정\'으로 이동하여 \'2G 허용\'을 사용 설정하세요."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"전화를 걸려면 올바른 번호를 입력하세요."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"전화 연결 실패"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"현재는 통화를 추가할 수 없습니다. 메시지를 보내 연락해 보세요."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"통화를 보류할 수 없습니다."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"전화를 걸려면 무선 네트워크에 연결하세요."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"전화를 걸려면 Wi-Fi 통화를 사용 설정하세요."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"전화를 걸려면 위성 모드를 사용 중지하세요."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"전화를 걸려면 먼저 위성 연결을 종료하세요."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Wi-Fi 또는 모바일 네트워크 없이 메시지를 주고받을 수 있습니다."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"긴급 상황 정보"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"소유자"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"정보를 보려면 다시 탭하세요."</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml
index 3fca1ed..32ffc65 100644
--- a/res/values-ky/strings.xml
+++ b/res/values-ky/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Кадимки шартта чалуу үчүн шашылыш кайра чалуу режиминен чыгыңыз."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Тармакта катталган эмес."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Мобилдик тармак жок."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Мобилдик тармак жеткиликсиз.\n\nЧалуу үчүн зымсыз тармакка туташыңыз.\n\nБул түзмөктө 2G өчүрүлгөндүктөн, байланышка таасирин тийгизиши мүмкүн. Улантуу үчүн параметрлерге өтүп, \"2G тармагына уруксат берүү\" параметрин иштетиңиз."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Мобилдик тармак жеткиликтүү эмес. Чалуу үчүн зымсыз тармакка туташыңыз."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Мобилдик тармак жеткиликсиз.\n\nЧалуу үчүн зымсыз тармакка туташыңыз.\n\nБул түзмөктө 2G өчүрүлгөндүктөн, байланышка таасирин тийгизиши мүмкүн. Улантуу үчүн параметрлерге өтүп, \"2G тармагына уруксат берүү\" параметрин иштетиңиз."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Чалуу үчүн, жарактуу номер киргизиңиз."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Чалынбай калды."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Чалуу бул жолу кошулбай койду. Билдирүү жөнөтүп, байланышсаңыз болот."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Чалууну кармап туруу мүмкүн эмес."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Чалуу үчүн зымсыз тармакка туташыңыз."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Wi-Fi аркылуу чалыңыз."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Чалуу үчүн спутникти өчүрүңүз."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Чалуу үчүн, адегенде спутникке туташыңыз."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Мобилдик же Wi-Fi тармагы жок эле билдирүүлөрдү жөнөтүп, ала аласыз."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Кырсыктаганда керек болчу маалымат"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Ээси"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Маалыматты көрүү үчүн кайра таптап коюңуз"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml
index 10ddb89..ae3767d 100644
--- a/res/values-lo/strings.xml
+++ b/res/values-lo/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"ອອກຈາກໂໝດໂທກັບສຸກເສີນ ເພື່ອເຮັດການໂທປົກກະຕິ."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ບໍ່ໄດ້ລົງທະບຽນໃນເຄືອຂ່າຍ."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"ເຄືອຂ່າຍມືຖືບໍ່ສາມາດໃຊ້ໄດ້."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"ເຄືອຂ່າຍມືຖືບໍ່ມີໃຫ້ໃຊ້.\n\nເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍໄຮ້ສາຍເພື່ອໂທອອກ.\n\n2G ປິດໄວ້ຢູ່ອຸປະກອນນີ້, ເຊິ່ງອາດສົ່ງຜົນຕໍ່ການເຊື່ອມຕໍ່ຂອງທ່ານ. ໄປຫາການຕັ້ງຄ່າ ແລະ ເປີດການນຳໃຊ້ອະນຸຍາດ 2G ເພື່ອສືບຕໍ່."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"ບໍ່ສາມາດໃຊ້ອິນເຕີເນັດມືຖືໄດ້. ກະລຸນາເຊື່ອມຕໍ່ຫາ Wi-Fi ເພື່ອໂທ."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"ເຄືອຂ່າຍມືຖືບໍ່ມີໃຫ້ໃຊ້.\n\nເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍໄຮ້ສາຍເພື່ອໂທອອກ.\n\n2G ປິດໄວ້ຢູ່ອຸປະກອນນີ້, ເຊິ່ງອາດສົ່ງຜົນຕໍ່ການເຊື່ອມຕໍ່ຂອງທ່ານ. ໄປຫາການຕັ້ງຄ່າ ແລະ ເປີດການນຳໃຊ້ອະນຸຍາດ 2G ເພື່ອສືບຕໍ່."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ເພື່ອທີ່ຈະໂທ, ປ້ອນເບີໂທທີ່ໃຊ້ໄດ້ເຂົ້າໄປ."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"ໂທບໍ່ສຳເລັດ."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ບໍ່ສາມາດໂທໄດ້ໃນຕອນນີ້. ທ່ານສາມາດລອງຕິດຕໍ່ຫາໄດ້ໂດຍການສົ່ງຂໍ້ຄວາມ."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"ບໍ່ສາມາດພັກສາຍໄດ້."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ເຊື່ອມຕໍ່ກັບເຄືອຂ່າຍໄຮ້ສາຍເພື່ອເຮັດການໂທ."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"ກະລຸນາເປີດໃຊ້ການໂທ Wi-Fi ເພື່ອໂທ."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"ປິດການນຳໃຊ້ໂໝດດາວທຽມເພື່ອໂທອອກ."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ເພື່ອໂທອອກ, ໃຫ້ສິ້ນສຸດການເຊື່ອມຕໍ່ຜ່ານດາວທຽມກ່ອນ."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"ທ່ານສາມາດສົ່ງ ແລະ ຮັບຂໍ້ຄວາມໂດຍບໍ່ຕ້ອງໃຊ້ເຄືອຂ່າຍມືຖື ຫຼື Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"ຂໍ້ມູນສຸກເສີນ"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"ເຈົ້າຂອງ"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"ແຕະອີກເທື່ອໜຶ່ງເພື່ອເບິ່ງຂໍ້ມູນ"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ເບິ່ງສະໝຸດທີ່ຢູ່ໃນຊິມ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ເບິ່ງໝາຍເລກໂທອອກທີ່ກຳນົດ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ເບິ່ງໝາຍເລກບໍລິການໂທອອກ"</string>
diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml
index 9e1a340..7ad3e77 100644
--- a/res/values-lt/strings.xml
+++ b/res/values-lt/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Jei norite skambinti ne pagalbos numeriu, išjunkite atgalinio skambinimo pagalbos numeriu režimą."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Neregistruota tinkle."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilusis tinklas negalimas."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobiliojo ryšio tinklas nepasiekiamas.\n\nPrisijunkite prie belaidžio ryšio tinklo, kad galėtumėte skambinti.\n\n2G išjungtas šiame įrenginyje, o tai gali paveikti jūsų ryšį. Eikite į skiltį „Nustatymai“ ir įgalinkite funkciją „Leisti 2G“, kad galėtumėte tęsti."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobiliojo ryšio tinklas nepasiekiamas. Prisijunkite prie belaidžio ryšio tinklo, kad galėtumėte skambinti."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobiliojo ryšio tinklas nepasiekiamas.\n\nPrisijunkite prie belaidžio ryšio tinklo, kad galėtumėte skambinti.\n\n2G išjungtas šiame įrenginyje, o tai gali paveikti jūsų ryšį. Eikite į skiltį „Nustatymai“ ir įgalinkite funkciją „Leisti 2G“, kad galėtumėte tęsti."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Kad galėtumėte paskambinti, įveskite tinkamą numerį."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Paskambinti nepavyko."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Šiuo metu skambučio pridėti negalima. Galite pabandyti susisiekti išsiųsdami pranešimą."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Negalima sulaikyti skambučių."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Prisijunkite prie belaidžio ryšio tinklo, kad galėtumėte skambinti."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Įgalinkite „Wi-Fi“ skambinimą, kad galėtumėte skambinti."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Išjunkite satelito režimą, kad galėtumėte skambinti."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Jei norite skambinti, pirmiausia nutraukite palydovinį ryšį."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Galite siųsti ir gauti pranešimus be mobiliojo ryšio ar „Wi-Fi“ tinklo."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Kritinės padėties informacija"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Savininkas"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Palieskite dar kartą, kad peržiūrėtumėte informaciją"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml
index 90165b8..62ae78f 100644
--- a/res/values-lv/strings.xml
+++ b/res/values-lv/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Lai veiktu parastu zvanu, izejiet no ārkārtas atzvana režīma."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Tīklā nav reģistrēts."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilais tīkls nav pieejams."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilais tīkls nav pieejams.\n\nLai veiktu zvanu, izveidojiet savienojumu ar bezvadu tīklu.\n\nŠajā ierīcē ir atspējots 2G, un tas var ietekmēt jūsu savienojamību. Lai turpinātu, pārejiet uz iestatījumiem un iespējojiet opciju “Atļaut 2G”."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilais tīkls nav pieejams. Lai veiktu zvanu, izveidojiet savienojumu ar bezvadu tīklu."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilais tīkls nav pieejams.\n\nLai veiktu zvanu, izveidojiet savienojumu ar bezvadu tīklu.\n\nŠajā ierīcē ir atspējots 2G, un tas var ietekmēt jūsu savienojamību. Lai turpinātu, pārejiet uz iestatījumiem un iespējojiet opciju “Atļaut 2G”."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Lai veiktu zvanu, ievadiet derīgu numuru."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Zvans neizdevās."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Pašlaik nevar pievienot zvanu. Varat mēģināt sūtīt īsziņu."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Nevar aizturēt zvanus."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Lai veiktu zvanu, izveidojiet savienojumu ar bezvadu tīklu."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Lai veiktu zvanu, iespējojiet Wi-Fi zvanus."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Lai zvanītu, atspējojiet satelīta režīmu."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Lai veiktu zvanu, vispirms pārtrauciet savienojumu ar satelītu."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Varat sūtīt un saņemt ziņojumus bez mobilā vai Wi-Fi tīkla."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Ārkārtas informācija"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Īpašnieks"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Pieskarieties vēlreiz, lai skatītu informāciju."</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 0ab1b47..1ed6d0a 100644
--- a/res/values-mk/strings.xml
+++ b/res/values-mk/strings.xml
@@ -318,7 +318,7 @@
<string name="throttle_current_usage" msgid="7483859109708658613">"Податоци кои се користат во тековниот период"</string>
<string name="throttle_time_frame" msgid="1813452485948918791">"Период на потрошен интернет"</string>
<string name="throttle_rate" msgid="7641913901133634905">"Политика на стапка на податоци"</string>
- <string name="throttle_help" msgid="2624535757028809735">"Дознај повеќе"</string>
+ <string name="throttle_help" msgid="2624535757028809735">"Дознајте повеќе"</string>
<string name="throttle_status_subtext" msgid="1110276415078236687">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g> ٪) од максимум <xliff:g id="USED_2">%3$s</xliff:g> за периодот\nСледниот период започнува за <xliff:g id="USED_3">%4$d</xliff:g> дена (<xliff:g id="USED_4">%5$s</xliff:g>)"</string>
<string name="throttle_data_usage_subtext" msgid="3185429653996709840">"<xliff:g id="USED_0">%1$s</xliff:g> (<xliff:g id="USED_1">%2$d</xliff:g>٪) од <xliff:g id="USED_2">%3$s</xliff:g> максимален период"</string>
<string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> максимум е надминат\nСтапката на податоци е намалена на <xliff:g id="USED_1">%2$d</xliff:g> Kb/s"</string>
@@ -485,8 +485,8 @@
<string name="simContacts_title" msgid="2714029230160136647">"Избери контакти за увоз"</string>
<string name="simContacts_airplaneMode" msgid="4654884030631503808">"Исклучете го авионскиот режим за да ги увезете контактите од SIM-картичката."</string>
<string name="enable_pin" msgid="967674051730845376">"Овозможи/оневозможи PIN на SIM"</string>
- <string name="change_pin" msgid="3657869530942905790">"Промени PIN на SIM"</string>
- <string name="enter_pin_text" msgid="3182311451978663356">"PIN на SIM:"</string>
+ <string name="change_pin" msgid="3657869530942905790">"Променете PIN за SIM-картичката"</string>
+ <string name="enter_pin_text" msgid="3182311451978663356">"PIN за SIM-картичката:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"Стар PIN"</string>
<string name="newPinLabel" msgid="3585899083055354732">"Нов PIN"</string>
<string name="confirmPinLabel" msgid="7783531218662473778">"Потврди нов PIN"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Излезете од режимот на итен повратен повик за да направите обичен повик."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Не е регистриран на мрежа."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Не е достапна мобилна мрежа."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Мобилната мрежа не е достапна.\n\nПоврзете се на безжична мрежа за да остварите повик.\n\n2G е оневозможено на уредов, а тоа може да влијае врз поврзливоста. Одете во „Поставки“ и овозможете ја опцијата „Дозволи 2G“ за да продолжите."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Не е достапна мобилна мрежа. Поврзете се на безжична мрежа за да повикате."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Мобилната мрежа не е достапна.\n\nПоврзете се на безжична мрежа за да остварите повик.\n\n2G е оневозможено на уредов, а тоа може да влијае врз поврзливоста. Одете во „Поставки“ и овозможете ја опцијата „Дозволи 2G“ за да продолжите."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"За да повикате, внесете важечки број."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Повикот не успеа."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Повикот не може да се додаде во моментов. Може да се обидете да стапите во контакт со испраќање порака."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Не може да се задржат повици."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Поврзете се на безжична мрежа за да повикате."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Овозможете повикување преку Wi-Fi за воспоставување повик."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Исклучете го режимот на сателит за да упатите повик."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"За да воспоставите повик, прво завршете ја сателитската врска."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Може да испраќате и примате пораки без мобилна или Wi-Fi мрежа."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Податоци за итни случаи"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Сопственик"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Допрете повторно за приказ на информации"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml
index b0785bb..32b93bb 100644
--- a/res/values-ml/strings.xml
+++ b/res/values-ml/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"അടിയന്തിരമല്ലാത്ത കോൾ ചെയ്യാൻ അടിയന്തിര കോൾബാക്ക് മോഡിൽ നിന്ന് പുറത്തുകടക്കുക."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"നെറ്റ്വർക്കിൽ രജിസ്റ്റർ ചെയ്തിട്ടില്ല."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"മൊബൈൽ നെറ്റ്വർക്ക് ലഭ്യമല്ല."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"മൊബൈൽ നെറ്റ്വർക്ക് ലഭ്യമല്ല.\n\nകോൾ ചെയ്യാൻ ഒരു വയർലെസ് നെറ്റ്വർക്കിലേക്ക് കണക്റ്റ് ചെയ്യുക.\n\nഈ ഉപകരണത്തിൽ 2G പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു, അത് നിങ്ങളുടെ കണക്റ്റിവിറ്റിയെ ബാധിച്ചേക്കാം. തുടരാൻ, ക്രമീകരണത്തിലേക്ക് പോയി 2G അനുവദിക്കുക പ്രവർത്തനക്ഷമമാക്കുക."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"മൊബൈൽ നെറ്റ്വർക്ക് ലഭ്യമല്ല. കോൾ വിളിക്കാൻ വയർലെസ്സ് നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്യുക."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"മൊബൈൽ നെറ്റ്വർക്ക് ലഭ്യമല്ല.\n\nകോൾ ചെയ്യാൻ ഒരു വയർലെസ് നെറ്റ്വർക്കിലേക്ക് കണക്റ്റ് ചെയ്യുക.\n\nഈ ഉപകരണത്തിൽ 2G പ്രവർത്തനരഹിതമാക്കിയിരിക്കുന്നു, അത് നിങ്ങളുടെ കണക്റ്റിവിറ്റിയെ ബാധിച്ചേക്കാം. തുടരാൻ, ക്രമീകരണത്തിലേക്ക് പോയി 2G അനുവദിക്കുക പ്രവർത്തനക്ഷമമാക്കുക."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ഒരു കോൾ ചെയ്യുന്നതിന്, സാധുതയുള്ള നമ്പർ നൽകുക."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"കോൾ ചെയ്യാനായില്ല."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ഇപ്പോൾ കോൾ ചേർക്കാനാവില്ല. നിങ്ങൾക്കൊരു സന്ദേശമയച്ചുകൊണ്ട് ബന്ധപ്പെടാൻ ശ്രമിക്കാം."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"കോളുകൾ ഹോൾഡുചെയ്യാൻ കഴിയില്ല."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ഒരു കോൾ വിളിക്കാൻ വയർലെസ്സ് നെറ്റ്വർക്കിലേക്ക് കണക്റ്റുചെയ്യുക."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"കോൾ ചെയ്യാൻ Wi-Fi കോളിംഗ് പ്രവർത്തനക്ഷമമാക്കുക."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"കോൾ ചെയ്യാൻ സാറ്റലൈറ്റ് മോഡ് പ്രവർത്തനരഹിതമാക്കുക."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ഒരു കോൾ ചെയ്യുന്നതിന്, ആദ്യം സാറ്റലൈറ്റ് കണക്ഷൻ അവസാനിപ്പിക്കുക."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"മൊബൈൽ അല്ലെങ്കിൽ വൈഫൈ നെറ്റ്വർക്ക് ഇല്ലാതെ തന്നെ നിങ്ങൾക്ക് സന്ദേശങ്ങൾ അയയ്ക്കാനും സ്വീകരിക്കാനും കഴിയും."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"അടിയന്തര വിവരം"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"ഉടമ"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"വിവരങ്ങൾ കാണാൻ വീണ്ടും ടാപ്പ് ചെയ്യുക"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"സിം വിലാസ പുസ്തകം കാണുക"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"സ്ഥിര ഡയലിംഗ് നമ്പറുകൾ കാണുക"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"സർവീസ് ഡയലിംഗ് നമ്പറുകൾ കാണുക"</string>
diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml
index 712042a..1d85926 100644
--- a/res/values-mn/strings.xml
+++ b/res/values-mn/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Яаралтай түргэн тусламжийн бус дуудлага хийхийн тулд яаралтай түргэн тусламжийн callback горимоос гарна уу."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Сүлжээнд бүртгэгдээгүй."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Мобайль сүлжээ байхгүй."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Мобайл сүлжээ боломжгүй байна.\n\nДуудлага хийхийн тулд утасгүй сүлжээнд холбогдоно уу.\n\n2G-г энэ төхөөрөмж дээр идэвхгүй болгосон бөгөөд энэ нь таны холболтод нөлөөлж байж магадгүй. Үргэлжлүүлэхийн тулд Тохиргоо руу очоод, 2G-г зөвшөөрөхийг идэвхжүүлнэ үү."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Мобайл сүлжээнд холбогдох боломжгүй байна. Дуудлага хийхийн тулд утасгүй интернетэд холбогдоно уу."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Мобайл сүлжээ боломжгүй байна.\n\nДуудлага хийхийн тулд утасгүй сүлжээнд холбогдоно уу.\n\n2G-г энэ төхөөрөмж дээр идэвхгүй болгосон бөгөөд энэ нь таны холболтод нөлөөлж байж магадгүй. Үргэлжлүүлэхийн тулд Тохиргоо руу очоод, 2G-г зөвшөөрөхийг идэвхжүүлнэ үү."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Дуудлага хийхийн тулд хүчин төгөлдөр дугаар оруулна уу."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Дуудлага амжилтгүй болсон."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Дуудлагыг энэ удаад нэмэх боломжгүй. Та мессеж илгээн холбоо тогтоохыг оролдох боломжтой."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Дуудлагыг хадгалах боломжгүй байна."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Дуудлага хийхийн тулд утасгүй интернетэд холбогдоно уу."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Дуудлага хийхийн тулд Wi-Fi дуудлагыг идэвхжүүлнэ үү."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Дуудлага хийхийн тулд хиймэл дагуулын горимыг идэвхгүй болгоно уу."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Дуудлага хийхийн тулд эхлээд хиймэл дагуулын холболтыг дуусгана уу."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Та мобайл эсвэл Wi-Fi сүлжээгүйгээр мессеж илгээх болон хүлээн авах боломжтой."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Яаралтай тусламжийн мэдээлэл"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Эзэмшигч"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Мэдээллийг үзэхийн тулд дахин товшино уу"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml
index 76dee50..e4d903c 100644
--- a/res/values-mr/strings.xml
+++ b/res/values-mr/strings.xml
@@ -296,7 +296,7 @@
<string name="limited_sim_function_with_phone_num_notification_message" msgid="5928988883403677610">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> चे कॉल आणि डेटा सेवा <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> चे कॉल आणि डेटा सेवा दुसरे सिम वापरताना ब्लॉक केले जाऊ शकतात."</string>
<string name="sip_accounts_removed_notification_title" msgid="3528076957535736095">"आढळलेली आणि काढून टाकलेली कालबाह्य झालेली SIP खाती"</string>
- <string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Android प्लॅटफॉर्मवर आता SIP कॉलिंगला सपोर्ट नाही.\nतुमची अस्तित्वात असलेली SIP खाती <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> काढून टाकली आहेत.\nकृपया तुमच्या कॉलिंगसंबंधित डीफॉल्ट खात्याचे सेटिंग कंफर्म करा."</string>
+ <string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Android प्लॅटफॉर्मवर आता SIP कॉलिंगला सपोर्ट नाही.\nतुमची अस्तित्वात असलेली SIP खाती <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> काढून टाकली आहेत.\nकृपया तुमच्या कॉलिंगसंबंधित डीफॉल्ट खात्याचे सेटिंग कन्फर्म करा."</string>
<string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"सेटिंग्जवर जा"</string>
<string name="data_usage_title" msgid="8438592133893837464">"अॅप डेटा वापर"</string>
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_2">%2$s</xliff:g> दरम्यान <xliff:g id="ID_1">%1$s</xliff:g> मोबाइल डेटा वापरला गेला"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"आणीबाणी नसलेला कॉल करण्यासाठी आणीबाणी कॉलबॅक मोडमधून बाहेर पडा."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"नेटवर्कवर नोंदणीकृत नाही."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"मोबाइल नेटवर्क उपलब्ध नाही."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"मोबाइल नेटवर्क उपलब्ध नाही. \n\nकॉल करण्यासाठी वायरलेस नेटवर्कशी कनेक्ट करा.\n\nया डिव्हाइसवर 2G बंद केले आहे, ज्यामुळे तुमच्या कनेक्टिव्हिटीवर परिणाम होत असेल. सेटिंग्ज वर जा आणि पुढे सुरू ठेवण्यासाठी 2G सुरू करा."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"मोबाइल नेटवर्क उपलब्ध नाही. कॉल करण्यासाठी वायरलेस नेटवर्कशी कनेक्ट करा."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"मोबाइल नेटवर्क उपलब्ध नाही. \n\nकॉल करण्यासाठी वायरलेस नेटवर्कशी कनेक्ट करा.\n\nया डिव्हाइसवर 2G बंद केले आहे, ज्यामुळे तुमच्या कनेक्टिव्हिटीवर परिणाम होत असेल. सेटिंग्ज वर जा आणि पुढे सुरू ठेवण्यासाठी 2G सुरू करा."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"कॉल करण्यासाठी, एक वैध नंबर एंटर करा."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"कॉल अयशस्वी झाला."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"या वेळी कॉल जोडू शकत नाही. तुम्ही मेसेज पाठवून संपर्क करण्याचा प्रयत्न करू शकता."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"कॉल सुरू ठेवू शकत नाही."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"कॉल करण्यासाठी वायरलेस नेटवर्कशी कनेक्ट करा."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"कॉल करण्यासाठी वाय-फाय कॉलिंग सक्षम करा."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"कॉल करण्यासाठी उपग्रह मोड बंद करा."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"कॉल करण्यासाठी, सर्वप्रथम उपग्रह कनेक्शन बंद करा."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"तुम्ही मोबाइल किंवा वाय-फाय नेटवर्कशिवाय मेसेज पाठवू आणि मिळवू शकता."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"अतिमहत्त्वाची माहिती"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"मालक"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"माहिती पाहण्यासाठी पुन्हा टॅप करा"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"सिम ॲड्रेस बुक पहा"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"निश्चित डायलिंग नंबर पहा"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"सर्व्हिस डायलिंग नंबर पहा"</string>
@@ -876,7 +881,7 @@
<string name="radio_info_dds" msgid="1122593144425697126">"डीफॉल्ट डेटा सिम SubId:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL बँडविड्थ (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL बँडविड्थ (kbps):"</string>
- <string name="radio_info_phy_chan_config" msgid="608045501232211303">"प्रत्यक्ष चॅनलची कॉंफिगरेशन:"</string>
+ <string name="radio_info_phy_chan_config" msgid="608045501232211303">"प्रत्यक्ष चॅनलची कॉन्फिगरेशन:"</string>
<string name="radio_info_cell_info_refresh_rate" msgid="670511448975997340">"सेल माहिती रिफ्रेश रेट:"</string>
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"सर्व सेल परिमाण माहिती:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"डेटा सर्व्हिस:"</string>
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index 18b47c2..ade76f7 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Keluar daripada mod panggil balik kecemasan untuk membuat panggilan bukan kecemasan."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Tidak didaftarkan pada rangkaian."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Rangkaian mudah alih tidak tersedia."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Rangkaian mudah alih tidak tersedia.\n\nBuat sambungan kepada rangkaian wayarles untuk membuat panggilan.\n\n2G dilumpuhkan pada peranti ini, yang mungkin menjejaskan kesambungan anda. Akses Tetapan dan dayakan Benarkan 2G untuk meneruskan kesambungan."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Rangkaian selular tidak tersedia. Sambung ke rangkaian wayarles untuk membuat panggilan."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Rangkaian mudah alih tidak tersedia.\n\nSambungkan kepada rangkaian wayarles untuk membuat panggilan.\n\n2G dilumpuhkan pada peranti ini, yang mungkin menjejaskan kesambungan anda. Akses Tetapan dan dayakan Benarkan 2G untuk meneruskan kesambungan."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Untuk membuat panggilan, masukkan nombor yang sah."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Panggilan gagal."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Panggilan tidak dapat ditambahkan pada masa ini. Anda boleh cuba menghantar mesej untuk berhubung."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Tidak dapat menunda panggilan."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Sambungkan ke rangkaian wayarles untuk membuat panggilan."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Dayakan panggilan Wi-Fi untuk membuat panggilan."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Lumpuhkan mod satelit untuk membuat panggilan."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Untuk membuat panggilan, tamatkan sambungan satelit dahulu."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Anda boleh menghantar dan menerima mesej tanpa rangkaian mudah alih atau Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Maklumat kecemasan"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Pemilik"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Ketik lagi untuk melihat maklumat"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 8576e1f..9ccd3df 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"အရေးပေါ် မဟုတ်သည့် ခေါ်ဆိုမှုကို ပြုလုပ်ရန် အရေးပေါ် ဖုန်းခေါ်မှုမှ ထွက်ပါ။"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ကွန်ယက်ပေါ်မှာ မှတ်ပုံတင်မှု မပြုလုပ်ထားပါ"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"မိုဘိုင်းကွန်ယက်များ မရှိပါ"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"မိုဘိုင်းကွန်ရက် မရနိုင်ပါ။\n\nဖုန်းခေါ်ရန် ကြိုးမဲ့ကွန်ရက်သို့ ချိတ်ဆက်ပါ။\n\nဤစက်တွင် 2G ကိုပိတ်ထားပြီး ၎င်းက သင့်ချိတ်ဆက်နိုင်မှုအပေါ် သက်ရောက်နိုင်သည်။ ဆက်တင်များသို့သွားပြီး ရှေ့ဆက်ရန် 2G ကိုခွင့်ပြုပါ။"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"မိုဘိုင်းကွန်ရက် မရနိုင်ပါ။ ခေါ်ဆိုမှုပြုလုပ်ရန် ကြိုးမဲ့ကွန်ရက်သို့ ချိတ်ဆက်လိုက်ပါ။"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"မိုဘိုင်းကွန်ရက် မရနိုင်ပါ။\n\nဖုန်းခေါ်ရန် ကြိုးမဲ့ကွန်ရက်သို့ ချိတ်ဆက်ပါ။\n\nဤစက်တွင် 2G ကိုပိတ်ထားပြီး ၎င်းက သင့်ချိတ်ဆက်နိုင်မှုအပေါ် သက်ရောက်နိုင်သည်။ ဆက်တင်များသို့သွားပြီး ရှေ့ဆက်ရန် 2G ကိုခွင့်ပြုပါ။"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ဖုန်းခေါ်ရန်အတွက်၊ သင့်လျော်သည့်နံပါတ် ရိုက်ထည့်ပါ။"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"ခေါ်ဆို၍ မရပါ။"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ယခုအချိန်တွင် ခေါ်ဆိုမှု ထပ်မထည့်နိုင်ပါ။ မက်ဆေ့ဂျ်ပို့ဆောင်ခြင်းဖြင့်လည်း ဆက်သွယ်ရန်ကြိုးစားနိုင်ပါသည်။"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"ခေါ်ဆိုမှုများကို ကိုင်ထား၍မရပါ။"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ဖုန်းခေါ်ရန် ကြိုးမဲကွန်ယက်တစ်ခုသို့ ချိတ်ဆက်ပါ။"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"ဖုန်းဆက်ရန် Wi-Fi ခေါ်ဆိုခြင်းကို ဖွင့်ပါ။"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"ဖုန်းခေါ်ရန် ဂြိုဟ်တုမုဒ် ပိတ်ပါ။"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ဖုန်းခေါ်ရန်အတွက် ဂြိုဟ်တုချိတ်ဆက်မှုကို အရင်ဖြုတ်ပါ။"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"မိုဘိုင်း (သို့) Wi-Fi ကွန်ရက်မရှိဘဲ မက်ဆေ့ဂျ်များကို ပို့နိုင်၊ လက်ခံနိုင်သည်။"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"အရေးပေါ် အချက်အလက်"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"ပိုင်ရှင်"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"အချက်အလက်ကြည့်ရန် ထပ်နှိပ်ပါ"</string>
@@ -674,8 +677,8 @@
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"အရေးပေါ် ခေါ်ဆိုမှုသာလျှင်"</string>
<string name="sim_description_default" msgid="7474671114363724971">"SIM ကတ်၊ အပေါက်: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"အများသုံးနိုင်မှု"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"အောက်ပါမှ Wi-Fi ခေါ်ခြင်း"</string>
- <string name="status_hint_label_wifi_call" msgid="942993035689809853">"ဝိုင်ဖိုင်ခေါ်ဆိုမှု"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"Wi-Fi ဖုန်းခေါ်နေသည်"</string>
+ <string name="status_hint_label_wifi_call" msgid="942993035689809853">"Wi-Fi ခေါ်ဆိုမှု"</string>
<string name="message_decode_error" msgid="1061856591500290887">"စာကို ကုဒ်ဖွင့်နေစဉ် အမှားရှိခဲ့သည်။"</string>
<string name="callFailed_cdma_activation" msgid="5392057031552253550">"SIM ကဒ်သည် သင့် ဖုန်းဝန်ဆောင်မှုအား အသက်သွင်းခဲ့ပြီး သင့်ဖုန်း၏ ကွန်ယက်ပြင်ပဒေတာသုံးနိုင်စွမ်းအား ပြင်ဆင်မွမ်းမံပြီးဖြစ်၏။"</string>
<string name="callFailed_cdma_call_limit" msgid="1074219746093031412">"လက်ရှိခေါ်ဆိုမှုများ အလွန်များနေပါသည်။ ခေါ်ဆိုမှုအသစ်တစ်ခု မပြုလုပ်ခင် လက်ရှိဖုန်းခေါ်ဆိုမှုများကို အဆုံးသတ် (သို့) ပေါင်း လိုက်ပါ။"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
index fb8a4fe..2e54a23 100644
--- a/res/values-nb/strings.xml
+++ b/res/values-nb/strings.xml
@@ -542,7 +542,9 @@
<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>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilnettverk er ikke tilgjengelig.\n\nKoble til et trådløst nettverk for å ringe.\n\n2G er deaktivert på denne enheten – dette kan påvirke tilkoblingen. Gå til Innstillinger og aktiver «Tillat 2G» for å fortsette."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilnettverk er ikke tilgjengelig. Koble til et trådløst nettverk for å ringe."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilnettverk er ikke tilgjengelig.\n\nKoble til et trådløst nettverk for å ringe.\n\n2G er deaktivert på denne enheten – dette kan påvirke tilkoblingen. Gå til Innstillinger og aktiver «Tillat 2G» for å fortsette."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Skriv inn et gyldig nummer for å plassere en samtale."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Anropet mislyktes."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Kan ikke legge til anropet akkurat nå. Du kan prøve å ta kontakt ved å sende en melding."</string>
@@ -557,7 +559,8 @@
<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 Wifi for å ringe."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Slå av satellittmodus for å ringe."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Du må avslutte satellittilkoblingen før du kan ringe."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Du kan sende og motta meldinger uten mobil- eller wifi-nettverk"</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>
@@ -841,6 +844,8 @@
<string name="removable_esim_string" msgid="7931369811671787649">"Angi flyttbart eSIM-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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml
index 1b399ab..ebf09e7 100644
--- a/res/values-ne/strings.xml
+++ b/res/values-ne/strings.xml
@@ -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>
@@ -187,9 +187,9 @@
<string name="manual_mode_disallowed_summary" msgid="3970048592179890197">"%1$s मा जडान हुँदा उपलब्ध छैन"</string>
<string name="network_select_title" msgid="4117305053881611988">"नेटवर्क"</string>
<string name="register_automatically" msgid="3907580547590554834">"स्वतः दर्ता..."</string>
- <string name="preferred_network_mode_title" msgid="5253395265169539830">"रुचाइएको सञ्जाल प्रकार"</string>
+ <string name="preferred_network_mode_title" msgid="5253395265169539830">"रुचाइएको नेटवर्कको प्रकार"</string>
<string name="preferred_network_mode_summary" msgid="3787989000044330064">"नेटवर्क संचालन मोड परिवर्तन गर्नुहोस्"</string>
- <string name="preferred_network_mode_dialogtitle" msgid="2781447433514459696">"रुचाइएको सञ्जाल प्रकार"</string>
+ <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>
@@ -298,7 +298,7 @@
<string name="sip_accounts_removed_notification_title" msgid="3528076957535736095">"चल्तीबाट हटाइएका SIP खाताहरू भेट्टाइयो र हटाइयो"</string>
<string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"अबदेखि Android प्लेटफर्ममा SIP कल गर्न मिल्दैन।\nतपाईंका हालका SIP खाताहरू <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> हटाइएका छन्।\nकृपया आफ्नो डिफल्ट कल गर्ने खाताको सेटिङ पुष्टि गर्नुहोस्।"</string>
<string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"सेटिङमा जानुहोस्"</string>
- <string name="data_usage_title" msgid="8438592133893837464">"अनुप्रयोगले गरेको डेटाको प्रयोग"</string>
+ <string name="data_usage_title" msgid="8438592133893837464">"एपले गरेको डेटाको प्रयोग"</string>
<string name="data_usage_template" msgid="6287906680674061783">"<xliff:g id="ID_2">%2$s</xliff:g> सम्म <xliff:g id="ID_1">%1$s</xliff:g> मोबाइल डेटा प्रयोग भयो"</string>
<string name="advanced_options_title" msgid="9208195294513520934">"उन्नत"</string>
<string name="carrier_settings_euicc" msgid="1190237227261337749">"सेवा प्रदायक"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"गैर-आपत्कालीन कल गर्न आपत्कालीन कलब्याक मोडबाट निस्कनुहोस्।"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"नेटवर्कमा दर्ता भएको छैन।"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"मोबाइल नेटवर्क उपलब्ध छैन।"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"मोबाइल नेटवर्क उपलब्ध छैन।\n\nकल गर्न वायरलेस नेटवर्कमा कनेक्ट गर्नुहोस्।\n\nयो डिभाइसमा 2G नेटवर्क अफ गरिएको छ, यसै कारणले तपाईंको कनेक्टिभिटी प्रभावित भएको हुन सक्छ। सेटिङमा जानुहोस् र जारी राख्नका निम्ति 2G प्रयोग गर्ने अनुमति दिनुहोस्।"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"मोबाइल नेटवर्क उपलब्ध छैन। कल गर्न तारविनाको नेटवर्कमा कनेक्ट गर्नुहोस्।"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"मोबाइल नेटवर्क उपलब्ध छैन।\n\nकल गर्न वायरलेस नेटवर्कमा कनेक्ट गर्नुहोस्।\n\nयो डिभाइसमा 2G अफ गरिएको छ, यसै कारणले तपाईंको कनेक्टिभिटी प्रभावित भएको हुन सक्छ। सेटिङमा जानुहोस् र जारी राख्नका निम्ति 2G प्रयोग गर्ने अनुमति दिनुहोस्।"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"एक कल गर्नको लागि, एक वैध नम्बर प्रविष्टि गर्नुहोस्।"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"कल विफल भयो।"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"यतिबेला कल गर्न सकिएन। तपाईंले कुनै सन्देश पठाएर सम्पर्क गर्ने प्रयास गर्न सक्नुहुन्छ।"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"कल सञ्चालन गर्न सकिँदैन।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"एक कल गर्न एक ताररहितको सञ्जालमा कनेक्ट गर्नुहोस्।"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"कल गर्नका लागि Wi-Fi कलिङ सक्षम गर्नुहोस्।"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"कल गर्न स्याटेलाइट मोड अफ गर्नुहोस्।"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"कल गर्न सर्वप्रथम स्याटलाइट कनेक्सन अन्त्य गर्नुहोस्।"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"तपाईं मोबाइल वा Wi-Fi नेटवर्कविनै म्यासेज पठाउन र प्राप्त गर्न सक्नुहुन्छ।"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"आपत्कालीन जानकारी"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"मालिक"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"जानकारी हेर्न पुनः ट्याप गर्नुहोस्"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-night/styles.xml b/res/values-night/styles.xml
index f7d831b..9774396 100644
--- a/res/values-night/styles.xml
+++ b/res/values-night/styles.xml
@@ -25,6 +25,11 @@
<item name="android:navigationBarDividerColor">@color/dialer_divider_color</item>
<item name="android:colorAccent">@color/dialer_theme_color</item>
<item name="android:dialogTheme">@style/DialerAlertDialogTheme</item>
+
+ <!--
+ TODO(b/309578419): Make activities handle insets properly and then remove this.
+ -->
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
</style>
<style name="EmergencyInfoNameTextAppearance"
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
index da89764..2f84556 100644
--- a/res/values-nl/strings.xml
+++ b/res/values-nl/strings.xml
@@ -485,7 +485,7 @@
<string name="simContacts_title" msgid="2714029230160136647">"Contacten selecteren om te importeren"</string>
<string name="simContacts_airplaneMode" msgid="4654884030631503808">"Zet de vliegtuigmodus uit om contacten van de simkaart te importeren."</string>
<string name="enable_pin" msgid="967674051730845376">"SIM pincode aan-/uitzetten"</string>
- <string name="change_pin" msgid="3657869530942905790">"Pincode simkaart wijzigen"</string>
+ <string name="change_pin" msgid="3657869530942905790">"Pincode van simkaart wijzigen"</string>
<string name="enter_pin_text" msgid="3182311451978663356">"Pincode simkaart:"</string>
<string name="oldPinLabel" msgid="8618515202411987721">"Oude pincode"</string>
<string name="newPinLabel" msgid="3585899083055354732">"Nieuwe pincode"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Sluit de modus voor noodoproepen af om een niet-noodoproep te plaatsen."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Niet geregistreerd op netwerk."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobiel netwerk niet beschikbaar."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobiel netwerk niet beschikbaar.\n\nMaak verbinding met een draadloos netwerk om te bellen.\n\n2G is uitgezet op dit apparaat. Dit kan gevolgen hebben voor je connectiviteit. Ga naar Instellingen en zet 2G toestaan aan om door te gaan."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobiel netwerk is niet beschikbaar. Maak verbinding met een draadloos netwerk om te bellen."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobiel netwerk is niet beschikbaar.\n\nMaak verbinding met een draadloos netwerk om te bellen.\n\n2G staat uit op dit apparaat. Dit kan gevolgen hebben voor je connectiviteit. Ga naar Instellingen en zet 2G toestaan aan om door te gaan."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Als je wilt bellen, moet je een geldig nummer invoeren."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Gesprek mislukt."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Gesprek kan op dit moment niet worden toegevoegd. Je kunt contact opnemen door een bericht te sturen."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Kan gesprekken niet in de wacht zetten."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Maak verbinding met een draadloos netwerk om te bellen."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Zet bellen via wifi aan om te bellen."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Zet de satellietmodus uit om te bellen."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Als je wilt bellen, moet je eerst de satellietverbinding beëindigen."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Je kunt berichten sturen en krijgen zonder een mobiel of wifi-netwerk."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Noodinformatie"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Eigenaar"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tik nogmaals om informatie te bekijken"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 5eea570..ac72cf2 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -19,7 +19,7 @@
<string name="phoneAppLabel" product="tablet" msgid="1916019789885839910">"ମୋବାଇଲ୍ ଡାଟା"</string>
<string name="phoneAppLabel" product="default" msgid="130465039375347763">"ଫୋନ୍ ସେବା"</string>
<string name="emergencyDialerIconLabel" msgid="8668005772339436680">"ଜରୁରୀକାଳିନ ଡାଏଲର୍"</string>
- <string name="phoneIconLabel" msgid="3015941229249651419">"ଫୋନ୍"</string>
+ <string name="phoneIconLabel" msgid="3015941229249651419">"ଫୋନ"</string>
<string name="fdnListLabel" msgid="4119121875004244097">"FDN ତାଲିକା"</string>
<string name="unknown" msgid="8279698889921830815">"ଅଜଣା"</string>
<string name="private_num" msgid="4487990167889159992">"ବ୍ୟକ୍ତିଗତ ନମ୍ବର୍"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"ଗୋଟିଏ ସାଧାରଣ କଲ୍ କରିବା ପାଇଁ ଜରୁରିକାଳୀନ କଲବ୍ୟାକ୍ ମୋଡ୍ରୁ ବାହାରି ଆସନ୍ତୁ।"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ନେଟ୍ୱର୍କରେ ପଞ୍ଜୀକୃତ କରାଯାଇନାହିଁ।"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"ମୋବାଇଲ୍ ନେଟ୍ୱର୍କ ଉପଲବ୍ଧ ନାହିଁ।"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"ମୋବାଇଲ ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ।\n\nଏକ କଲ କରିବାକୁ ଗୋଟିଏ ୱେୟାରଲେସ ନେଟୱାର୍କ ସହ କନେକ୍ଟ କରନ୍ତୁ।\n\nଏହି ଡିଭାଇସରେ 2Gକୁ ଅକ୍ଷମ କରାଯାଇଛି, ଯାହା ଆପଣଙ୍କ କନେକ୍ଟିଭିଟିକୁ ପ୍ରଭାବିତ କରୁଥାଇପାରେ। ଜାରି ରଖିବା ପାଇଁ ସେଟିଂସକୁ ଯାଇ \'2Gକୁ ଅନୁମତି ଦିଅନ୍ତୁ\'କୁ ସକ୍ଷମ କରନ୍ତୁ।"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"ମୋବାଇଲ୍ ନେଟ୍ୱର୍କ ଉପଲବ୍ଧ ନାହିଁ। କଲ୍ କରିବା ପାଇଁ ଗୋଟିଏ ତାରବିହୀନ ନେଟ୍ୱର୍କରେ କନେକ୍ଟ କରନ୍ତୁ"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"ମୋବାଇଲ ନେଟୱାର୍କ ଉପଲବ୍ଧ ନାହିଁ।\n\nଏକ କଲ କରିବାକୁ ଗୋଟିଏ ୱେୟାରଲେସ ନେଟୱାର୍କ ସହ କନେକ୍ଟ କରନ୍ତୁ।\n\nଏହି ଡିଭାଇସରେ 2Gକୁ ଅକ୍ଷମ କରାଯାଇଛି, ଯାହା ଆପଣଙ୍କ କନେକ୍ଟିଭିଟିକୁ ପ୍ରଭାବିତ କରୁଥାଇପାରେ। ଜାରି ରଖିବା ପାଇଁ ସେଟିଂସକୁ ଯାଇ \'2Gକୁ ଅନୁମତି ଦିଅନ୍ତୁ\'କୁ ସକ୍ଷମ କରନ୍ତୁ।"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ଗୋଟିଏ କଲ୍ କରିବା ପାଇଁ ଏକ ବୈଧ ନମ୍ବର୍ ପ୍ରବେଶ କରନ୍ତୁ।"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"କଲ୍ ହେଲା ନାହିଁ।"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ଏବେ କଲ୍କୁ ଯୋଡ଼ାଯାଇପାରିବ ନାହିଁ। ଆପଣ ମେସେଜ୍ ପଠାଇ ସମ୍ପର୍କ କରିବା ପାଇଁ ଚେଷ୍ଟା କରିପାରନ୍ତି।"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"କଲ୍କୁ ହୋଲ୍ଡ କରାଯାଇପାରିବ ନାହିଁ।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ଗୋଟିଏ କଲ୍ କରିବା ପାଇଁ ଏକ ତାରବିହୀନ ନେଟ୍ୱର୍କ ସହ କନେକ୍ଟ କରନ୍ତୁ।"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"ଗୋଟିଏ କଲ୍ କରିବା ପାଇଁ ୱାଇ-ଫାଇ କଲିଙ୍ଗକୁ ସକ୍ଷମ କରନ୍ତୁ।"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"ଏକ କଲ କରିବା ପାଇଁ ସେଟେଲାଇଟ ମୋଡକୁ ଅକ୍ଷମ କରନ୍ତୁ।"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ଏକ କଲ କରିବାକୁ ପ୍ରଥମେ ସେଟେଲାଇଟ କନେକ୍ସନ ସମାପ୍ତ କରନ୍ତୁ।"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"ଏକ ମୋବାଇଲ କିମ୍ବା ୱାଇ-ଫାଇ ନେଟୱାର୍କ ବିନା ଆପଣ ମେସେଜ ପଠାଇପାରିବେ ଏବଂ ପାଇପାରିବେ।"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"ଜରୁରୀକାଳୀନ ସୂଚନା"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"ମାଲିକ"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"ସୂଚନା ଦେଖିବାକୁ ପୁଣିଥରେ ଟାପ୍ କରନ୍ତୁ"</string>
@@ -674,8 +677,8 @@
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"କେବଳ ଜରୁରିକାଳୀନ କଲ୍ ପାଇଁ"</string>
<string name="sim_description_default" msgid="7474671114363724971">"SIM କାର୍ଡ, ସ୍ଲଟ୍: <xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"ଆକ୍ସେସିବିଲିଟୀ"</string>
- <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"ଠାରୁ ୱାଇ-ଫାଇ କଲ୍ କରନ୍ତୁ"</string>
- <string name="status_hint_label_wifi_call" msgid="942993035689809853">"ୱାଇ-ଫାଇ କଲ୍"</string>
+ <string name="status_hint_label_incoming_wifi_call" msgid="2606052595898044071">"ୱାଇ-ଫାଇ କଲ କରିଛନ୍ତି"</string>
+ <string name="status_hint_label_wifi_call" msgid="942993035689809853">"ୱାଇ-ଫାଇ କଲ"</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>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ସିମ୍ରେ ଥିବା ଠିକଣା ପୁସ୍ତକ ଦେଖନ୍ତୁ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ସ୍ଥାୟୀ ଡାଏଲିଂ ନମ୍ୱରଗୁଡ଼ିକୁ ଦେଖନ୍ତୁ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ସର୍ଭିସ୍ ଡାଏଲିଂ ନମ୍ୱରଗୁଡ଼ିକ ଦେଖନ୍ତୁ"</string>
diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml
index 8dd6abd..859198a 100644
--- a/res/values-pa/strings.xml
+++ b/res/values-pa/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"ਇੱਕ ਗ਼ੈਰ-ਅਪਾਤਕਾਲ ਕਾਲ ਕਰਨ ਲਈ ਅਪਾਤਕਾਲ ਕਾਲਬੈਕ ਮੋਡ ਤੋਂ ਬਾਹਰ ਆਓ।"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ਨੈਟਵਰਕ ਤੇ ਰਜਿਸਟਰ ਨਹੀਂ ਕੀਤਾ।"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"ਮੋਬਾਈਲ ਨੈਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ।"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।\n\nਕਾਲ ਕਰਨ ਲਈ ਵਾਇਰਲੈੱਸ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰੋ।\n\nਇਸ ਡੀਵਾਈਸ \'ਤੇ 2G ਬੰਦ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਕਨੈਕਟੀਵਿਟੀ ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕਰ ਸਕਦਾ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ \'2G ਨੂੰ ਆਗਿਆ ਦਿਓ\' ਨੂੰ ਚਾਲੂ ਕਰੋ।"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ। ਕਾਲ ਕਰਨ ਲਈ ਕਿਸੇ ਵਾਇਰਲੈੱਸ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰੋ।"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"ਮੋਬਾਈਲ ਨੈੱਟਵਰਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।\n\nਕਾਲ ਕਰਨ ਲਈ ਵਾਇਰਲੈੱਸ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰੋ।\n\nਇਸ ਡੀਵਾਈਸ \'ਤੇ 2G ਬੰਦ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਕਨੈਕਟੀਵਿਟੀ ਨੂੰ ਪ੍ਰਭਾਵਿਤ ਕਰ ਸਕਦਾ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ \'2G ਨੂੰ ਆਗਿਆ ਦਿਓ\' ਨੂੰ ਚਾਲੂ ਕਰੋ।"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ਇੱਕ ਕਾਲ ਕਰਨ ਲਈ, ਇੱਕ ਪ੍ਰਮਾਣਿਕ ਨੰਬਰ ਦਰਜ ਕਰੋ।"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"ਕਾਲ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ।"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ਇਸ ਸਮੇਂ ਕਾਲ ਸ਼ਾਮਲ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ। ਤੁਸੀਂ ਇੱਕ ਸੁਨੇਹਾ ਭੇਜ ਕੇ ਸੰਪਰਕ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰ ਸਕਦੇ ਹੋ।"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"ਕਾਲਾਂ ਹੋਲਡ ਨਹੀਂ ਕੀਤੀਆਂ ਜਾ ਸਕਦੀਆਂ ਹਨ।"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ਇੱਕ ਕਾਲ ਕਰਨ ਲਈ ਇੱਕ ਵਾਇਰਲੈਸ ਨੈਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਕਰੋ।"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"ਇੱਕ ਕਾਲ ਕਰਨ ਲਈ Wi-Fi ਕਾਲਿੰਗ ਯੋਗ ਬਣਾਓ।"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"ਕਾਲ ਕਰਨ ਲਈ ਉਪਗ੍ਰਹਿ ਮੋਡ ਬੰਦ ਕਰੋ।"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ਕਾਲ ਕਰਨ ਲਈ, ਪਹਿਲਾਂ ਉਪਗ੍ਰਹਿ ਕਨੈਕਸ਼ਨ ਬੰਦ ਕਰੋ।"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"ਤੁਸੀਂ ਮੋਬਾਈਲ ਜਾਂ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕ ਤੋਂ ਬਿਨਾਂ ਸੁਨੇਹੇ ਭੇਜ ਅਤੇ ਪ੍ਰਾਪਤ ਕਰ ਸਕਦੇ ਹੋ।"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"ਸੰਕਟਕਾਲੀਨ ਜਾਣਕਾਰੀ"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"ਮਾਲਕ"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"ਜਾਣਕਾਰੀ ਦੇਖਣ ਲਈ ਦੁਬਾਰਾ ਟੈਪ ਕਰੋ"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ਸਿਮ ਦੀ ਪਤਾ ਬੁੱਕ ਦੇਖੋ"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ਫਿਕਸਡ ਡਾਇਲਿੰਗ ਨੰਬਰ ਦੇਖੋ"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ਸੇਵਾ ਡਾਇਲਿੰਗ ਨੰਬਰ ਦੇਖੋ"</string>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
index 18ff3b1..8bd1c0e 100644
--- a/res/values-pl/strings.xml
+++ b/res/values-pl/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Aby zadzwonić normalnie, wyjdź z trybu alarmowego połączenia zwrotnego."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Nie zarejestrowano w sieci"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Sieć komórkowa jest niedostępna."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Sieć komórkowa jest niedostępna.\n\nAby zadzwonić, połącz się z siecią bezprzewodową.\n\nSieć 2G na tym urządzeniu jest wyłączona, co może mieć wpływ na łączność. Aby kontynuować, przejdź do Ustawień i włącz opcję „Zezwól na 2G”."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Sieć komórkowa jest niedostępna. Połącz się z siecią bezprzewodową, by zadzwonić."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Sieć komórkowa jest niedostępna.\n\nAby zadzwonić, połącz się z siecią bezprzewodową.\n\nSieć 2G na tym urządzeniu jest wyłączona, co może mieć wpływ na łączność. Aby kontynuować, przejdź do Ustawień i włącz opcję „Zezwól na 2G”."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Aby zadzwonić, wybierz prawidłowy numer."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Nie udało się połączyć."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"W tej chwili nie możesz zadzwonić. Zamiast tego możesz wysłać wiadomość."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Nie można zawieszać połączeń."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Połącz się z siecią bezprzewodową, by zadzwonić."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Włącz Połączenia przez Wi-Fi, aby nawiązać połączenie."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Aby zadzwonić, wyłącz tryb satelitarny."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Aby zadzwonić, najpierw zakończ połączenie satelitarne."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Możesz wymieniać wiadomości bez dostępu do sieci komórkowej lub Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informacje alarmowe"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Właściciel"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Kliknij ponownie, aby wyświetlić informacje"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml
index 10fb31a..8bfb02b 100644
--- a/res/values-pt-rPT/strings.xml
+++ b/res/values-pt-rPT/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Sair do modo de chamada de retorno de emergência para efetuar uma chamada que não é de emergência."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Sem registo na rede."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Rede móvel não disponível."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"A rede móvel não está disponível.\n\nLigue-se a uma rede sem fios para fazer uma chamada.\n\nO 2G está desativado neste dispositivo, o que pode estar a afetar a sua conetividade. Aceda às Definições e ative a opção Permitir 2G para continuar."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"A rede móvel não está disponível. Ligue-se a uma rede sem fios para efetuar uma chamada."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"A rede móvel não está disponível.\n\nLigue-se a uma rede sem fios para fazer uma chamada.\n\nO 2G está desativado neste dispositivo, o que pode estar a afetar a sua conetividade. Aceda às Definições e ative a opção Permitir 2G para continuar."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Para telefonar, introduza um número válido."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"A chamada falhou."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Não é possível adicionar a chamada neste momento. Pode tentar entrar em contacto ao enviar uma mensagem."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Não é possível colocar as chamadas em espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Ligue-se a uma rede sem fios para fazer uma chamada."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Ativar as chamadas através de Wi-Fi para fazer uma chamada."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Desative o modo satélite para fazer uma chamada."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Para fazer uma chamada, termine primeiro a ligação de satélite."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Pode enviar e receber mensagens sem uma rede móvel ou Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informações de emergência"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Proprietário"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Toque novamente para ver informações"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml
index 02288b9..c14b710 100644
--- a/res/values-pt/strings.xml
+++ b/res/values-pt/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Saia do modo de retorno de chamada de emergência para fazer uma chamada que não seja de emergência."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Não registrado na rede."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Rede móvel não disponível."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Rede móvel indisponível.\n\nConecte-se a uma rede sem fio para fazer uma ligação.\n\nO 2G está desativado neste dispositivo e isso pode afetar sua conectividade. Acesse \"Configurações\" e ative a opção \"Permitir 2G\" para continuar."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"A rede móvel não está disponível. Conecte-se a uma rede sem fio para fazer uma chamada."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"A rede móvel está indisponível.\n\nConecte-se a uma rede sem fio para fazer uma ligação.\n\nO 2G está desativado neste dispositivo e pode estar afetando sua conectividade. Acesse \"Configurações\" e ative a opção \"Permitir 2G\" para continuar."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Para realizar uma chamada, digite um número válido."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Falha na chamada."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Não é possível ligar no momento. Entre em contato enviando uma mensagem."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Não é possível colocar chamadas em espera."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Conecte-se a uma rede sem fio para fazer uma chamada."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Ative as chamadas por Wi-Fi para fazer uma chamada."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Desative o modo satélite para fazer uma ligação."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Para fazer uma ligação, encerre a conexão por satélite."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Você pode enviar e receber mensagens sem um dispositivo móvel ou uma rede Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informações de emergência"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Proprietário"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Toque novamente para ver as informações"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml
index 94cf9d4..c855de1 100644
--- a/res/values-ro/strings.xml
+++ b/res/values-ro/strings.xml
@@ -542,7 +542,9 @@
<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_2g" msgid="904434080740846116">"Rețeaua mobilă nu este disponibilă.\n\nConectează-te la o rețea wireless pentru a iniția un apel.\n\n2G este dezactivat pe acest dispozitiv, ceea ce poate afecta conectivitatea. Accesează Setări și activează setarea Permite 2G pentru a continua."</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_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Rețeaua mobilă nu este disponibilă.\n\nConectează-te la o rețea wireless pentru a iniția un apel.\n\n2G este dezactivat pe acest dispozitiv, ceea ce poate afecta conectivitatea. Accesează Setări și activează setarea Permite 2G pentru a continua."</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. Poți lua legătura cu persoana respectivă trimițându-i un mesaj."</string>
@@ -557,7 +559,8 @@
<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, 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="incall_error_satellite_enabled" msgid="1936541518147323016">"Dezactivează modul Satelit pentru a apela."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Pentru a apela, mai întâi încheie conexiunea prin satelit."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Poți să trimiți și să primești mesaje fără o rețea mobilă sau Wi-Fi."</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 din nou pentru a vedea informațiile"</string>
@@ -841,6 +844,8 @@
<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="simulate_out_of_service_string" msgid="7787925611727597193">"Simulează modul în afara ariei de acoperire (numai în versiunea pentru remedierea erorilor)"</string>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
index ec534c6..becc6aa 100644
--- a/res/values-ru/strings.xml
+++ b/res/values-ru/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Чтобы сделать обычный звонок, выйдите из режима экстренных обратных вызовов."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Нет регистрации в сети."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Мобильная сеть недоступна."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Мобильная сеть недоступна.\n\nЧтобы позвонить, подключитесь к беспроводной сети.\n\nНа этом устройстве отключена передача данных по сетям 2G, что может влиять на функции связи. Чтобы продолжить, перейдите в настройки и включите параметр \"Разрешить 2G\"."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Мобильная сеть недоступна. Чтобы позвонить, подключитесь к Wi-Fi."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Мобильная сеть недоступна.\n\nЧтобы позвонить, подключитесь к беспроводной сети.\n\nНа этом устройстве отключена передача данных по сетям 2G, что может влиять на функции связи. Чтобы продолжить, перейдите в настройки и включите параметр \"Разрешить 2G\"."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Недействительный номер."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Не удалось отправить вызов."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Не удается позвонить. Попробуйте отправить сообщение."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Удержание невозможно."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Чтобы позвонить, подключитесь к Wi-Fi."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Чтобы позвонить, включите звонки через Wi-Fi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Чтобы позвонить, отключите спутниковый режим."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Чтобы позвонить, сначала завершите спутниковое соединение."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Вы можете отправлять и получать сообщения без доступа к мобильной сети или Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Данные для экстренных случаев"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Владелец"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Чтобы посмотреть информацию, нажмите ещё раз"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml
index 22f0a1c..6fd6ff6 100644
--- a/res/values-si/strings.xml
+++ b/res/values-si/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"හදිසි-නොවන ඇමතුමක් සිදු කිරීමට හදිසි අවස්ථා පසු ඇමතුම් ප්රකාරයෙන් ඉවත් වන්න."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ජාලය මත ලියාපදිංචි වී නැත."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"ජංගම ජාලය නොමැත."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"ජංගම ජාලය නොලැබේ.\n\nඇමතුමක් කිරීමට රැහැන් රහිත ජාලයකට සම්බන්ධ කරන්න.\n\nමෙම උපාංගය මත 2G අබල කර ඇත, එය ඔබේ සම්බන්ධතාවට බලපාමින් තිබේවි. ඉදිරියට යාමට සැකසීම් වෙත ගොස් 2G හට ඉඩ දෙන්න සබල කරන්න."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"ජංගම ජාලය ලබා ගැනීමට නොහැකිය. ඇමතුමක් කිරීමට රැහැන් රහිත ජාලයකට සම්බන්ධ කරන්න."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"ජංගම ජාලය නොලැබේ.\n\nඇමතුමක් කිරීමට රැහැන් රහිත ජාලයකට සම්බන්ධ කරන්න.\n\nමෙම උපාංගය මත 2G අබල කර ඇත, එය ඔබේ සම්බන්ධතාවට බලපාමින් තිබේවි. ඉදිරියට යාමට සැකසීම් වෙත ගොස් 2G හට ඉඩ දෙන්න සබල කරන්න."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"ඇමතුමක් ලබාගැනීමට, වලංගු අංකයක් ලබාගන්න."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"ඇමතුම අසාර්ථක විය."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ඇමතුම මෙම වේලාවේදී එක් කිරීමට නොහැකිය. ඔබට පණිවිඩයක් යැවීමෙන් ළඟා වීමට උත්සාහ කිරීමට හැකිය."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"ඇමතුම් රඳවා තැබීමට නොහැකිය."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"ඇමතුමක් ගැනීමට රැහැන් රහිත ජාලයක් වෙත සම්බන්ධ වෙන්න."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"ඇමතුමක් කිරීමට Wi-Fi ඇමතීම සබල කරන්න."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"ඇමතුමක් ගැනීමට චන්ද්රිකා ප්රකාරය ක්රියාවිරහිත කරන්න."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"ඇමතුමක් ගැනීමට, පළමුව චන්ද්රිකා සම්බන්ධතාව නිමා කරන්න."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"ඔබට ජංගම හෝ Wi-Fi ජාලයක් නොමැතිව පණිවිඩ යැවීමට සහ ලැබීමට හැක."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"හදිසි අවස්ථා තොරතුරු"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"හිමිකරු"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"තොරතුරු බැලීම සඳහා නැවත තට්ටු කරන්න"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml
index 623f3c0..a0eac8b 100644
--- a/res/values-sk/strings.xml
+++ b/res/values-sk/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Ak chcete volať štandardným spôsobom, ukončite režim tiesňového spätného volania."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Prihlásenie do siete nebolo úspešné."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobilná sieť nie je k dispozícii."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilná sieť nie je k dispozícii.\n\nAk chcete volať, pripojte sa k bezdrôtovej sieti.\n\nV tomto zariadení nie je zapnuté pripojenie 2G, čo môže mať vplyv na možnosti pripojenia. Ak chcete pokračovať, prejdite do nastavení a zapnite možnosť Povoliť 2G."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilná sieť nie je k dispozícii. Ak chcete volať, pripojte sa k bezdrôtovej sieti."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilná sieť nie je k dispozícii.\n\nAk chcete volať, pripojte sa k bezdrôtovej sieti.\n\nV tomto zariadení je prístup k 2G vypnutý, čo môže mať vplyv na pripojenie. Ak chcete pokračovať, prejdite do nastavení a zapnite možnosť Povoliť 2G."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Ak chcete volať, zadajte platné číslo"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Hovor zlyhal."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Hovor sa momentálne nedá pridať. Môžete namiesto toho skúsiť poslať správu."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Hovory nie je možné podržať."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Ak chcete volať, pripojte sa k bezdrôtovej sieti"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Na uskutočnenie hovoru povoľte volanie cez Wi‑Fi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Ak chcete volať, deaktivujte satelitný režim."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Ak chcete uskutočniť hovor, musíte najprv ukončiť satelitné pripojenie."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Správy môžete odosielať a prijímať bez mobilnej siete či siete Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Tiesňové informácie"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Vlastník"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Informácie si zobrazíte opätovným klepnutím"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 1f86b13..ed4f6b3 100644
--- a/res/values-sl/strings.xml
+++ b/res/values-sl/strings.xml
@@ -168,7 +168,7 @@
<string name="vm_change_pin_progress_message" msgid="626015184502739044">"Počakajte."</string>
<string name="vm_change_pin_error_too_short" msgid="1789139338449945483">"Nova koda PIN je prekratka."</string>
<string name="vm_change_pin_error_too_long" msgid="3634907034310018954">"Nova koda PIN je predolga."</string>
- <string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"Nova koda PIN je prešibka. Zapleteno geslo ne sme vsebovati zaporednih ali ponavljajočih se števk."</string>
+ <string name="vm_change_pin_error_too_weak" msgid="8581892952627885719">"Nova koda PIN je prešibka. Močno geslo ne sme vsebovati zaporednih ali ponavljajočih se števk."</string>
<string name="vm_change_pin_error_mismatch" msgid="5364847280026257331">"Stara koda PIN se ne ujema."</string>
<string name="vm_change_pin_error_invalid" msgid="5230002671175580674">"Nova koda PIN vsebuje neveljavne znake."</string>
<string name="vm_change_pin_error_system_error" msgid="9116483527909681791">"Ni mogoče spremeniti kode PIN"</string>
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Če ne gre za klic v sili, zaprite način za povratni klici v sili."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ni registrirano v omrežju."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Omrežje prenosnega telefona ni na voljo."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobilno omrežje ni na voljo.\n\nČe želite opraviti klic, vzpostavite povezavo z brezžičnim omrežjem.\n\nOmrežje 2G je v tej napravi onemogočeno, kar lahko vpliva na povezljivost. Odprite nastavitve in vklopite možnost »Omogoči 2G«, če želite nadaljevati."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobilno omrežje ni na voljo. Če želite opraviti klic, vzpostavite povezavo z brezžičnim omrežjem."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobilno omrežje ni na voljo.\n\nČe želite opraviti klic, vzpostavite povezavo z brezžičnim omrežjem.\n\nOmrežje 2G je v tej napravi onemogočeno, kar lahko vpliva na povezljivost. Odprite nastavitve in vklopite možnost »Omogoči 2G«, če želite nadaljevati."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Če želite opraviti klic, vnesite veljavno številko."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Klic ni uspel."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Trenutno ni mogoče dodati klica. Poskusite poslati sporočilo."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Klicev ni mogoče zadržati."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Povežite se v omrežje Wi-Fi, če želite opraviti klic."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Če želite opraviti klic, omogočite klicanja prek Wi-Fi-ja."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Če želite opraviti klic, onemogočite satelitski način."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Če želite opraviti klic, najprej prekinite satelitsko povezavo."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Sporočila SMS lahko pošiljate in prejemate brez mobilnega omrežja ali omrežja Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informacije za nujne primere"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Lastnik"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Znova se dotaknite, da si ogledate podatke"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml
index 0d4d021..9ce3ce3 100644
--- a/res/values-sq/strings.xml
+++ b/res/values-sq/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Dil nga modaliteti i kthimit të telefonatës së urgjencës për të bërë një telefonatë jo urgjente."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"I paregjistruar në rrjet."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Rrjeti celular nuk mundësohet."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Rrjeti celular nuk ofrohet.\n\nLidhu me një rrjet wireless për të bërë një telefonatë.\n\n2G është çaktivizuar në këtë pajisje, e cila mund të ketë ndikim te lidhshmëria. Shko te \"Cilësimet\" dhe aktivizo \"Lejo 2G\" për të vazhduar."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Rrjeti celular nuk ofrohet. Lidhu me një rrjet wireless për të bërë një telefonatë."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Rrjeti celular nuk ofrohet.\n\nLidhu me një rrjet wireless për të bërë një telefonatë.\n\n2G është çaktivizuar në këtë pajisje, e cila mund të ketë ndikim te lidhshmëria. Shko te \"Cilësimet\" dhe aktivizo \"Lejo 2G\" për të vazhduar."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Për të kryer një telefonatë, fut një numër të vlefshëm."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Thirrja dështoi."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Telefonata nuk mund të shtohet në këtë moment. Mund të provosh të kontaktosh duke dërguar një mesazh."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Telefonatat nuk mund të mbahen në pritje."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Lidhu me një rrjet wireless për të bërë një telefonatë."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Aktivizo telefonatat nëpërmjet rrjetit Wi-Fi për të bërë një telefonatë."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Çaktivizo modalitetin e satelitit për të bërë një telefonatë."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Për të bërë një telefonatë, në fillim mbyll lidhjen satelitore."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Mund të dërgosh dhe të marrësh mesazhe pa një rrjet celular apo rrjet Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Informacioni i urgjencës"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Zotëruesi"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Trokit përsëri për të shikuar informacionet"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index d25009f..701cce8 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Изађите из режима хитног повратног позива да бисте упутили позив који није хитан."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Није регистровано на мрежи."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Мобилна мрежа није доступна."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Мобилна мрежа није доступна.\n\nПовежите се на бежичну мрежу да бисте упутили позив.\n\n2G је онемогућен на овом уређају, што може да утиче на повезивање. Идите у Подешавања и омогућите опцију Дозволи 2G да бисте наставили."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Мобилна мрежа није доступна. Повежите се на бежичну да бисте упутили позив."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Мобилна мрежа није доступна.\n\nПовежите се на бежичну мрежу да бисте упутили позив.\n\n2G је онемогућен на овом уређају, што може да утиче на повезивање. Идите у Подешавања и омогућите опцију Дозволи 2G да бисте наставили."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Да бисте упутили позив, унесите важећи број."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Позив није успео."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Додавање позива тренутно није могуће. Можете да покушате да остварите контакт помоћу поруке."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Није могуће стављати позиве на чекање."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Повежите се на бежичну мрежу да бисте упутили позив."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Омогућите позивање преко WiFi-а да бисте упутили позив."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Онемогућите сателитски режим да бисте упутили позив."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Да бисте упутили позив, прво завршите сателитску везу."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Можете да шаљете и примате поруке без мобилне или WiFi мреже."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Информације за хитне случајеве"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Власник"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Додирните поново да бисте видели информације"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml
index 19ce90f..9f65b29 100644
--- a/res/values-sv/strings.xml
+++ b/res/values-sv/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Avsluta läget för återuppringning vid nödsamtal om du vill ringa ett vanligt samtal."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Inte registrerat på nätverk."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Inget mobilt nätverk är tillgängligt."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Det finns inga tillgängliga mobilnätverk.\n\nAnslut till ett trådlöst nätverk om du vill ringa.\n\n2G har inaktiverats på den här enheten, vilket kan påverka anslutningen. Öppna inställningarna och aktivera Tillåt 2G om du vill fortsätta."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Det finns inga tillgängliga mobilnätverk. Anslut till ett trådlöst nätverk om du vill ringa."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Det finns inget mobilnätverk.\n\nAnslut till ett trådlöst nätverk om du vill ringa ett samtal.\n\n2G har inaktiverats på den här enheten, vilket kan påverka anslutningen. Öppna inställningarna och aktivera Tillåt 2G om du vill fortsätta."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Ange ett giltigt nummer om du vill ringa ett samtal."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Det gick inte att koppla samtalet."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Det går inte att lägga till samtalet just nu. Ta istället kontakt genom att skicka ett meddelande."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Det går inte att hålla kvar samtal."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Anslut till ett trådlöst nätverk om du vill ringa."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Aktivera wifi-samtal för att ringa."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Inaktivera satellitläget om du vill ringa ett samtal."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Om du vill ringa ett samtal måste du först avsluta satellitanslutningen."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Du kan skicka och ta emot meddelanden utan mobil- eller wifi-nätverk."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Nödinformation"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Ägare"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Tryck igen för att visa information"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
@@ -881,7 +886,7 @@
<string name="radio_info_cellinfo_label" msgid="8199062974670377659">"Alla information om mastmätning:"</string>
<string name="radio_info_gprs_service_label" msgid="6819204246355412952">"Datatjänst:"</string>
<string name="radio_info_roaming_label" msgid="6636932886446857120">"Roaming:"</string>
- <string name="radio_info_imei_label" msgid="8947899706930120368">"IMEI-kod:"</string>
+ <string name="radio_info_imei_label" msgid="8947899706930120368">"IMEI-nummer:"</string>
<string name="radio_info_call_redirect_label" msgid="4526480903023362276">"Vidarekoppling av samtal:"</string>
<string name="radio_info_ppp_resets_label" msgid="9131901102339077661">"Antal återställningar av köpkraftsparitet sedan start:"</string>
<string name="radio_info_current_network_label" msgid="3052098695239642450">"Aktuellt nätverk:"</string>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 2cbcafa..1569803 100644
--- a/res/values-sw/strings.xml
+++ b/res/values-sw/strings.xml
@@ -45,8 +45,8 @@
<string name="pause_prompt_no" msgid="2145264674774138579">"Hapana"</string>
<string name="wild_prompt_str" msgid="5858910969703305375">"Badilisha kibambo egemezi na"</string>
<string name="no_vm_number" msgid="6623853880546176930">"Nambari ya sauti inayokosekana"</string>
- <string name="no_vm_number_msg" msgid="5165161462411372504">"Hakuna nambari ya ujumbe wa sauti iliyohifadhiwa katika SIM kadi."</string>
- <string name="add_vm_number_str" msgid="7368168964435881637">"Ongeza nambari"</string>
+ <string name="no_vm_number_msg" msgid="5165161462411372504">"Hakuna namba ya ujumbe wa sauti iliyohifadhiwa katika SIM kadi."</string>
+ <string name="add_vm_number_str" msgid="7368168964435881637">"Ongeza namba"</string>
<string name="voice_number_setting_primary_user_only" msgid="3394706575741912843">"Mipangilio ya ujumbe wa sauti inaweza kubadilishwa na Mtumiaji wa Msingi Pekee."</string>
<string name="puk_unlocked" msgid="4627340655215746511">"Kadi yako ya simu imefunguliwa. Simu yangu inafungua…."</string>
<string name="label_ndp" msgid="7617392683877410341">"PIN ya kufungua mtandao wa SIM"</string>
@@ -82,7 +82,7 @@
<string name="voicemail_abbreviated" msgid="7746778673131551185">"VM:"</string>
<string name="make_and_receive_calls" msgid="4868913166494621109">"Kupiga na kupokea simu"</string>
<string name="smart_forwarding_settings_menu" msgid="8850429887958938540">"Usambazaji Mahiri"</string>
- <string name="smart_forwarding_settings_menu_summary" msgid="5096947726032885325">"Ikiwa nambari moja haiwezi kufikiwa, sambaza simu kwa nambari nyingine kila wakati"</string>
+ <string name="smart_forwarding_settings_menu_summary" msgid="5096947726032885325">"Ikiwa namba moja haiwezi kufikiwa, sambaza simu kwa namba nyingine kila wakati"</string>
<string name="voicemail_notifications_preference_title" msgid="7829238858063382977">"Arifa"</string>
<string name="cell_broadcast_settings" msgid="8135324242541809924">"Matangazo ya dharura"</string>
<string name="call_settings" msgid="3677282690157603818">"Mipangilio ya simu"</string>
@@ -96,7 +96,7 @@
<string name="sum_loading_settings" msgid="434063780286688775">"Mipangilio inapakia..."</string>
<string name="sum_hide_caller_id" msgid="131100328602371933">"Nambari imefichwa kwa simu unayopiga"</string>
<string name="sum_show_caller_id" msgid="3571854755324664591">"Namba inaonekana kwa simu zinazopigwa"</string>
- <string name="sum_default_caller_id" msgid="1767070797135682959">"Tumia mipangilio ya mtoa huduma chaguomsingi kuonyesha nambari kwa simu unazopiga"</string>
+ <string name="sum_default_caller_id" msgid="1767070797135682959">"Tumia mipangilio ya mtoa huduma chaguomsingi kuonyesha namba kwa simu unazopiga"</string>
<string name="labelCW" msgid="8449327023861428622">"Simu inayosubiri kupokewa"</string>
<string name="sum_cw_enabled" msgid="3977308526187139996">"Wakati ninapokea simu, niarifu kuhusu simu zingine zinazoingia"</string>
<string name="sum_cw_disabled" msgid="3658094589461768637">"Wakati ninapokea simu, niarifu kuhusu simu zingine zinazoingia"</string>
@@ -104,7 +104,7 @@
<string name="call_forwarding_settings_with_label" msgid="2345432813399564272">"Mipangilio ya kusambaza simu (<xliff:g id="SUBSCRIPTIONLABEL">%s</xliff:g>)"</string>
<string name="labelCF" msgid="3578719437928476078">"Kusambaza simu"</string>
<string name="labelCFU" msgid="8870170873036279706">"Sambaza kila wakati"</string>
- <string name="messageCFU" msgid="1361806450979589744">"Kila wakati tumia nambari hii"</string>
+ <string name="messageCFU" msgid="1361806450979589744">"Kila wakati tumia namba hii"</string>
<string name="sum_cfu_enabled_indicator" msgid="9030139213402432776">"Inasambaza simu zote"</string>
<string name="sum_cfu_enabled" msgid="5806923046528144526">"Inasambaza simu zote kwa <xliff:g id="PHONENUMBER">{0}</xliff:g>"</string>
<string name="sum_cfu_enabled_no_number" msgid="7287752761743377930">"Nambari haipatikani"</string>
@@ -145,7 +145,7 @@
<string name="stk_cc_ss_to_ussd_error" msgid="8330749347425752192">"Imebadilisha ombi la SS kuwa ombi la USSD"</string>
<string name="stk_cc_ss_to_ss_error" msgid="8297155544652134278">"Imebadilishwa kuwa ombi jipya la SS"</string>
<string name="stk_cc_ss_to_dial_video_error" msgid="4255261231466032505">"Imebadilisha ombi la SS kuwa simu ya video"</string>
- <string name="fdn_check_failure" msgid="1833769746374185247">"Mipangilio ya programu ya simu yako ya nambari za simu zilizobainishwa pekee imewashwa. Kutokana na hayo, baadhi ya vipengele vya kupiga simu havifanyi kazi."</string>
+ <string name="fdn_check_failure" msgid="1833769746374185247">"Mipangilio ya programu ya simu yako ya namba za simu zilizobainishwa pekee imewashwa. Kutokana na hayo, baadhi ya vipengele vya kupiga simu havifanyi kazi."</string>
<string name="radio_off_error" msgid="8321564164914232181">"Washa redio kabla ya kutazama mipangilio hii."</string>
<string name="close_dialog" msgid="1074977476136119408">"Sawa"</string>
<string name="enable" msgid="2636552299455477603">"Washa"</string>
@@ -153,13 +153,13 @@
<string name="change_num" msgid="6982164494063109334">"Sasisha"</string>
<string-array name="clir_display_values">
<item msgid="8477364191403806960">"Chaguomsingi la mtandao"</item>
- <item msgid="6813323051965618926">"Ficha nambari"</item>
- <item msgid="9150034130629852635">"Onyesha nambari"</item>
+ <item msgid="6813323051965618926">"Ficha namba"</item>
+ <item msgid="9150034130629852635">"Onyesha namba"</item>
</string-array>
<string name="vm_changed" msgid="4739599044379692505">"Nambari ya ujumbe wa sauti haijabadilishwa"</string>
<string name="vm_change_failed" msgid="7877733929455763566">"Haikuweza kubadilisha namba ya ujumbe wa sauti.\nWasiliana na mtoa huduma wako shida hii ikiendelea."</string>
<string name="fw_change_failed" msgid="9179241823460192148">"Haikuweza kubadilisha namba ya kusambaza.\nWasiliana na mtoa huduma wako shida hii ikiendelea."</string>
- <string name="fw_get_in_vm_failed" msgid="2432678237218183844">"Haikuweza kuepua na kuhifadhi mipangilio ya nambari ya usambazaji. \n Hata hivyo swichi kwa mtoahuduma mpya?"</string>
+ <string name="fw_get_in_vm_failed" msgid="2432678237218183844">"Haikuweza kuepua na kuhifadhi mipangilio ya namba ya usambazaji. \n Hata hivyo swichi kwa mtoahuduma mpya?"</string>
<string name="no_change" msgid="3737264882821031892">"Hakuna mabadiliko yaliyofanywa"</string>
<string name="sum_voicemail_choose_provider" msgid="6750824719081403773">"Chagua huduma ya barua ya sauti"</string>
<string name="voicemail_default" msgid="6427575113775462077">"Mtoa huduma wako"</string>
@@ -449,9 +449,9 @@
<string name="change_pin2" msgid="3110844547237754871">"Badilisha PIN2"</string>
<string name="enable_fdn_ok" msgid="5080925177369329827">"Lemaza FDN"</string>
<string name="disable_fdn_ok" msgid="3745475926874838676">"Washa FDN"</string>
- <string name="sum_fdn" msgid="6152246141642323582">"Dhibiti nambari za simu zilizobainishwa"</string>
+ <string name="sum_fdn" msgid="6152246141642323582">"Dhibiti namba za simu zilizobainishwa"</string>
<string name="sum_fdn_change_pin" msgid="3510994280557335727">"Badilisha nenosiri la kufikia FDN"</string>
- <string name="sum_fdn_manage_list" msgid="3311397063233992907">"Dhibiti orodha ya nambari za simu"</string>
+ <string name="sum_fdn_manage_list" msgid="3311397063233992907">"Dhibiti orodha ya namba za simu"</string>
<string name="voice_privacy" msgid="7346935172372181951">"Faragha ya sauti"</string>
<string name="voice_privacy_summary" msgid="3556460926168473346">"Wezesha gumzo ya faragha iliyoboreshwa"</string>
<string name="tty_mode_option_title" msgid="3843817710032641703">"Hali ya TTY"</string>
@@ -462,22 +462,22 @@
<string name="menu_add" msgid="5616487894975773141">"Ongeza anwani"</string>
<string name="menu_edit" msgid="3593856941552460706">"Hariri anwani"</string>
<string name="menu_delete" msgid="6326861853830546488">"Futa anwani"</string>
- <string name="menu_dial" msgid="4178537318419450012">"Piga nambari ya unayewasiliana naye"</string>
+ <string name="menu_dial" msgid="4178537318419450012">"Piga namba ya unayewasiliana naye"</string>
<string name="get_pin2" msgid="4221654606863196332">"Chapa PIN2"</string>
<string name="name" msgid="1347432469852527784">"Jina"</string>
<string name="number" msgid="1564053487748491000">"Nambari"</string>
<string name="save" msgid="983805790346099749">"Hifadhi"</string>
- <string name="add_fdn_contact" msgid="1169713422306640887">"Ongeza nambari za upigaji simu uliobanwa"</string>
- <string name="adding_fdn_contact" msgid="3112531600824361259">"Inaongeza nambari ya upigaji uliobanwa..."</string>
+ <string name="add_fdn_contact" msgid="1169713422306640887">"Ongeza namba za upigaji simu uliobanwa"</string>
+ <string name="adding_fdn_contact" msgid="3112531600824361259">"Inaongeza namba ya upigaji uliobanwa..."</string>
<string name="fdn_contact_added" msgid="2840016151693394596">"Nambari ya upigaji simu uliobanwa imeongezwa."</string>
- <string name="edit_fdn_contact" msgid="6030829994819587408">"Hariri nambari za kudumu"</string>
- <string name="updating_fdn_contact" msgid="6989341376868227150">"Inasasisha nambari ya upigaji simu uliobanwa..."</string>
+ <string name="edit_fdn_contact" msgid="6030829994819587408">"Hariri namba za kudumu"</string>
+ <string name="updating_fdn_contact" msgid="6989341376868227150">"Inasasisha namba ya upigaji simu uliobanwa..."</string>
<string name="fdn_contact_updated" msgid="6876330243323118937">"Nambari ya upigaji simu uliobanwa imesasishwa."</string>
<string name="delete_fdn_contact" msgid="7027405651994507077">"Futa namba ya upigaji simu ya kudumu"</string>
- <string name="deleting_fdn_contact" msgid="6872320570844460428">"Inafuta nambari ya upigaji simu uliobanwa..."</string>
+ <string name="deleting_fdn_contact" msgid="6872320570844460428">"Inafuta namba ya upigaji simu uliobanwa..."</string>
<string name="fdn_contact_deleted" msgid="1680714996763848838">"Nambari ya upigaji simu uliobanwa imefutwa"</string>
<string name="pin2_invalid" msgid="2313954262684494442">"FDN haikusasishwa kwa sababu uliweka PIN isiyo sahihi."</string>
- <string name="fdn_invalid_number" msgid="9067189814657840439">"FDN haijasasishwa kwa sababu nambari inazidi tarakimu <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g>."</string>
+ <string name="fdn_invalid_number" msgid="9067189814657840439">"FDN haijasasishwa kwa sababu namba inazidi tarakimu <xliff:g id="FDN_NUMBER_LIMIT_LENGTH">%d</xliff:g>."</string>
<string name="pin2_or_fdn_invalid" msgid="7542639487955868181">"FDN haikusasishwa. PIN2 haikuwa sahihi, au namba ya simu ilikataliwa."</string>
<string name="fdn_failed" msgid="216592346853420250">"Utendakazi wa FDN ulishindwa."</string>
<string name="simContacts_emptyLoading" msgid="4989040293858675483">"Inasoma kutoka kwa SIM kadi…"</string>
@@ -492,7 +492,7 @@
<string name="confirmPinLabel" msgid="7783531218662473778">"Thibitisha PIN mpya"</string>
<string name="badPin" msgid="4549286285015892321">"PIN ya zamani uliyochapa sio sahihi. Jaribu tena."</string>
<string name="mismatchPin" msgid="1467254768290323845">"PIN ulizochapa hazilingani. Jaribu tena."</string>
- <string name="invalidPin" msgid="7363723429414001979">"Chapisha nenosiri lenye nambari kati ya 4 na 8."</string>
+ <string name="invalidPin" msgid="7363723429414001979">"Chapisha nenosiri lenye namba kati ya 4 na 8."</string>
<string name="disable_sim_pin" msgid="3112303905548613752">"Ondoa PIN ya SIM"</string>
<string name="enable_sim_pin" msgid="445461050748318980">"Weka PIN ya SIM"</string>
<string name="enable_in_progress" msgid="4135305985717272592">"Inaweka PIN…"</string>
@@ -508,8 +508,8 @@
<string name="badPuk2" msgid="6438182906645832235">"PUK2 si sahihi. Jaribu tena."</string>
<string name="badPin2" msgid="2760917538643074635">"PIN2 ya zamani si sahihi. Jaribu tena."</string>
<string name="mismatchPin2" msgid="4952718725266700631">"PIN2 hazilingani. Jaribu tena."</string>
- <string name="invalidPin2" msgid="6467957903056379343">"Weka PIN2 iliyo na kati ya nambari 4 hadi 8."</string>
- <string name="invalidPuk2" msgid="713729511903849544">"Weka PUK2 yenye nambari 8."</string>
+ <string name="invalidPin2" msgid="6467957903056379343">"Weka PIN2 iliyo na kati ya namba 4 hadi 8."</string>
+ <string name="invalidPuk2" msgid="713729511903849544">"Weka PUK2 yenye namba 8."</string>
<string name="pin2_changed" msgid="5710551850481287821">"PIN2 imesasishwa"</string>
<string name="label_puk2_code" msgid="2852217004288085562">"Weka msimbo wa PUK2"</string>
<string name="fdn_enable_puk2_requested" msgid="5793652792131588041">"Nenosiri si sahihi. PIN2 sasa Imezuiwa. Ili ujaribu tena, badilisha PIN 2."</string>
@@ -542,8 +542,10 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Ondoka kwenye hali ya kupiga simu za dharura ili upige simu zisizokuwa za dharura."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Haijasajiliwa kwa mitandao"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mtandao wa simu haupatikani."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mtandao wa simu haupatikani.\n\nUnganisha kwenye mtandao pasiwaya ili upige simu.\n\n2G imezimwa kwenye kifaa hiki, hali ambayo huenda inaathiri muunganisho wako. Nenda kwenye Mipangilio kisha uwashe \'Ruhusu 2G\' ili uendelee."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mtandao wa simu za mkononi haupatikani. Unganisha kwenye mtandao pasiwaya ili upige simu."</string>
- <string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Ili upige simu, weka nambari sahihi."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mtandao wa simu haupatikani.\n\nUnganisha kwenye mtandao pasiwaya ili upige simu.\n\n2G imezimwa kwenye kifaa hiki, hali ambayo huenda inaathiri muunganisho wako. Nenda kwenye Mipangilio kisha uwashe \'Ruhusu 2G\' ili uendelee."</string>
+ <string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Ili upige simu, weka namba sahihi."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Imeshindwa kupiga simu."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Simu haiwezi kuongezwa kwa sasa. Unaweza kujaribu kuwasiliana kwa kutuma ujumbe."</string>
<string name="incall_error_supp_service_unknown" msgid="8751177117194592623">"Huduma haiwezi kutumika."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Haiwezi kushikilia simu."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Unganisha kwenye mtandao pasiwaya ili upige simu."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Washa kipengele cha kupiga simu kupitia Wi-Fi ili upige simu."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Zima hali ya sateliti ili upige simu."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Ili uweze kupiga simu, kwanza katisha muunganisho wa setilaiti."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Unaweza kutuma na kupokea ujumbe bila mtandao wa simu au Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Maelezo ya dharura"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Mmiliki"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Gusa tena ili uangalie maelezo"</string>
@@ -568,8 +571,8 @@
<string name="emergency_enable_radio_dialog_message" msgid="1695305158151408629">"Inawasha redio..."</string>
<string name="emergency_enable_radio_dialog_retry" msgid="4329131876852608587">"Hakuna huduma. Inajaribu tena..."</string>
<string name="radio_off_during_emergency_call" msgid="8011154134040481609">"Huwezi kuingia katika hali ya ndegeni huku simu ya dharura inaendelea."</string>
- <string name="dial_emergency_error" msgid="825822413209026039">"Haiwezi kupiga simu. <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> si nambari ya dharura."</string>
- <string name="dial_emergency_empty_error" msgid="2785803395047793634">"Haiwezi kupiga simu. Piga nambari ya dharura."</string>
+ <string name="dial_emergency_error" msgid="825822413209026039">"Haiwezi kupiga simu. <xliff:g id="NON_EMERGENCY_NUMBER">%s</xliff:g> si namba ya dharura."</string>
+ <string name="dial_emergency_empty_error" msgid="2785803395047793634">"Haiwezi kupiga simu. Piga namba ya dharura."</string>
<string name="dial_emergency_calling_not_available" msgid="6485846193794727823">"Upigaji simu ya dharura haupatikani"</string>
<string name="pin_puk_system_user_only" msgid="1045147220686867922">"Mmiliki wa kifaa pekee ndiye anaweza kuweka misimbo ya PIN/PUK."</string>
<string name="police_type_description" msgid="2819533883972081757">"Polisi"</string>
@@ -692,7 +695,7 @@
<string name="change_pin_enter_old_pin_header" msgid="853151335217594829">"Thibitisha PIN yako ya awali"</string>
<string name="change_pin_enter_old_pin_hint" msgid="8801292976275169367">"Weka PIN yako ya ujumbe wa sauti ili uendelee."</string>
<string name="change_pin_enter_new_pin_header" msgid="4739465616733486118">"Weka PIN mpya"</string>
- <string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"PIN lazima iwe na nambari <xliff:g id="MIN">%1$d</xliff:g>-<xliff:g id="MAX">%2$d</xliff:g>."</string>
+ <string name="change_pin_enter_new_pin_hint" msgid="2326038476516364210">"PIN lazima iwe na namba <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">"Thibitisha PIN yako"</string>
<string name="change_pin_confirm_pins_dont_match" msgid="305164501222587215">"PIN hazilingani"</string>
<string name="change_pin_succeeded" msgid="2504705600693014403">"PIN ya ujumbe wa sauti imesasishwa"</string>
@@ -716,55 +719,55 @@
<string name="clh_callFailed_simError_txt" msgid="5128538525762326413">"Imeshindwa kufikia SIM kadi"</string>
<string name="clh_incall_error_out_of_service_txt" msgid="2736010617446749869">"Mtandao wa simu za mkononi haupatikani"</string>
<string name="clh_callFailed_satelliteEnabled_txt" msgid="1675517238240377396">"Hali ya sateliti imewashwa"</string>
- <string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"Nambari ya simu unayojaribu kupiga ina hitilafu. Msimbo wa hitilafu nambari 1."</string>
- <string name="clh_callFailed_no_route_to_destination_txt" msgid="4805015149822352308">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 3."</string>
- <string name="clh_callFailed_channel_unacceptable_txt" msgid="4062754579408613021">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 6."</string>
- <string name="clh_callFailed_operator_determined_barring_txt" msgid="4202077821465974286">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 8."</string>
- <string name="clh_callFailed_normal_call_clearing_txt" msgid="5677987959062976462">"Imeshidwa kupiga simu. Msimbo wa hitilafu nambari 16."</string>
+ <string name="clh_callFailed_unassigned_number_txt" msgid="141967660286695682">"Nambari ya simu unayojaribu kupiga ina hitilafu. Msimbo wa hitilafu namba 1."</string>
+ <string name="clh_callFailed_no_route_to_destination_txt" msgid="4805015149822352308">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 3."</string>
+ <string name="clh_callFailed_channel_unacceptable_txt" msgid="4062754579408613021">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 6."</string>
+ <string name="clh_callFailed_operator_determined_barring_txt" msgid="4202077821465974286">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 8."</string>
+ <string name="clh_callFailed_normal_call_clearing_txt" msgid="5677987959062976462">"Imeshidwa kupiga simu. Msimbo wa hitilafu namba 16."</string>
<string name="clh_callFailed_user_busy_txt" msgid="8886432858568086854">"Mtumiaji ana shughuli"</string>
<string name="clh_callFailed_no_user_responding_txt" msgid="341100226919865128">"Mtumiaji hajibu"</string>
- <string name="clh_callFailed_user_alerting_txt" msgid="896082976264427969">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 19."</string>
+ <string name="clh_callFailed_user_alerting_txt" msgid="896082976264427969">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 19."</string>
<string name="clh_callFailed_call_rejected_txt" msgid="3439435671153341709">"Simu imekataliwa"</string>
<string name="clh_callFailed_number_changed_txt" msgid="2868476949771441667">"Nambari imebadilishwa"</string>
- <string name="clh_callFailed_pre_emption_txt" msgid="8887998866342162724">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 25."</string>
- <string name="clh_callFailed_non_selected_user_clearing_txt" msgid="4804529874810197550">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 26."</string>
- <string name="clh_callFailed_destination_out_of_order_txt" msgid="1130697076352728824">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 27."</string>
- <string name="clh_callFailed_invalid_number_format_txt" msgid="3171016382987224989">"Muundo usio sahihi wa nambari (nambari haijakamilika)"</string>
- <string name="clh_callFailed_facility_rejected_txt" msgid="1054386430010898993">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 29."</string>
- <string name="clh_callFailed_response_to_STATUS_ENQUIRY_txt" msgid="2763172551412307536">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 30."</string>
- <string name="clh_callFailed_normal_unspecified_txt" msgid="978119938935737419">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 31."</string>
- <string name="clh_callFailed_no_circuit_available_txt" msgid="1519684050419134605">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 34."</string>
- <string name="clh_callFailed_network_out_of_order_txt" msgid="8689826504394592289">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 38."</string>
- <string name="clh_callFailed_temporary_failure_txt" msgid="5065091554509067874">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 41."</string>
- <string name="clh_callFailed_switching_equipment_congestion_txt" msgid="8681599376741988769">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 42."</string>
- <string name="clh_callFailed_access_information_discarded_txt" msgid="2476199425130545428">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 43."</string>
- <string name="clh_callFailed_requested_circuit_txt" msgid="7497497808928490219">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 44."</string>
- <string name="clh_callFailed_resources_unavailable_unspecified_txt" msgid="144010529672928445">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 47."</string>
- <string name="clh_callFailed_quality_of_service_unavailable_txt" msgid="4650329342288289290">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 49."</string>
- <string name="clh_callFailed_requested_facility_not_subscribed_txt" msgid="9107977008516882170">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 50."</string>
- <string name="clh_callFailed_incoming_calls_barred_within_the_CUG_txt" msgid="501037491908315591">"Imeshidwa kupiga simu. Msimbo wa hitilafu nambari 55."</string>
- <string name="clh_callFailed_bearer_capability_not_authorized_txt" msgid="4344366517528362620">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 57."</string>
- <string name="clh_callFailed_bearer_capability_not_presently_available_txt" msgid="1436957294571545381">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 58."</string>
- <string name="clh_callFailed_service_or_option_not_available_unspecified_txt" msgid="2149878874722675428">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 63."</string>
- <string name="clh_callFailed_bearer_service_not_implemented_txt" msgid="1074983013965612410">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 65."</string>
- <string name="clh_callFailed_ACM_equal_to_or_greater_than_ACMmax_txt" msgid="7889034195264205333">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 68."</string>
- <string name="clh_callFailed_requested_facility_not_implemented_txt" msgid="7996646684699167978">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 69."</string>
- <string name="clh_callFailed_only_restricted_digital_information_bearer_capability_is_available_txt" msgid="2358958110447385682">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 70."</string>
- <string name="clh_callFailed_service_or_option_not_implemented_unspecified_txt" msgid="3046428509531159481">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 79."</string>
- <string name="clh_callFailed_invalid_transaction_identifier_value_txt" msgid="1727401871777396619">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 81."</string>
- <string name="clh_callFailed_user_not_member_of_CUG_txt" msgid="442282135105229307">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 87."</string>
- <string name="clh_callFailed_incompatible_destination_txt" msgid="5900394706344969020">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 88."</string>
- <string name="clh_callFailed_invalid_transit_network_selection_txt" msgid="6274621838349037741">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 91."</string>
- <string name="clh_callFailed_semantically_incorrect_message_txt" msgid="7000705190197981937">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 95."</string>
- <string name="clh_callFailed_invalid_mandatory_information_txt" msgid="3609204152671052123">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 96."</string>
- <string name="clh_callFailed_message_type_non_existent_or_not_implemented_txt" msgid="1552110431052032814">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 97."</string>
- <string name="clh_callFailed_message_type_not_compatible_with_protocol_state_txt" msgid="7717048934226300032">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 98."</string>
- <string name="clh_callFailed_information_element_non_existent_or_not_implemented_txt" msgid="8931396541061612169">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 99."</string>
- <string name="clh_callFailed_conditional_IE_error_txt" msgid="4630685477888727741">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 100."</string>
- <string name="clh_callFailed_message_not_compatible_with_protocol_state_txt" msgid="3014075977395922947">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 101."</string>
- <string name="clh_callFailed_recovery_on_timer_expiry_txt" msgid="5637581978978731672">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 102."</string>
- <string name="clh_callFailed_protocol_Error_unspecified_txt" msgid="9203320572562697755">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 111."</string>
- <string name="clh_callFailed_interworking_unspecified_txt" msgid="7969686413930847182">"Imeshindwa kupiga simu. Msimbo wa hitilafu nambari 127."</string>
+ <string name="clh_callFailed_pre_emption_txt" msgid="8887998866342162724">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 25."</string>
+ <string name="clh_callFailed_non_selected_user_clearing_txt" msgid="4804529874810197550">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 26."</string>
+ <string name="clh_callFailed_destination_out_of_order_txt" msgid="1130697076352728824">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 27."</string>
+ <string name="clh_callFailed_invalid_number_format_txt" msgid="3171016382987224989">"Muundo usio sahihi wa namba (namba haijakamilika)"</string>
+ <string name="clh_callFailed_facility_rejected_txt" msgid="1054386430010898993">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 29."</string>
+ <string name="clh_callFailed_response_to_STATUS_ENQUIRY_txt" msgid="2763172551412307536">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 30."</string>
+ <string name="clh_callFailed_normal_unspecified_txt" msgid="978119938935737419">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 31."</string>
+ <string name="clh_callFailed_no_circuit_available_txt" msgid="1519684050419134605">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 34."</string>
+ <string name="clh_callFailed_network_out_of_order_txt" msgid="8689826504394592289">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 38."</string>
+ <string name="clh_callFailed_temporary_failure_txt" msgid="5065091554509067874">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 41."</string>
+ <string name="clh_callFailed_switching_equipment_congestion_txt" msgid="8681599376741988769">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 42."</string>
+ <string name="clh_callFailed_access_information_discarded_txt" msgid="2476199425130545428">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 43."</string>
+ <string name="clh_callFailed_requested_circuit_txt" msgid="7497497808928490219">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 44."</string>
+ <string name="clh_callFailed_resources_unavailable_unspecified_txt" msgid="144010529672928445">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 47."</string>
+ <string name="clh_callFailed_quality_of_service_unavailable_txt" msgid="4650329342288289290">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 49."</string>
+ <string name="clh_callFailed_requested_facility_not_subscribed_txt" msgid="9107977008516882170">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 50."</string>
+ <string name="clh_callFailed_incoming_calls_barred_within_the_CUG_txt" msgid="501037491908315591">"Imeshidwa kupiga simu. Msimbo wa hitilafu namba 55."</string>
+ <string name="clh_callFailed_bearer_capability_not_authorized_txt" msgid="4344366517528362620">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 57."</string>
+ <string name="clh_callFailed_bearer_capability_not_presently_available_txt" msgid="1436957294571545381">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 58."</string>
+ <string name="clh_callFailed_service_or_option_not_available_unspecified_txt" msgid="2149878874722675428">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 63."</string>
+ <string name="clh_callFailed_bearer_service_not_implemented_txt" msgid="1074983013965612410">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 65."</string>
+ <string name="clh_callFailed_ACM_equal_to_or_greater_than_ACMmax_txt" msgid="7889034195264205333">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 68."</string>
+ <string name="clh_callFailed_requested_facility_not_implemented_txt" msgid="7996646684699167978">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 69."</string>
+ <string name="clh_callFailed_only_restricted_digital_information_bearer_capability_is_available_txt" msgid="2358958110447385682">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 70."</string>
+ <string name="clh_callFailed_service_or_option_not_implemented_unspecified_txt" msgid="3046428509531159481">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 79."</string>
+ <string name="clh_callFailed_invalid_transaction_identifier_value_txt" msgid="1727401871777396619">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 81."</string>
+ <string name="clh_callFailed_user_not_member_of_CUG_txt" msgid="442282135105229307">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 87."</string>
+ <string name="clh_callFailed_incompatible_destination_txt" msgid="5900394706344969020">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 88."</string>
+ <string name="clh_callFailed_invalid_transit_network_selection_txt" msgid="6274621838349037741">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 91."</string>
+ <string name="clh_callFailed_semantically_incorrect_message_txt" msgid="7000705190197981937">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 95."</string>
+ <string name="clh_callFailed_invalid_mandatory_information_txt" msgid="3609204152671052123">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 96."</string>
+ <string name="clh_callFailed_message_type_non_existent_or_not_implemented_txt" msgid="1552110431052032814">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 97."</string>
+ <string name="clh_callFailed_message_type_not_compatible_with_protocol_state_txt" msgid="7717048934226300032">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 98."</string>
+ <string name="clh_callFailed_information_element_non_existent_or_not_implemented_txt" msgid="8931396541061612169">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 99."</string>
+ <string name="clh_callFailed_conditional_IE_error_txt" msgid="4630685477888727741">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 100."</string>
+ <string name="clh_callFailed_message_not_compatible_with_protocol_state_txt" msgid="3014075977395922947">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 101."</string>
+ <string name="clh_callFailed_recovery_on_timer_expiry_txt" msgid="5637581978978731672">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 102."</string>
+ <string name="clh_callFailed_protocol_Error_unspecified_txt" msgid="9203320572562697755">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 111."</string>
+ <string name="clh_callFailed_interworking_unspecified_txt" msgid="7969686413930847182">"Imeshindwa kupiga simu. Msimbo wa hitilafu namba 127."</string>
<string name="labelCallBarring" msgid="4180377113052853173">"Kuzuia upigaji simu"</string>
<string name="sum_call_barring_enabled" msgid="5184331188926370824">"Washa"</string>
<string name="sum_call_barring_disabled" msgid="5699448000600153096">"Zima"</string>
@@ -802,7 +805,7 @@
<string name="supp_service_notification_call_deflected" msgid="4980942818105909813">"Simu unayopiga imeelekezwa kwingine."</string>
<string name="supp_service_notification_call_forwarded" msgid="7102930311735433088">"Simu imesambazwa."</string>
<string name="supp_service_notification_call_waiting" msgid="4577403881609445324">"Simu inasubiri."</string>
- <string name="supp_service_clir_suppression_rejected" msgid="6105737020194776121">"Ombi la kuzuia nambari limekataliwa."</string>
+ <string name="supp_service_clir_suppression_rejected" msgid="6105737020194776121">"Ombi la kuzuia namba limekataliwa."</string>
<string name="supp_service_closed_user_group_call" msgid="2811636666505250689">"Simu kwenye kikundi cha watumiaji teule."</string>
<string name="supp_service_incoming_calls_barred" msgid="2034627421274447674">"Simu zinazoingia zimezuiwa."</string>
<string name="supp_service_outgoing_calls_barred" msgid="5205725332394087112">"Simu unazopiga zimezuiwa."</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml
index 620d4c0..cb4c887 100644
--- a/res/values-ta/strings.xml
+++ b/res/values-ta/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"வழக்கமான அழைப்பிற்கு, அவசரகாலத் திரும்ப அழைக்கும் பயன்முறையிலிருந்து வெளியேறவும்."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"நெட்வொர்க்கில் பதிவுசெய்யப்படவில்லை."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"மொபைல் நெட்வொர்க் கிடைக்கவில்லை."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"மொபைல் நெட்வொர்க் கிடைக்கவில்லை.\n\nஅழைப்பைச் செய்ய வயர்லெஸ் நெட்வொர்க்குடன் இணைக்கவும்.\n\nஇந்தச் சாதனத்தில் 2G முடக்கப்பட்டுள்ளதால் இணைப்பு பாதிக்கப்பட்டிருக்கலாம். தொடர, அமைப்புகளுக்குச் சென்று \'2G சேவையை அனுமதி\' என்பதை இயக்கவும்."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"மொபைல் நெட்வொர்க் கிடைக்கவில்லை. அழைக்க, வயர்லெஸ் நெட்வொர்க்குடன் இணைக்கவும்."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"மொபைல் நெட்வொர்க் கிடைக்கவில்லை.\n\nஅழைப்பைச் செய்ய வயர்லெஸ் நெட்வொர்க்குடன் இணைக்கவும்.\n\nஇந்தச் சாதனத்தில் 2G முடக்கப்பட்டுள்ளதால் இணைப்பு பாதிக்கப்பட்டிருக்கலாம். தொடர, அமைப்புகளுக்குச் சென்று \'2G சேவையை அனுமதி\' என்பதை இயக்கவும்."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"அழைக்க, சரியான எண்ணை உள்ளிடவும்."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"அழைப்பு தோல்வியடைந்தது."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"தற்போது அழைக்க முடியவில்லை. செய்தியை அனுப்பி, தொடர்புகொள்ள முயலவும்."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"அழைப்புகளை ஹோல்டு செய்ய முடியாது."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"அழைக்க, வயர்லெஸ் நெட்வொர்க்குடன் இணைக்கவும்."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"அழைக்க, வைஃபை அழைப்பை இயக்கவும்."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"அழைப்பை மேற்கொள்ள சாட்டிலைட் பயன்முறையை முடக்கவும்."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"அழைக்க, முதலில் சாட்டிலைட் இணைப்பை ஆஃப் செய்யவும்."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"மொபைல்/வைஃபை நெட்வொர்க் இல்லாமல் நீங்கள் மெசேஜ்களை அனுப்பலாம் பெறலாம்."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"அவசரத் தகவல்"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"உரிமையாளர்"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"தகவலைப் பார்க்க, மீண்டும் தட்டவும்"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"சிம் முகவரிப் புத்தகத்தைக் காட்டு"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"நிலையான அழைப்பு எண்களைக் காட்டு"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"சேவை அழைப்பு எண்களைக் காட்டு"</string>
diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml
index 45417a6..f6acedf 100644
--- a/res/values-te/strings.xml
+++ b/res/values-te/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"సాధారణ కాల్ చేయడానికి అత్యవసర కాల్బ్యాక్ మోడ్ నుండి నిష్క్రమించండి."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"నెట్వర్క్లో నమోదు కాలేదు."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"మొబైల్ నెట్వర్క్ అందుబాటులో లేదు."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"మొబైల్ నెట్వర్క్ అందుబాటులో లేదు.\n\nకాల్ చేయడానికి వైర్లెస్ నెట్వర్క్కు కనెక్ట్ చేయండి.\n\nఈ పరికరంలో 2G డిజేబుల్ చేయబడింది, ఇది మీ కనెక్టివిటీని ప్రభావితం చేస్తూ ఉండవచ్చు. సెట్టింగ్లకు వెళ్లి, \'కొనసాగించడానికి 2Gని అనుమతించండి\'ని ఎనేబుల్ చేయండి."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"మొబైల్ నెట్వర్క్ అందుబాటులో లేదు. కాల్ చేయడానికి వైర్లెస్ నెట్వర్క్కు కనెక్ట్ చేయండి."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"మొబైల్ నెట్వర్క్ అందుబాటులో లేదు.\n\nకాల్ చేయడానికి వైర్లెస్ నెట్వర్క్కు కనెక్ట్ చేయండి.\n\nఈ పరికరంలో 2G డిజేబుల్ చేయబడింది, ఇది మీ కనెక్టివిటీని ప్రభావితం చేస్తూ ఉండవచ్చు. సెట్టింగ్లకు వెళ్లి, \'కొనసాగించడానికి 2Gని అనుమతించండి\'ని ఎనేబుల్ చేయండి."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"కాల్ చేయడానికి, చెల్లుబాటు అయ్యే నంబర్ను నమోదు చేయండి."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"కాల్ విఫలమైంది."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"ఈ సమయంలో కాల్ జోడించబడదు. మీరు మెసేజ్ను పంపడం ద్వారా సంప్రదించవచ్చు."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"కాల్స్ను హోల్డ్ చేయలేరు."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"కాల్ చేయడానికి వైర్లెస్ నెట్వర్క్కు కనెక్ట్ చేయండి."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"కాల్ను చేయడానికి Wi-Fi కాలింగ్ను ప్రారంభించండి."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"కాల్ చేయడానికి ఉపగ్రహ మోడ్ను డిజేబుల్ చేయండి."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"కాల్ చేయడానికి, ముందుగా శాటిలైట్ కనెక్షన్ను ముగించండి."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"మీరు మొబైల్ లేదా Wi-Fi నెట్వర్క్ లేకుండా మెసేజ్లను పంపవచ్చు, స్వీకరించవచ్చు."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"అత్యవసర సమాచారం"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"యజమాని"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"సమాచారాన్ని చూడడానికి మళ్లీ నొక్కండి"</string>
@@ -669,7 +672,7 @@
<string name="enable_video_calling_title" msgid="7246600931634161830">"వీడియో కాలింగ్ని ఆన్ చేయండి"</string>
<string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"వీడియో కాలింగ్ను ఆన్ చేయడానికి, మీరు నెట్వర్క్ సెట్టింగ్ల్లో మెరుగుపరిచిన 4G LTE మోడ్ను ప్రారంభించాలి."</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"నెట్వర్క్ సెట్టింగ్లు"</string>
- <string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"మూసివేయి"</string>
+ <string name="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>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml
index 1ada10d..8d78212 100644
--- a/res/values-th/strings.xml
+++ b/res/values-th/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"โปรดออกจากโหมดการโทรกลับกรณีฉุกเฉินเพื่อโทรไปยังหมายเลขที่ไม่ใช่หมายเลขฉุกเฉิน"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"ยังไม่ได้ลงทะเบียนบนเครือข่าย"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"เครือข่ายมือถือใช้งานไม่ได้"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"เครือข่ายมือถือไม่พร้อมใช้งาน\n\nเชื่อมต่อเครือข่ายไร้สายเพื่อโทรออก\n\nอุปกรณ์นี้ปิดใช้งาน 2G อยู่ซึ่งอาจส่งผลต่อการเชื่อมต่อ โปรดไปที่การตั้งค่าและเปิด \"อนุญาตให้ใช้ 2G\" เพื่อดำเนินการต่อ"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"เครือข่ายมือถือไม่พร้อมใช้งาน โปรดเชื่อมต่อเครือข่ายไร้สายเพื่อโทรออก"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"เครือข่ายมือถือไม่พร้อมใช้งาน\n\nเชื่อมต่อเครือข่ายไร้สายเพื่อโทรออก\n\nอุปกรณ์นี้ปิดใช้งาน 2G อยู่ซึ่งอาจส่งผลต่อการเชื่อมต่อ โปรดไปที่การตั้งค่าและเปิด \"อนุญาตให้ใช้ 2G\" เพื่อดำเนินการต่อ"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"หากต้องการโทรออก โปรดป้อนหมายเลขที่ถูกต้อง"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"การโทรล้มเหลว"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"เพิ่มการโทรไม่ได้ในขณะนี้ คุณสามารถพยายามติดต่อได้โดยการส่งข้อความ"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"ไม่สามารถถือสายรอได้"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"เชื่อมต่อเครือข่ายไร้สายเพื่อโทรออก"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"เปิดใช้การโทรผ่าน Wi-Fi เพื่อโทรออก"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"ปิดโหมดดาวเทียมเพื่อโทรออก"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"หากต้องการโทรออก ให้หยุดการเชื่อมต่อดาวเทียมก่อน"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"คุณรับส่งข้อความผ่านดาวเทียมได้โดยไม่ต้องใช้เครือข่ายมือถือหรือ Wi-Fi"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"ข้อมูลสำหรับกรณีฉุกเฉิน"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"เจ้าของ"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"แตะอีกครั้งเพื่อดูข้อมูล"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<string name="radioInfo_menu_viewADN" msgid="4533179730908559846">"ดูสมุดที่อยู่ของซิม"</string>
<string name="radioInfo_menu_viewFDN" msgid="1847236480527032061">"ดูการจำกัดหมายเลขโทรออก"</string>
<string name="radioInfo_menu_viewSDN" msgid="2613431584522392842">"ดูหมายเลขรับบริการโทรออก"</string>
diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml
index 81d5bd3..578c3f4 100644
--- a/res/values-tl/strings.xml
+++ b/res/values-tl/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Lumabas sa emergency callback mode upang makapagsagawa ng hindi pang-emergency na pagtawag."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Hindi nakarehistro sa network."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Hindi available ang mobile network."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Hindi available ang mobile network.\n\nKumonekta sa wireless network para tumawag.\n\nNaka-disable ang 2G sa device na ito, na posibleng nakakaapekto sa iyong pagkakonekta. Pumunta sa Mga Setting at i-enable ang Payagan ang 2G para magpatuloy."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Hindi available ang mobile network. Kumonekta sa isang wireless network upang tumawag."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Hindi available ang mobile network.\n\nKumonekta sa wireless network para tumawag.\n\nNaka-disable ang 2G sa device na ito, na posibleng nakakaapekto sa iyong pagkakonekta. Pumunta sa Mga Setting at i-enable ang Payagan ang 2G para magpatuloy."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Upang tumawag, maglagay ng wastong numero."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Nabigo ang tawag."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Hindi maidaragdag ang tawag na ito sa ngayon. Maaari mong subukang makipag-ugnayan sa pamamagitan ng pagpapadala ng isang mensahe."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Hindi makakapag-hold ng mga tawag."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Kumonekta sa isang wireless network upang makatawag."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"I-enable ang pagtawag sa Wi-Fi upang tumawag."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"I-disable ang satellite mode para tumawag."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Para tumawag, wakasan muna ang koneksyon sa satellite."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Puwede kang magpadala at tumanggap ng mga mensahe nang walang mobile o Wi-Fi network."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Impormasyong pang-emergency"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"May-ari"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"I-tap muli para tingnan ang impormasyon"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml
index 40eb5e7..a5757ce 100644
--- a/res/values-tr/strings.xml
+++ b/res/values-tr/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Acil durum çağrısı dışında bir çağrı yapmak için acil durumda geri aranma modundan çıkın."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ağda kayıtlı değil."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mobil ağ kullanılamıyor."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobil ağ kullanılamıyor.\n\nArama yapmak için kablosuz ağa bağlanın.\n\nBu cihazda 2G devre dışı olduğundan bağlantınız etkilenebilir. Devam etmek için Ayarlar\'a gidip \"2G\'ye izin ver\" ayarını etkinleştirin."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobil ağ kullanılamıyor. Telefon etmek için kablosuz ağa bağlanın."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobil ağ kullanılamıyor.\n\nArama yapmak için kablosuz ağa bağlanın.\n\nBu cihazda 2G devre dışı olduğundan bağlantınız etkilenebilir. Devam etmek için Ayarlar\'a gidip \"2G\'ye izin ver\" ayarını etkinleştirin."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Arama yapmak için geçerli bir numara girin."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Sesli arama başarısız oldu."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Çağrı şu anda eklenemiyor. Mesaj göndererek ulaşmayı deneyebilirsiniz."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Çağrılar beklemeye alınamıyor."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Telefon etmek için kablosuz ağa bağlanın."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Telefon etmek için Kablosuz çağrı\'yı etkinleştirin."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Arama yapmak için uydu modunu devre dışı bırakın."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Arama yapmak için önce uydu bağlantısını sonlandırın."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Mobil veya kablosuz ağa bağlı olmadan mesaj alıp gönderebilirsiniz."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Acil durum bilgisi"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Sahip"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Bilgileri görüntülemek için tekrar dokunun"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index 345d8e7..ff4f765 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Щоб зателефонувати на звичайний номер, вимкніть режим екстрених викликів."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Не зареєстровано в мережі."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Мобільна мережа недоступна."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Мобільна мережа недоступна.\n\nЩоб зателефонувати, підключіться до бездротової мережі.\n\nНа цьому пристрої вимкнено 2G, що може вплинути на з’єднання. Щоб продовжити, перейдіть у налаштування й увімкніть \"Дозволити 2G\"."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Мобільна мережа недоступна. Щоб зателефонувати, під’єднайтеся до бездротової мережі."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Мобільна мережа недоступна.\n\nЩоб зателефонувати, підключіться до бездротової мережі.\n\nНа цьому пристрої вимкнено 2G, що може вплинути на з’єднання. Щоб продовжити, перейдіть у налаштування й увімкніть \"Дозволити 2G\"."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Щоб зателефонувати, введіть дійсний номер."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Не вдалося здійснити виклик."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Не вдається додати виклик. Спробуйте надіслати повідомлення."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Не можна призупиняти виклики."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Щоб зателефонувати, під’єднайтеся до бездротової мережі."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Щоб мати змогу телефонувати, увімкніть виклики через Wi-Fi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Щоб зателефонувати, вимкніть режим супутника."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Щоб зателефонувати, спершу відключіть супутниковий зв’язок."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Ви можете надсилати й отримувати повідомлення, не використовуючи Wi-Fi або мобільну мережу."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Дані для екстрених випадків"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Власник"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Торкніться ще раз, щоб переглянути відомості"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml
index 520f493..1d67bbb 100644
--- a/res/values-ur/strings.xml
+++ b/res/values-ur/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"غیر ایمرجنسی کال کرنے کیلئے ایمرجنسی کال بیک موڈ سے اخراج کریں۔"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"نیٹ ورک پر رجسٹرڈ نہیں ہے۔"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"موبائل نیٹ ورک دستیاب نہیں ہے۔"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"موبائل نیٹ ورک دستیاب نہیں ہے۔\n\nکال کرنے کے لیے وائرلیس نیٹ ورک سے منسلک ہوں۔\n\n2G اس آلے پر غیر فعال ہے، جو آپ کی کنیکٹیوٹی کو متاثر کر سکتا ہے۔ ترتیبات پر جائیں اور \'2G کو جاری رکھنے کی اجازت دیں\' کو فعال کریں۔"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"موبائل نیٹ ورک دستیاب نہیں ہے۔ کال کرنے کیلئے کسی وائرلیس نیٹ ورک سے منسلک ہوں۔"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"موبائل نیٹ ورک دستیاب نہیں ہے۔\n\nکال کرنے کے لیے وائرلیس نیٹ ورک سے منسلک ہوں۔\n\n2G اس آلے پر غیر فعال ہے، جو آپ کی کنیکٹیوٹی کو متاثر کر سکتا ہے۔ ترتیبات پر جائیں اور \'2G کو جاری رکھنے کی اجازت دیں\' کو فعال کریں۔"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"کال کرنے کیلئے، ایک درست نمبر درج کریں۔"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"کال ناکام ہوگئی۔"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"اس وقت کال شامل نہیں کی جا سکتی۔ آپ ایک پیغام بھیج کر رابطہ کرنے کی کوشش کر سکتے ہیں۔"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"کالز کو ہولڈ نہیں کیا جا سکتا۔"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"کال کرنے کیلئے کسی وائرلیس نیٹ ورک سے منسلک ہوں۔"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"کال کرنے کیلئے Wi-Fi کالنگ فعال کریں۔"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"کال کرنے کیلئے سیٹلائٹ موڈ کو غیرفعال کریں"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"کال کرنے کے لیے، پہلے سیٹلائٹ کنکشن ختم کریں۔"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"آپ موبائل یا Wi-Fi نیٹ ورک کے بغیر پیغامات بھیج اور موصول کر سکتے ہیں۔"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"ایمرجنسی معلومات"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"مالک"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"معلومات دیکھنے کیلئے دوبارہ تھپتھپائیں"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml
index 19d5563..22d7094 100644
--- a/res/values-uz/strings.xml
+++ b/res/values-uz/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Odatiy qo‘ng‘iroq qilish uchun favqulodda qayta qo‘ng‘iroq rejimidan chiqing."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Tarmoqda ro‘yxatdan o‘tmagan."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Uyali tarmoq mavjud emas."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Mobil tarmoq ishlamayapti.\n\nTelefon qilish uchun simsiz tarmoqqa ulaning.\n\nBu qurilmada 2G yoqilmagan va aloqaga taʼsir qilishi mumkin. Davom etish uchun Sozlamalar orqali 2G ulanishga ruxsat bering."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Mobil tarmoqdan foydalanib bo‘lmaydi. Qo‘ng‘iroq qilish uchun Wi-Fi tarmog‘iga ulaning."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Mobil tarmoq ishlamayapti.\n\nTelefon qilish uchun simsiz tarmoqqa ulaning.\n\nBu qurilmada 2G yoqilmagan va aloqaga taʼsir qilishi mumkin. Davom etish uchun Sozlamalar orqali 2G ulanishga ruxsat bering."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Qo‘ng‘iroq qilish uchun raqamni to‘g‘ri kiriting."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Chaqiruv amalga oshmadi."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Qo‘ng‘iroq qilib bo‘lmayapti. Xabar yuborib ko‘ring."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Qo‘ng‘iroqlarni ushlab turib bo‘lmadi."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Qo‘ng‘iroq qilish uchun simsiz tarmoqqa ulaning"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Qo‘ng‘iroq qilish uchun Wi-Fi qo‘ng‘iroqlar funksiyasini yoqing."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Telefon qilish uchun sputnik rejimini faolsizlantiring."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Telefon qilish uchun avval sputnik orqali aloqani uzing."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Mobil yoki Wi-Fi tarmoqsiz xabarlarni yuborish va qabul qilish mumkin."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Favqulodda vaziyatlar uchun axborot"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Egasi"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Axborotni ochish uchun yana bir marta bosing"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml
index ebaf17f..11f8645 100644
--- a/res/values-vi/strings.xml
+++ b/res/values-vi/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Thoát khỏi chế độ gọi lại khẩn cấp để thực hiện cuộc gọi không khẩn cấp."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Chưa được đăng ký trên mạng."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Mạng di động không khả dụng."</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Không có mạng di động.\n\nHãy kết nối với mạng không dây để gọi điện.\n\n2G đã bị tắt trên thiết bị này. Điều này có thể ảnh hưởng đến khả năng kết nối của bạn. Chuyển đến phần Cài đặt rồi bật tuỳ chọn Cho phép 2G để tiếp tục."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Hiện không có mạng di động. Hãy kết nối với mạng không dây để thực hiện cuộc gọi."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Không có mạng di động.\n\nHãy kết nối với mạng không dây để gọi điện.\n\n2G đã bị tắt trên thiết bị này. Điều này có thể ảnh hưởng đến khả năng kết nối của bạn. Chuyển đến phần Cài đặt rồi bật cài đặt Cho phép 2G để tiếp tục."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Để thực hiện cuộc gọi, hãy nhập một số hợp lệ."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Cuộc gọi không thành công."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Không thể thêm cuộc gọi tại thời điểm này. Bạn có thể cố gắng liên hệ bằng cách gửi tin nhắn."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Không thể giữ cuộc gọi."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Kết nối với mạng không dây để thực hiện cuộc gọi."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Bật gọi điện qua Wi-Fi để thực hiện cuộc gọi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Hãy tắt chế độ vệ tinh để gọi điện."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Để gọi điện, trước tiên hãy tắt kết nối vệ tinh."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Bạn có thể gửi và nhận tin nhắn mà không cần mạng di động hoặc mạng Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Thông tin khẩn cấp"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Chủ sở hữu"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Nhấn lại để xem thông tin"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index f439c6b..3bd3f35 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"要拨打非紧急电话,请先退出紧急回拨模式。"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"尚未注册网络。"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"无法连接到移动网络"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"移动网络不可用。\n\n需连接至无线网络才能拨打电话。\n\n此设备已停用 2G,这可能会影响您的连接。如需继续操作,请前往“设置”并启用“允许启用 2G”。"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"移动网络不可用。需连接至无线网络才能拨打电话。"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"移动网络不可用。\n\n需连接至无线网络才能拨打电话。\n\n此设备已停用 2G,这可能会影响您的连接。如需继续操作,请前往“设置”并启用“允许启用 2G”。"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"要拨打电话,请输入有效的电话号码。"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"无法通话。"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"暂时无法拨打电话。您可以尝试通过发送信息来联系对方。"</string>
@@ -557,11 +559,12 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"无法保持通话。"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"需连接至无线网络才能拨打电话。"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"启用 WLAN 通话功能以拨打电话。"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"停用卫星模式才能拨打电话。"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"如要拨打电话,请先结束卫星连接。"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"您无需使用移动网络或 Wi-Fi 网络便能收发消息。"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"急救信息"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"所有者"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"再次点按即可查看信息"</string>
- <string name="emergency_enable_radio_dialog_title" msgid="2667568200755388829">"紧急呼救"</string>
+ <string name="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>
@@ -670,7 +673,7 @@
<string name="enable_video_calling_dialog_msg" msgid="7141478720386203540">"要开启视频通话功能,您需要在网络设置中启用增强型 4G LTE 模式。"</string>
<string name="enable_video_calling_dialog_settings" msgid="8697890611305307110">"网络设置"</string>
<string name="enable_video_calling_dialog_close" msgid="4298929725917045270">"关闭"</string>
- <string name="sim_label_emergency_calls" msgid="9078241989421522310">"紧急呼救"</string>
+ <string name="sim_label_emergency_calls" msgid="9078241989421522310">"紧急呼叫"</string>
<string name="sim_description_emergency_calls" msgid="5146872803938897296">"只能拨打紧急呼救电话"</string>
<string name="sim_description_default" msgid="7474671114363724971">"SIM 卡,插槽:<xliff:g id="SLOT_ID">%s</xliff:g>"</string>
<string name="accessibility_settings_activity_title" msgid="7883415189273700298">"无障碍功能"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
@@ -853,7 +858,7 @@
<string name="radio_info_ims_reg_status" msgid="25582845222446390">"IMS 注册:<xliff:g id="STATUS">%1$s</xliff:g>\nLTE 语音通话:<xliff:g id="AVAILABILITY_0">%2$s</xliff:g>\nWLAN 语音通话:<xliff:g id="AVAILABILITY_1">%3$s</xliff:g>\n视频通话:<xliff:g id="AVAILABILITY_2">%4$s</xliff:g>\nUT 接口:<xliff:g id="AVAILABILITY_3">%5$s</xliff:g>"</string>
<string name="radioInfo_service_in" msgid="45753418231446400">"服务中"</string>
<string name="radioInfo_service_out" msgid="287972405416142312">"不在服务区"</string>
- <string name="radioInfo_service_emergency" msgid="4763879891415016848">"只能拨打紧急呼救电话"</string>
+ <string name="radioInfo_service_emergency" msgid="4763879891415016848">"只能拨打紧急呼叫电话"</string>
<string name="radioInfo_service_off" msgid="3456583511226783064">"关闭无线装置"</string>
<string name="radioInfo_roaming_in" msgid="3156335577793145965">"漫游"</string>
<string name="radioInfo_roaming_not" msgid="1904547918725478110">"未使用漫游服务"</string>
diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml
index 0fadc35..f3e2633 100644
--- a/res/values-zh-rHK/strings.xml
+++ b/res/values-zh-rHK/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"離開緊急回撥模式即可撥打非緊急電話。"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"未在網絡上完成註冊。"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"無法使用流動網絡。"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"無法使用流動網絡。\n\n必須連接無線網絡才可打電話。\n\n此裝置已停用 2G,可能影響到裝置的連接性。請先前往「設定」開啟「允許 2G」再試。"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"無法使用流動網絡。請連接無線網絡,以撥打電話。"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"無法使用流動網絡。\n\n請連接無線網絡,以撥打電話。\n\n2G 已在此裝置停用,這可能會影響裝置的連接性。請前往「設定」並開啟「允許 2G」以繼續。"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"要撥打電話,請輸入有效的號碼。"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"無法接通。"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"目前無法新增通話。你可以改以傳送短訊聯絡對方。"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"無法保留通話。"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"連接無線網絡,以撥打電話。"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"啟用 Wi-Fi 通話功能以撥打電話。"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"如要撥打電話,請停用衛星模式。"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"如要撥打電話,請先中斷衛星連接。"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"你可在沒有流動/Wi-Fi 網絡的情況下收發訊息。"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"緊急資料"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"擁有者"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"再次輕按即可查看資訊"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
index c2aa76c..38ab780 100644
--- a/res/values-zh-rTW/strings.xml
+++ b/res/values-zh-rTW/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"結束緊急回撥模式,以便撥打非緊急電話。"</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"尚未註冊網路。"</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"無法使用 Google 行動服務網路。"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"無法使用行動網路。\n\n如要撥打電話,請連線至無線網路。\n\n這部裝置已停用 2G,這可能會影響連線能力。請前往「設定」並啟用「允許啟用 2G」,再繼續操作。"</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"無法使用行動網路。連上 Wi-Fi 網路即可撥打電話。"</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"無法使用行動網路。\n\n如要撥打電話,請連線至無線網路。\n\n這部裝置已停用 2G,這可能會影響連線能力。請前往「設定」並啟用「允許啟用 2G」,再繼續操作。"</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"如要撥打電話,請輸入有效的號碼。"</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"無法通話。"</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"目前無法新增通話,你可以試著傳送簡訊聯絡對方。"</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"無法保留通話。"</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"連上無線網路即可撥打電話。"</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"請啟用 Wi-Fi 通話功能以撥打電話。"</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"如要撥打電話,請停用衛星模式。"</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"如要撥打電話,請先結束衛星連線。"</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"你可以收發訊息,沒有行動/Wi-Fi 網路也無妨。"</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"緊急救援資訊"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"擁有者"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"再次輕觸即可查看資訊"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml
index 452a3c8..19f0e81 100644
--- a/res/values-zu/strings.xml
+++ b/res/values-zu/strings.xml
@@ -542,7 +542,9 @@
<string name="incall_error_ecm_emergency_only" msgid="5622379058883722080">"Phuma kwimodi yokushayela emuva yesiko esiphuthumayo ukuze wenze ikholi yemodi engaphuthumi."</string>
<string name="incall_error_emergency_only" msgid="8786127461027964653">"Ayibhalisiwe kwinethiwekhi."</string>
<string name="incall_error_out_of_service" msgid="1927265196942672791">"Inethiwekhi yefoni ayitholakali"</string>
+ <string name="incall_error_out_of_service_2g" msgid="904434080740846116">"Inethiwekhi yeselula ayitholakali.\n\nXhuma kunethiwekhi e-wireless ukuze ufone.\n\nU-2G ukhutshaziwe kule divayisi, okungenzeka kunomthelela ekuxhumaneni kwakho. Iya Kumasethingi bese uvula u-Vumela u-2G ukuze uqhubeke."</string>
<string name="incall_error_out_of_service_wfc" msgid="4497663185857190885">"Inethiwekhi yeselula ayitholakali. Xhumeka kunethiwekhi engenantambo ukuze wenze ikholi."</string>
+ <string name="incall_error_out_of_service_wfc_2g_user" msgid="8218768986365299663">"Inethiwekhi yeselula ayitholakali.\n\nXhuma kunethiwekhi e-wireless ukuze ufone.\n\nU-2G ukhutshaziwe kule divayisi, okungenzeka kunomthelela ekuxhumaneni kwakho. Iya Kumasethingi bese uvula u-Vumela u-2G ukuze uqhubeke."</string>
<string name="incall_error_no_phone_number_supplied" msgid="8680831089508851894">"Ukuze wenze ikholi, faka inombolo evumelekile."</string>
<string name="incall_error_call_failed" msgid="393508653582682539">"Ikholi ihlulekile."</string>
<string name="incall_error_cannot_add_call" msgid="5425764862628655443">"Ikholi ayikwazi ukungezwa ngalesi sikhathi. Ungazama ukufinyelela ngokuthumela umlayezo."</string>
@@ -557,7 +559,8 @@
<string name="incall_error_supp_service_hold" msgid="8535056414643540997">"Ayikwazi ukubamba amakholi."</string>
<string name="incall_error_wfc_only_no_wireless_network" msgid="5860742792811400109">"Xhumeka kunethiwekhi engenantambo ukuze wenze ikholi."</string>
<string name="incall_error_promote_wfc" msgid="9164896813931363415">"Nika amandla ukushaya kwevoyisimeyili ukuze wenze ikholi."</string>
- <string name="incall_error_satellite_enabled" msgid="1936541518147323016">"Khubaza umumo wesethelayithi ukuze wenze ikholi."</string>
+ <string name="incall_error_satellite_enabled" msgid="5247740814607087814">"Ukuze ufone, qala ngokuvala uxhumano lwesathelayithi."</string>
+ <string name="incall_error_carrier_roaming_satellite_mode" msgid="678603203562886361">"Ungathumela futhi wamukele imilayezo ngaphandle kwenethiwekhi yeselula noma ye-Wi-Fi."</string>
<string name="emergency_information_hint" msgid="9208897544917793012">"Ulwazi lwesimo esiphuthumayo"</string>
<string name="emergency_information_owner_hint" msgid="6256909888049185316">"Umnikazi"</string>
<string name="emergency_information_confirm_hint" msgid="5109017615894918914">"Thepha futhi ukuze ubuke ulwazi"</string>
@@ -841,6 +844,8 @@
<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>
+ <!-- no translation found for mock_carrier_roaming_satellite_string (4796300252858292593) -->
+ <skip />
<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>
diff --git a/res/values/config.xml b/res/values/config.xml
index dcfa364..a934398 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -318,13 +318,6 @@
<string-array name="thermal_mitigation_allowlisted_packages" translatable="false">
</string-array>
- <!-- Array of carriers that don't care about NGRAN's preference in the preferred emergency
- network scan list after SIM is removed. -->
- <integer-array name="config_carriers_ignore_ngran_preference_when_sim_removed">
- <!-- 001-01 Test SIM -->
- <item>1911</item>
- </integer-array>
-
<!-- Array of countries that active SIM is needed for emergency calls. Values should be
ISO3166 country codes in lowercase. -->
<string-array name="config_countries_require_sim_for_emergency" translatable="false">
@@ -335,9 +328,38 @@
<item>sg</item>
<!-- b/198393826 -->
<item>de</item>
+ <!-- b/334773484 -->
+ <item>gb</item>
+ <item>fr</item>
+ <item>be</item>
+ <item>ro</item>
+ <item>si</item>
+ <item>hr</item>
+ <item>gr</item>
+ <item>bg</item>
+ <item>my</item>
</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>
+ <!-- Array of countries that a normal service capable subscription is preferred
+ for emergency calls. Values should be ISO3166 country codes in lowercase. -->
+ <string-array name="config_countries_prefer_normal_service_capable_subscription"
+ translatable="false">
+ <!-- b/317945295 -->
+ <item>in</item>
+ <item>sg</item>
+ </string-array>
+
+ <!-- Array of countries that a CS preferred scan is preferred after CSFB failure
+ due to the failure of extended service request. Values should be ISO3166
+ country codes in lowercase. -->
+ <string-array name="config_countries_prefer_cs_preferred_scan_after_csfb_failure"
+ translatable="false">
+ <!-- b/300022457 -->
+ <item>us</item>
+ </string-array>
+
+ <!-- The component name(a flattened ComponentName string) for the telephony domain selection
+ service. The device should fallback to the modem based domain selection architecture
+ if this is not configured. -->
+ <string name="config_domain_selection_service_component_name" translatable="false"></string>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 61143c9..05bcbc1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1206,8 +1206,13 @@
<string name="incall_error_emergency_only">Not registered on network.</string>
<!-- In-call screen: call failure message displayed in an error dialog -->
<string name="incall_error_out_of_service">Mobile network not available.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog if 2G is disabled -->
+ <string name="incall_error_out_of_service_2g">Mobile network not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable "Allow 2G" to continue.</string>
<!-- In-call screen: call failure message displayed in an error dialog -->
<string name="incall_error_out_of_service_wfc">Mobile network is not available. Connect to a wireless network to make a call.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog if the user disabled 2G -->
+ <string name="incall_error_out_of_service_wfc_2g_user">Mobile network is not available.\n\nConnect to a wireless network to make a call.\n\n2G is disabled on this device, which may be impacting your connectivity. Go to Settings and enable "Allow 2G" to continue.</string>
+
<!-- In-call screen: call failure message displayed in an error dialog -->
<string name="incall_error_no_phone_number_supplied">To place a call, enter a valid number.</string>
<!-- In-call screen: call failure message displayed in an error dialog -->
@@ -1240,7 +1245,9 @@
<!-- In-call screen: call failure message displayed in an error dialog when the user is connected to a wireless network, but wifi calling is turned off. [CHAR_LIMIT=NONE] -->
<string name="incall_error_promote_wfc">Enable Wi-Fi calling to make a call.</string>
<!-- In-call screen: call failure message displayed in an error dialog when the satellite modem is on. [CHAR_LIMIT=NONE] -->
- <string name="incall_error_satellite_enabled">Disable satellite mode to make a call.</string>
+ <string name="incall_error_satellite_enabled">To make a call, first end the satellite connection.</string>
+ <!-- In-call screen: call failure message displayed in an error dialog when device is connected to carrier roaming satellite network [CHAR_LIMIT=NONE] -->
+ <string name="incall_error_carrier_roaming_satellite_mode">You can send and receive messages without a mobile or Wi-Fi network.</string>
<!-- Hint for the button of emergency information -->
<string name="emergency_information_hint">Emergency information</string>
@@ -2019,6 +2026,9 @@
<!-- Title for simulating device out of service. -->
<string name="simulate_out_of_service_string">Simulate Out of Service (Debug Build only)</string>
+ <!-- Title for simulating SIM capable of satellite. -->
+ <string name="mock_carrier_roaming_satellite_string">Mock Carrier Satellite Mode (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 -->
@@ -2180,6 +2190,8 @@
<string name="radio_info_nr_frequency">NR Frequency:</string>
<!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
<string name="radio_info_network_slicing_config" translatable="false">Network Slicing Config:</string>
+ <!-- Radio Info screen. Label for a status item. Used for diagnostic info screens, precise translation isn't needed -->
+ <string name="radio_info_euicc_info" translatable="false">eUICC info:</string>
<!-- Band Mode Selection -->
<!-- Band mode screen. Title of activity. -->
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 19798f0..435e3a6 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -202,6 +202,11 @@
<item name="android:colorAccent">@color/dialer_theme_color</item>
<item name="android:dialogTheme">@style/DialerAlertDialogTheme</item>
<item name="android:homeAsUpIndicator">@drawable/ic_back_arrow</item>
+
+ <!--
+ TODO(b/309578419): Make activities handle insets properly and then remove this.
+ -->
+ <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
</style>
<style name="DialerAlertDialogTheme"
diff --git a/src/com/android/phone/CallForwardEditPreference.java b/src/com/android/phone/CallForwardEditPreference.java
index d1c8303..b877112 100644
--- a/src/com/android/phone/CallForwardEditPreference.java
+++ b/src/com/android/phone/CallForwardEditPreference.java
@@ -26,6 +26,7 @@
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.Flags;
import java.util.HashMap;
import java.util.Locale;
@@ -34,6 +35,9 @@
private static final String LOG_TAG = "CallForwardEditPreference";
private static final String SRC_TAGS[] = {"{0}"};
+
+ private static final int DEFAULT_NO_REPLY_TIMER_FOR_CFNRY = 20;
+
private CharSequence mSummaryOnTemplate;
/**
* Remembers which button was clicked by a user. If no button is clicked yet, this should have
@@ -154,7 +158,14 @@
.getCarrierConfigForSubId(mPhone.getSubId());
if (carrierConfig.getBoolean(
CarrierConfigManager.KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true)) {
- time = 20;
+ if (Flags.setNoReplyTimerForCfnry()) {
+ // Get timer value from carrier config
+ time = carrierConfig.getInt(
+ CarrierConfigManager.KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT,
+ DEFAULT_NO_REPLY_TIMER_FOR_CFNRY);
+ } else {
+ time = DEFAULT_NO_REPLY_TIMER_FOR_CFNRY;
+ }
}
}
final String number = getPhoneNumber();
diff --git a/src/com/android/phone/CallWaitingSwitchPreference.java b/src/com/android/phone/CallWaitingSwitchPreference.java
index 00407f3..a5bc92e 100644
--- a/src/com/android/phone/CallWaitingSwitchPreference.java
+++ b/src/com/android/phone/CallWaitingSwitchPreference.java
@@ -35,6 +35,8 @@
private int mUpdateStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
private int mQueryStatus = TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR;
private boolean mUssdMode = false;
+ private boolean mCwEnabled = false;
+ private boolean mCwClicked = false;
public CallWaitingSwitchPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
@@ -60,6 +62,7 @@
PersistableBundle bundle = configManager.getConfigForSubId(phone.getSubId());
mUssdMode = (bundle != null) ? bundle.getBoolean(
CarrierConfigManager.KEY_USE_CALL_WAITING_USSD_BOOL, false) : false;
+ mCwEnabled = false;
if (!skipReading) {
Log.d(LOG_TAG, "init getCallWaitingStatus");
@@ -101,7 +104,9 @@
@Override
protected void onClick() {
super.onClick();
- mTelephonyManager.setCallWaitingEnabled(isChecked(), mExecutor, this::updateStatusCallBack);
+ mCwEnabled = isChecked();
+ mCwClicked = true;
+ mTelephonyManager.setCallWaitingEnabled(mCwEnabled, mExecutor, this::updateStatusCallBack);
if (mTcpListener != null) {
mIsDuringUpdateProcess = true;
mTcpListener.onStarted(this, false);
@@ -145,6 +150,8 @@
if (mTcpListener != null) {
mTcpListener.onError(CallWaitingSwitchPreference.this, error);
}
+ handleCwFallbackOnError();
+ setChecked(mCwEnabled);
} else if (mQueryStatus == TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR
|| (mIsDuringUpdateProcess && (
mUpdateStatus != TelephonyManager.CALL_WAITING_STATUS_ENABLED
@@ -153,14 +160,21 @@
if (mTcpListener != null) {
mTcpListener.onError(CallWaitingSwitchPreference.this, RESPONSE_ERROR);
}
+ handleCwFallbackOnError();
+ setChecked(mCwEnabled);
} else {
- if (mQueryStatus == TelephonyManager.CALL_WAITING_STATUS_ENABLED) {
- setChecked(true);
- } else {
- setChecked(false);
- }
+ mCwEnabled = mQueryStatus == TelephonyManager.CALL_WAITING_STATUS_ENABLED;
+ setChecked(mCwEnabled);
}
mIsDuringUpdateProcess = false;
+ mCwClicked = false;
+ }
+ }
+
+ private void handleCwFallbackOnError() {
+ // Recover initial state before onClick.
+ if (mCwClicked) {
+ mCwEnabled = !mCwEnabled;
}
}
}
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 3eafb24..9b71919 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -16,12 +16,15 @@
package com.android.phone;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION;
import static android.service.carrier.CarrierService.ICarrierServiceWrapper.KEY_CONFIG_BUNDLE;
import static android.service.carrier.CarrierService.ICarrierServiceWrapper.RESULT_ERROR;
+import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
+import android.app.compat.CompatChanges;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -49,6 +52,7 @@
import android.service.carrier.CarrierIdentifier;
import android.service.carrier.CarrierService;
import android.service.carrier.ICarrierService;
+import android.telephony.AnomalyReporter;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyFrameworkInitializer;
@@ -66,6 +70,7 @@
import com.android.internal.telephony.PhoneConfigurationManager;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.ArrayUtils;
import com.android.internal.telephony.util.TelephonyUtils;
@@ -90,6 +95,7 @@
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
+import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -214,6 +220,10 @@
CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL
};
+ // UUID to report anomaly when config changed reported with subId that map to invalid phone
+ private static final String UUID_NOTIFY_CONFIG_CHANGED_WITH_INVALID_PHONE =
+ "d81cef11-c2f1-4d76-955d-7f50e8590c48";
+
// Handler to process various events.
//
// For each phoneId, the event sequence should be:
@@ -685,12 +695,17 @@
@NonNull private final Handler mHandler;
+ @NonNull private final FeatureFlags mFeatureFlags;
+
+ @NonNull private final PackageManager mPackageManager;
+
/**
* Constructs a CarrierConfigLoader, registers it as a service, and registers a broadcast
* receiver for relevant events.
*/
@VisibleForTesting
- /* package */ CarrierConfigLoader(@NonNull Context context, @NonNull Looper looper) {
+ /* package */ CarrierConfigLoader(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags) {
super(PermissionEnforcer.fromContext(context));
mContext = context;
mPlatformCarrierConfigPackage =
@@ -719,6 +734,8 @@
TelephonyManager.from(context).registerCarrierPrivilegesCallback(phoneId,
new HandlerExecutor(mHandler), mCarrierServiceChangeCallbacks[phoneId]);
}
+ mFeatureFlags = featureFlags;
+ mPackageManager = context.getPackageManager();
logd("CarrierConfigLoader has started");
PhoneConfigurationManager.registerForMultiSimConfigChange(
@@ -733,10 +750,11 @@
* This is only done once, at startup, from {@link com.android.phone.PhoneApp#onCreate}.
*/
@NonNull
- /* package */ static CarrierConfigLoader init(@NonNull Context context) {
+ /* package */ static CarrierConfigLoader init(@NonNull Context context,
+ @NonNull FeatureFlags featureFlags) {
synchronized (CarrierConfigLoader.class) {
if (sInstance == null) {
- sInstance = new CarrierConfigLoader(context, Looper.myLooper());
+ sInstance = new CarrierConfigLoader(context, Looper.myLooper(), featureFlags);
// Make this service available through ServiceManager.
TelephonyFrameworkInitializer.getTelephonyServiceManager()
.getCarrierConfigServiceRegisterer().register(sInstance);
@@ -1323,6 +1341,8 @@
return new PersistableBundle();
}
+ enforceTelephonyFeatureWithException(callingPackage, "getConfigForSubIdWithFeature");
+
int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig();
if (SubscriptionManager.isValidPhoneId(phoneId)) {
@@ -1367,6 +1387,9 @@
Objects.requireNonNull(keys, "Config keys must be non-null");
enforceCallerIsSystemOrRequestingPackage(callingPackage);
+ enforceTelephonyFeatureWithException(callingPackage,
+ "getConfigSubsetForSubIdWithFeature");
+
// Permission check is performed inside and an empty bundle will return on failure.
// No SecurityException thrown here since most clients expect to retrieve the overridden
// value if present or use default one if not
@@ -1416,6 +1439,9 @@
throw new IllegalArgumentException(
"Invalid phoneId " + phoneId + " for subId " + subscriptionId);
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "overrideConfig");
+
// Post to run on handler thread on which all states should be confined.
mHandler.post(() -> {
overrideConfig(mOverrideConfigs, phoneId, overrides);
@@ -1463,11 +1489,19 @@
int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
- logd("Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId);
- throw new IllegalArgumentException(
- "Invalid phoneId " + phoneId + " for subId " + subscriptionId);
+ final String msg =
+ "Ignore invalid phoneId: " + phoneId + " for subId: " + subscriptionId;
+ if (mFeatureFlags.addAnomalyWhenNotifyConfigChangedWithInvalidPhone()) {
+ AnomalyReporter.reportAnomaly(
+ UUID.fromString(UUID_NOTIFY_CONFIG_CHANGED_WITH_INVALID_PHONE), msg);
+ }
+ logd(msg);
+ throw new IllegalArgumentException(msg);
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "notifyConfigChangedForSubId");
+
logdWithLocalLog("Notified carrier config changed. phoneId=" + phoneId
+ ", subId=" + subscriptionId);
@@ -1488,6 +1522,9 @@
if (!SubscriptionManager.isValidPhoneId(phoneId)) {
throw new IllegalArgumentException("Invalid phoneId: " + phoneId);
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(), "updateConfigForPhoneId");
+
// requires Java 7 for switch on string.
switch (simState) {
case IccCardConstants.INTENT_VALUE_ICC_ABSENT:
@@ -1509,6 +1546,10 @@
@NonNull
public String getDefaultCarrierServicePackageName() {
getDefaultCarrierServicePackageName_enforcePermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "getDefaultCarrierServicePackageName");
+
return mPlatformCarrierConfigPackage;
}
@@ -1819,6 +1860,40 @@
== TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
}
+ /**
+ * Get the current calling package name.
+ * @return the current calling package name
+ */
+ @Nullable
+ private String getCurrentPackageName() {
+ if (mPackageManager == null) return null;
+ String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid());
+ return (callingUids == null) ? null : callingUids[0];
+ }
+
+ /**
+ * Make sure the device has required telephony feature
+ *
+ * @throws UnsupportedOperationException if the device does not have required telephony feature
+ */
+ private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
+ @NonNull String methodName) {
+ if (callingPackage == null || mPackageManager == null) {
+ return;
+ }
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+ Binder.getCallingUserHandle())) {
+ return;
+ }
+
+ if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_SUBSCRIPTION)) {
+ throw new UnsupportedOperationException(
+ methodName + " is unsupported without " + FEATURE_TELEPHONY_SUBSCRIPTION);
+ }
+ }
+
private class CarrierServiceConnection implements ServiceConnection {
final int phoneId;
@NonNull final String pkgName;
diff --git a/src/com/android/phone/ChangeIccPinScreen.java b/src/com/android/phone/ChangeIccPinScreen.java
index 5369aa3..0784495 100644
--- a/src/com/android/phone/ChangeIccPinScreen.java
+++ b/src/com/android/phone/ChangeIccPinScreen.java
@@ -18,12 +18,14 @@
import android.app.Activity;
import android.app.AlertDialog;
+import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.UserManager;
import android.text.method.DigitsKeyListener;
import android.util.Log;
import android.view.View;
@@ -46,12 +48,12 @@
private static final boolean DBG = false;
private static final int EVENT_PIN_CHANGED = 100;
-
+
private enum EntryState {
ES_PIN,
ES_PUK
}
-
+
private EntryState mState;
private static final int NO_ERROR = 0;
@@ -61,6 +63,8 @@
private static final int MIN_PIN_LENGTH = 4;
private static final int MAX_PIN_LENGTH = 8;
+ private UserManager mUserManager;
+ private boolean mDisallowedConfig;
private Phone mPhone;
private boolean mChangePin2;
private TextView mBadPinError;
@@ -91,49 +95,74 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ mUserManager = this.getSystemService(UserManager.class);
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+ mDisallowedConfig = true;
+ }
+
mPhone = PhoneGlobals.getPhone();
resolveIntent();
setContentView(R.layout.change_sim_pin_screen);
+ setupView();
+ mState = EntryState.ES_PIN;
+ }
+
+ private void setupView() {
mOldPin = (EditText) findViewById(R.id.old_pin);
- mOldPin.setKeyListener(DigitsKeyListener.getInstance());
- mOldPin.setMovementMethod(null);
- mOldPin.setOnClickListener(mClicked);
-
mNewPin1 = (EditText) findViewById(R.id.new_pin1);
- mNewPin1.setKeyListener(DigitsKeyListener.getInstance());
- mNewPin1.setMovementMethod(null);
- mNewPin1.setOnClickListener(mClicked);
-
mNewPin2 = (EditText) findViewById(R.id.new_pin2);
- mNewPin2.setKeyListener(DigitsKeyListener.getInstance());
- mNewPin2.setMovementMethod(null);
- mNewPin2.setOnClickListener(mClicked);
-
mBadPinError = (TextView) findViewById(R.id.bad_pin);
mMismatchError = (TextView) findViewById(R.id.mismatch);
-
mButton = (Button) findViewById(R.id.button);
- mButton.setOnClickListener(mClicked);
-
mScrollView = (ScrollView) findViewById(R.id.scroll);
-
mPUKCode = (EditText) findViewById(R.id.puk_code);
- mPUKCode.setKeyListener(DigitsKeyListener.getInstance());
- mPUKCode.setMovementMethod(null);
- mPUKCode.setOnClickListener(mClicked);
-
mPUKSubmit = (Button) findViewById(R.id.puk_submit);
- mPUKSubmit.setOnClickListener(mClicked);
-
mIccPUKPanel = (LinearLayout) findViewById(R.id.puk_panel);
-
int id = mChangePin2 ? R.string.change_pin2 : R.string.change_pin;
setTitle(getResources().getText(id));
-
- mState = EntryState.ES_PIN;
+
+ if (mDisallowedConfig) {
+ mOldPin.setEnabled(false);
+ mOldPin.setAlpha(.5f);
+
+ mNewPin1.setEnabled(false);
+ mNewPin1.setAlpha(.5f);
+
+ mNewPin2.setEnabled(false);
+ mNewPin2.setAlpha(.5f);
+
+ mButton.setEnabled(false);
+ mButton.setAlpha(.5f);
+
+ mPUKCode.setEnabled(false);
+ mPUKCode.setAlpha(.5f);
+
+ mPUKSubmit.setEnabled(false);
+ mPUKSubmit.setAlpha(.5f);
+ } else {
+ mOldPin.setKeyListener(DigitsKeyListener.getInstance());
+ mOldPin.setMovementMethod(null);
+ mOldPin.setOnClickListener(mClicked);
+
+ mNewPin1.setKeyListener(DigitsKeyListener.getInstance());
+ mNewPin1.setMovementMethod(null);
+ mNewPin1.setOnClickListener(mClicked);
+
+ mNewPin2.setKeyListener(DigitsKeyListener.getInstance());
+ mNewPin2.setMovementMethod(null);
+ mNewPin2.setOnClickListener(mClicked);
+
+ mButton.setOnClickListener(mClicked);
+
+ mPUKCode.setKeyListener(DigitsKeyListener.getInstance());
+ mPUKCode.setMovementMethod(null);
+ mPUKCode.setOnClickListener(mClicked);
+
+ mPUKSubmit.setOnClickListener(mClicked);
+ }
}
private void resolveIntent() {
diff --git a/src/com/android/phone/DiagnosticDataCollector.java b/src/com/android/phone/DiagnosticDataCollector.java
index e997270..e0b1dac 100644
--- a/src/com/android/phone/DiagnosticDataCollector.java
+++ b/src/com/android/phone/DiagnosticDataCollector.java
@@ -16,7 +16,6 @@
package com.android.phone;
-import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.WorkerThread;
import android.os.DropBoxManager;
@@ -25,7 +24,6 @@
import android.telephony.AnomalyReporter;
import android.telephony.TelephonyManager;
import android.util.Log;
-import java.util.UUID;
import java.io.BufferedReader;
import java.io.IOException;
@@ -34,6 +32,7 @@
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
+import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@@ -75,16 +74,16 @@
}
public void persistEmergencyDianosticData(@NonNull DataCollectorConfig.Adapter dc,
- @NonNull TelephonyManager.EmergencyCallDiagnosticParams edp, @NonNull String tag) {
+ @NonNull TelephonyManager.EmergencyCallDiagnosticData ecdData, @NonNull String tag) {
- if (edp.isTelephonyDumpSysCollectionEnabled()) {
+ if (ecdData.isTelephonyDumpsysCollectionEnabled()) {
persistTelephonyState(dc, tag);
}
- if (edp.isTelecomDumpSysCollectionEnabled()) {
+ if (ecdData.isTelecomDumpsysCollectionEnabled()) {
persistTelecomState(dc, tag);
}
- if (edp.isLogcatCollectionEnabled()) {
- persistLogcat(dc, tag, edp.getLogcatStartTime());
+ if (ecdData.isLogcatCollectionEnabled()) {
+ persistLogcat(dc, tag, ecdData.getLogcatCollectionStartTimeMillis());
}
}
diff --git a/src/com/android/phone/EmergencyDialer.java b/src/com/android/phone/EmergencyDialer.java
index 5fe8708..a608b1b 100644
--- a/src/com/android/phone/EmergencyDialer.java
+++ b/src/com/android/phone/EmergencyDialer.java
@@ -263,7 +263,7 @@
setTurnScreenOn(true);
CarrierConfigManager configMgr = getSystemService(CarrierConfigManager.class);
- PersistableBundle carrierConfig =
+ PersistableBundle carrierConfig = configMgr == null ? null :
configMgr.getConfigForSubId(SubscriptionManager.getDefaultVoiceSubscriptionId());
mShortcutViewConfig = new ShortcutViewUtils.Config(this, carrierConfig, mEntryType);
@@ -313,12 +313,14 @@
// Check whether we should show the onscreen "Dial" button and co.
// Read carrier config through the public API because PhoneGlobals is not available when we
// run as a secondary user.
- if (carrierConfig.getBoolean(CarrierConfigManager.KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL)) {
+ if (carrierConfig != null
+ && carrierConfig.getBoolean(
+ CarrierConfigManager.KEY_SHOW_ONSCREEN_DIAL_BUTTON_BOOL)) {
mDialButton.setOnClickListener(this);
} else {
mDialButton.setVisibility(View.GONE);
}
- mIsWfcEmergencyCallingWarningEnabled = carrierConfig.getInt(
+ mIsWfcEmergencyCallingWarningEnabled = carrierConfig != null && carrierConfig.getInt(
CarrierConfigManager.KEY_EMERGENCY_NOTIFICATION_DELAY_INT) > -1;
maybeShowWfcEmergencyCallingWarning();
diff --git a/src/com/android/phone/EnableIccPinScreen.java b/src/com/android/phone/EnableIccPinScreen.java
index 160978f..092fa64 100644
--- a/src/com/android/phone/EnableIccPinScreen.java
+++ b/src/com/android/phone/EnableIccPinScreen.java
@@ -17,10 +17,12 @@
package com.android.phone;
import android.app.Activity;
+import android.content.Context;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.UserManager;
import android.text.TextUtils;
import android.text.method.DigitsKeyListener;
import android.util.Log;
@@ -41,11 +43,13 @@
private static final int ENABLE_ICC_PIN_COMPLETE = 100;
private static final boolean DBG = false;
+ private UserManager mUserManager;
private LinearLayout mPinFieldContainer;
private EditText mPinField;
private TextView mStatusField;
private boolean mEnable;
private Phone mPhone;
+ private boolean mDisallowedConfig = false;
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
@@ -64,6 +68,11 @@
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ mUserManager = this.getSystemService(UserManager.class);
+ if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
+ mDisallowedConfig = true;
+ }
+
setContentView(R.layout.enable_sim_pin_screen);
setupView();
@@ -76,12 +85,20 @@
private void setupView() {
mPinField = (EditText) findViewById(R.id.pin);
- mPinField.setKeyListener(DigitsKeyListener.getInstance());
- mPinField.setMovementMethod(null);
- mPinField.setOnClickListener(mClicked);
-
mPinFieldContainer = (LinearLayout) findViewById(R.id.pinc);
mStatusField = (TextView) findViewById(R.id.status);
+
+ if (mDisallowedConfig) {
+ mPinField.setEnabled(false);
+ mPinField.setAlpha(.5f);
+
+ mPinFieldContainer.setEnabled(false);
+ mPinFieldContainer.setAlpha(.5f);
+ } else {
+ mPinField.setKeyListener(DigitsKeyListener.getInstance());
+ mPinField.setMovementMethod(null);
+ mPinField.setOnClickListener(mClicked);
+ }
}
private void showStatus(CharSequence statusMsg) {
diff --git a/src/com/android/phone/ImsProvisioningController.java b/src/com/android/phone/ImsProvisioningController.java
index b2e34ae..d2c720b 100644
--- a/src/com/android/phone/ImsProvisioningController.java
+++ b/src/com/android/phone/ImsProvisioningController.java
@@ -70,6 +70,7 @@
import com.android.ims.RcsFeatureManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.PhoneConfigurationManager;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.util.HandlerExecutor;
import com.android.telephony.Rlog;
@@ -92,6 +93,7 @@
@VisibleForTesting
protected static final int EVENT_MULTI_SIM_CONFIGURATION_CHANGE = 3;
private static final int EVENT_PROVISIONING_VALUE_CHANGED = 4;
+ private static final int EVENT_NOTIFY_INIT_PROVISIONED_VALUE = 5;
// Provisioning Keys that are handled via AOSP cache and not sent to the ImsService
private static final int[] LOCAL_IMS_CONFIG_KEYS = {
@@ -121,6 +123,11 @@
CAPABILITY_TYPE_CALL_COMPOSER
};
+ private static final int[] LOCAL_RCS_CAPABILITY = {
+ CAPABILITY_TYPE_OPTIONS_UCE,
+ CAPABILITY_TYPE_PRESENCE_UCE
+ };
+
/**
* map the MmTelCapabilities.MmTelCapability and
* CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT
@@ -199,6 +206,7 @@
private final SparseArray<ProvisioningCallbackManager> mProvisioningCallbackManagersSlotMap =
new SparseArray<>();
private final ImsProvisioningLoader mImsProvisioningLoader;
+ private final FeatureFlags mFeatureFlags;
private int mNumSlot;
@@ -253,6 +261,18 @@
+ " value : " + (int) msg.obj);
updateCapabilityTechFromKey(msg.arg1, msg.arg2, (int) msg.obj);
break;
+ case EVENT_NOTIFY_INIT_PROVISIONED_VALUE:
+ int slotId = msg.arg1;
+ int subId = msg.arg2;
+ IFeatureProvisioningCallback callback =
+ (IFeatureProvisioningCallback) msg.obj;
+ log("slotId " + slotId + " subId " + subId
+ + " callback " + (callback != null));
+
+ // Notify MmTel Provisioning Status
+ notifyMmTelProvisioningStatus(slotId, subId, callback);
+ notifyRcsProvisioningStatus(slotId, subId, callback);
+ break;
default:
log("unknown message " + msg);
break;
@@ -508,6 +528,13 @@
// notify provisioning key value to ImsService
setInitialProvisioningKeys(mSubId);
+
+ if (mFeatureFlags.notifyInitialImsProvisioningStatus()) {
+ // Notify MmTel provisioning value based on capability and radio tech.
+ if (mProvisioningCallbackManagersSlotMap.get(mSlotId).hasCallblacks()) {
+ notifyMmTelProvisioningStatus(mSlotId, mSubId, null);
+ }
+ }
} else {
// wait until subId is valid
mRequiredNotify = true;
@@ -740,6 +767,13 @@
// notify provisioning key value to ImsService
setInitialProvisioningKeys(mSubId);
+
+ if (mFeatureFlags.notifyInitialImsProvisioningStatus()) {
+ if (mProvisioningCallbackManagersSlotMap.get(mSlotId).hasCallblacks()) {
+ // Notify RCS provisioning value based on capability and radio tech.
+ notifyRcsProvisioningStatus(mSlotId, mSubId, null);
+ }
+ }
} else {
// wait until subId is valid
mRequiredNotify = true;
@@ -828,7 +862,7 @@
@VisibleForTesting
public ImsProvisioningController(PhoneGlobals app, int numSlot, Looper looper,
MmTelFeatureConnector mmTelFeatureConnector, RcsFeatureConnector rcsFeatureConnector,
- ImsProvisioningLoader imsProvisioningLoader) {
+ ImsProvisioningLoader imsProvisioningLoader, FeatureFlags featureFlags) {
log("ImsProvisioningController");
mApp = app;
mNumSlot = numSlot;
@@ -841,6 +875,7 @@
mTelephonyRegistryManager.addOnSubscriptionsChangedListener(
mSubChangedListener, mHandler::post);
mImsProvisioningLoader = imsProvisioningLoader;
+ mFeatureFlags = featureFlags;
PhoneConfigurationManager.registerForMultiSimConfigChange(mHandler,
EVENT_MULTI_SIM_CONFIGURATION_CHANGE, null);
@@ -924,7 +959,8 @@
* create an instance
*/
@VisibleForTesting
- public static ImsProvisioningController make(PhoneGlobals app, int numSlot) {
+ public static ImsProvisioningController make(PhoneGlobals app, int numSlot,
+ FeatureFlags featureFlags) {
synchronized (ImsProvisioningController.class) {
if (sInstance == null) {
Rlog.i(TAG, "ImsProvisioningController created");
@@ -932,7 +968,7 @@
handlerThread.start();
sInstance = new ImsProvisioningController(app, numSlot, handlerThread.getLooper(),
ImsManager::getConnector, RcsFeatureManager::getConnector,
- new ImsProvisioningLoader(app));
+ new ImsProvisioningLoader(app), featureFlags);
}
}
return sInstance;
@@ -966,6 +1002,11 @@
try {
mProvisioningCallbackManagersSlotMap.get(slotId).registerCallback(callback);
log("Feature Provisioning Callback registered.");
+
+ if (mFeatureFlags.notifyInitialImsProvisioningStatus()) {
+ mHandler.sendMessage(mHandler.obtainMessage(EVENT_NOTIFY_INIT_PROVISIONED_VALUE,
+ getSlotId(subId), subId, (Object) callback));
+ }
} catch (NullPointerException e) {
logw("can not access callback manager to add callback");
}
@@ -1639,6 +1680,90 @@
return true;
}
+ private void notifyMmTelProvisioningStatus(int slotId, int subId,
+ @Nullable IFeatureProvisioningCallback callback) {
+ int value = ImsProvisioningLoader.STATUS_NOT_SET;
+ int[] techArray;
+ for (int capability : LOCAL_MMTEL_CAPABILITY) {
+ techArray = getTechsFromCarrierConfig(subId, capability, /*isMmTle*/true);
+ if (techArray == null) {
+ continue;
+ }
+
+ for (int radioTech : techArray) {
+ value = mImsProvisioningLoader.getProvisioningStatus(subId, FEATURE_MMTEL,
+ capability, radioTech);
+ if (value == ImsProvisioningLoader.STATUS_NOT_SET) {
+ // Not yet provisioned
+ continue;
+ }
+
+ value = (value == ImsProvisioningLoader.STATUS_PROVISIONED)
+ ? PROVISIONING_VALUE_ENABLED : PROVISIONING_VALUE_DISABLED;
+
+ // Notify all registered callbacks
+ if (callback == null) {
+ mProvisioningCallbackManagersSlotMap.get(slotId)
+ .notifyProvisioningCapabilityChanged(
+ new FeatureProvisioningData(
+ capability,
+ radioTech,
+ getBoolValue(value),
+ /*isMmTle*/true));
+ } else {
+ try {
+ callback.onFeatureProvisioningChanged(capability, radioTech,
+ getBoolValue(value));
+ } catch (RemoteException e) {
+ logw("notifyMmTelProvisioningStatus callback is not available");
+ }
+ }
+ }
+ }
+ }
+
+ private void notifyRcsProvisioningStatus(int slotId, int subId,
+ @Nullable IFeatureProvisioningCallback callback) {
+ int value = ImsProvisioningLoader.STATUS_NOT_SET;
+ int[] techArray;
+ for (int capability : LOCAL_RCS_CAPABILITY) {
+ techArray = getTechsFromCarrierConfig(subId, capability, /*isMmTle*/false);
+ if (techArray == null) {
+ continue;
+ }
+
+ for (int radioTech : techArray) {
+ value = mImsProvisioningLoader.getProvisioningStatus(subId, FEATURE_RCS,
+ capability, radioTech);
+ if (value == ImsProvisioningLoader.STATUS_NOT_SET) {
+ // Not yet provisioned
+ continue;
+ }
+
+ value = (value == ImsProvisioningLoader.STATUS_PROVISIONED)
+ ? PROVISIONING_VALUE_ENABLED : PROVISIONING_VALUE_DISABLED;
+
+ // Notify all registered callbacks
+ if (callback == null) {
+ mProvisioningCallbackManagersSlotMap.get(slotId)
+ .notifyProvisioningCapabilityChanged(
+ new FeatureProvisioningData(
+ capability,
+ radioTech,
+ getBoolValue(value),
+ /*isMmTle*/false));
+ } else {
+ try {
+ callback.onRcsFeatureProvisioningChanged(capability, radioTech,
+ getBoolValue(value));
+ } catch (RemoteException e) {
+ logw("notifyRcsProvisioningStatus callback is not available");
+ }
+ }
+ }
+ }
+ }
+
private void log(String s) {
Rlog.d(TAG, s);
}
diff --git a/src/com/android/phone/ImsRcsController.java b/src/com/android/phone/ImsRcsController.java
index 3f35454..a778f6a 100644
--- a/src/com/android/phone/ImsRcsController.java
+++ b/src/com/android/phone/ImsRcsController.java
@@ -16,7 +16,13 @@
package com.android.phone;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_IMS;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION;
+import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
+
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledAfter;
@@ -53,6 +59,7 @@
import com.android.internal.telephony.ISipDialogStateCallback;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyPermissions;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.ims.ImsResolver;
import com.android.services.telephony.rcs.RcsFeatureController;
import com.android.services.telephony.rcs.SipTransportController;
@@ -74,6 +81,8 @@
private PhoneGlobals mApp;
private TelephonyRcsService mRcsService;
private ImsResolver mImsResolver;
+ private FeatureFlags mFeatureFlags;
+ private PackageManager mPackageManager;
// set by shell cmd phone src set-device-enabled true/false
private Boolean mSingleRegistrationOverride;
@@ -90,10 +99,10 @@
* Initialize the singleton ImsRcsController instance.
* This is only done once, at startup, from PhoneApp.onCreate().
*/
- static ImsRcsController init(PhoneGlobals app) {
+ static ImsRcsController init(PhoneGlobals app, FeatureFlags featureFlags) {
synchronized (ImsRcsController.class) {
if (sInstance == null) {
- sInstance = new ImsRcsController(app);
+ sInstance = new ImsRcsController(app, featureFlags);
} else {
Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance);
}
@@ -102,9 +111,11 @@
}
/** Private constructor; @see init() */
- private ImsRcsController(PhoneGlobals app) {
+ private ImsRcsController(PhoneGlobals app, FeatureFlags featureFlags) {
Log.i(TAG, "ImsRcsController");
mApp = app;
+ mFeatureFlags = featureFlags;
+ mPackageManager = mApp.getPackageManager();
TelephonyFrameworkInitializer
.getTelephonyServiceManager().getTelephonyImsServiceRegisterer().register(this);
mImsResolver = ImsResolver.getInstance();
@@ -118,6 +129,10 @@
public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "registerImsRegistrationCallback");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "registerImsRegistrationCallback");
+
final long token = Binder.clearCallingIdentity();
try {
getRcsFeatureController(subId).registerImsRegistrationCallback(subId, callback);
@@ -136,6 +151,10 @@
public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "unregisterImsRegistrationCallback");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "unregisterImsRegistrationCallback");
+
final long token = Binder.clearCallingIdentity();
try {
getRcsFeatureController(subId).unregisterImsRegistrationCallback(subId, callback);
@@ -153,6 +172,10 @@
public void getImsRcsRegistrationState(int subId, IIntegerConsumer consumer) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getImsRcsRegistrationState");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getImsRcsRegistrationState");
+
final long token = Binder.clearCallingIdentity();
try {
getRcsFeatureController(subId).getRegistrationState(regState -> {
@@ -175,6 +198,10 @@
public void getImsRcsRegistrationTransportType(int subId, IIntegerConsumer consumer) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getImsRcsRegistrationTransportType");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getImsRcsRegistrationTransportType");
+
final long token = Binder.clearCallingIdentity();
try {
getRcsFeatureController(subId).getRegistrationTech(regTech -> {
@@ -204,6 +231,10 @@
@Override
public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
enforceReadPrivilegedPermission("registerRcsAvailabilityCallback");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "registerRcsAvailabilityCallback");
+
final long token = Binder.clearCallingIdentity();
try {
getRcsFeatureController(subId).registerRcsAvailabilityCallback(subId, callback);
@@ -224,6 +255,10 @@
@Override
public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
enforceReadPrivilegedPermission("unregisterRcsAvailabilityCallback");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "unregisterRcsAvailabilityCallback");
+
final long token = Binder.clearCallingIdentity();
try {
getRcsFeatureController(subId).unregisterRcsAvailabilityCallback(subId, callback);
@@ -247,6 +282,10 @@
@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
enforceReadPrivilegedPermission("isCapable");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isCapable");
+
final long token = Binder.clearCallingIdentity();
try {
return getRcsFeatureController(subId).isCapable(capability, radioTech);
@@ -273,6 +312,10 @@
@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
enforceReadPrivilegedPermission("isAvailable");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isAvailable");
+
final long token = Binder.clearCallingIdentity();
try {
return getRcsFeatureController(subId).isAvailable(capability, radioTech);
@@ -290,6 +333,10 @@
List<Uri> contactNumbers, IRcsUceControllerCallback c) {
enforceAccessUserCapabilityExchangePermission("requestCapabilities");
enforceReadContactsPermission("requestCapabilities");
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ FEATURE_TELEPHONY_IMS, "requestCapabilities");
+
final long token = Binder.clearCallingIdentity();
try {
UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
@@ -311,6 +358,10 @@
String callingFeatureId, Uri contactNumber, IRcsUceControllerCallback c) {
enforceAccessUserCapabilityExchangePermission("requestAvailability");
enforceReadContactsPermission("requestAvailability");
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ FEATURE_TELEPHONY_IMS, "requestAvailability");
+
final long token = Binder.clearCallingIdentity();
try {
UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
@@ -330,6 +381,10 @@
@Override
public @PublishState int getUcePublishState(int subId) {
enforceReadPrivilegedPermission("getUcePublishState");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getUcePublishState");
+
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
boolean isSupportPublishingState = false;
@@ -485,6 +540,10 @@
@Override
public void registerUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
enforceReadPrivilegedPermission("registerUcePublishStateCallback");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "registerUcePublishStateCallback");
+
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
boolean isSupportPublishingState = false;
@@ -510,6 +569,10 @@
@Override
public void unregisterUcePublishStateCallback(int subId, IRcsUcePublishStateCallback c) {
enforceReadPrivilegedPermission("unregisterUcePublishStateCallback");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "unregisterUcePublishStateCallback");
+
final long token = Binder.clearCallingIdentity();
try {
UceControllerManager uceCtrlManager = getRcsFeatureController(subId).getFeature(
@@ -534,6 +597,10 @@
+ "isUceSettingEnabled");
return false;
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ FEATURE_TELEPHONY_IMS, "isUceSettingEnabled");
+
final long token = Binder.clearCallingIdentity();
try {
return SubscriptionManager.getBooleanSubscriptionProperty(subId,
@@ -546,6 +613,10 @@
@Override
public void setUceSettingEnabled(int subId, boolean isEnabled) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setUceSettingEnabled");
+
final long token = Binder.clearCallingIdentity();
try {
SubscriptionManager.setSubscriptionProperty(subId,
@@ -680,6 +751,10 @@
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION, "registerSipDialogStateCallback");
+
try {
SipTransportController transport = getRcsFeatureController(subId).getFeature(
SipTransportController.class);
@@ -707,6 +782,10 @@
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION, "unregisterSipDialogStateCallback");
+
try {
SipTransportController transport = getRcsFeatureController(subId).getFeature(
SipTransportController.class);
@@ -897,6 +976,40 @@
PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION);
}
+ /**
+ * Get the current calling package name.
+ * @return the current calling package name
+ */
+ @Nullable
+ private String getCurrentPackageName() {
+ if (mPackageManager == null) return null;
+ String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid());
+ return (callingUids == null) ? null : callingUids[0];
+ }
+
+ /**
+ * Make sure the device has required telephony feature
+ *
+ * @throws UnsupportedOperationException if the device does not have required telephony feature
+ */
+ private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
+ @NonNull String telephonyFeature, @NonNull String methodName) {
+ if (callingPackage == null || mPackageManager == null) {
+ return;
+ }
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+ Binder.getCallingUserHandle())) {
+ return;
+ }
+
+ if (!mPackageManager.hasSystemFeature(telephonyFeature)) {
+ throw new UnsupportedOperationException(
+ methodName + " is unsupported without " + telephonyFeature);
+ }
+ }
+
void setRcsService(TelephonyRcsService rcsService) {
mRcsService = rcsService;
}
diff --git a/src/com/android/phone/PhoneApp.java b/src/com/android/phone/PhoneApp.java
index df151bf..bb663dc 100644
--- a/src/com/android/phone/PhoneApp.java
+++ b/src/com/android/phone/PhoneApp.java
@@ -38,7 +38,11 @@
mPhoneGlobals = new PhoneGlobals(this);
mPhoneGlobals.onCreate();
- TelecomAccountRegistry.getInstance(this).setupOnBoot();
+ TelecomAccountRegistry telecomAccountRegistry =
+ TelecomAccountRegistry.getInstance(this);
+ if (telecomAccountRegistry != null) {
+ telecomAccountRegistry.setupOnBoot();
+ }
}
}
}
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index f93b1e5..0c97cc2 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -78,12 +78,12 @@
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.subscription.SubscriptionManagerService;
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;
@@ -91,6 +91,7 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Global state for the telephony subsystem when running in the primary
@@ -166,7 +167,6 @@
public ImsStateCallbackController mImsStateCallbackController;
public ImsProvisioningController mImsProvisioningController;
CarrierConfigLoader configLoader;
- TelephonyDomainSelectionService mDomainSelectionService;
private Phone phoneInEcm;
@@ -190,13 +190,15 @@
ROAMING_NOTIFICATION_REASON_DATA_ROAMING_SETTING_CHANGED,
ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED,
ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED,
- ROAMING_NOTIFICATION_REASON_DEFAULT_DATA_SUBS_CHANGED})
+ ROAMING_NOTIFICATION_REASON_DEFAULT_DATA_SUBS_CHANGED,
+ ROAMING_NOTIFICATION_REASON_DISCONNECTED_SINGLE_NETWORK})
public @interface RoamingNotificationReason {}
private static final int ROAMING_NOTIFICATION_REASON_DATA_SETTING_CHANGED = 0;
private static final int ROAMING_NOTIFICATION_REASON_DATA_ROAMING_SETTING_CHANGED = 1;
private static final int ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED = 2;
private static final int ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED = 3;
private static final int ROAMING_NOTIFICATION_REASON_DEFAULT_DATA_SUBS_CHANGED = 4;
+ private static final int ROAMING_NOTIFICATION_REASON_DISCONNECTED_SINGLE_NETWORK = 5;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -215,6 +217,14 @@
private int mCurrentRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
/**
+ * If true, update roaming notifications after the Internet is completely disconnected. If
+ * carrier allows only a single data network, wait until the Internet connection is completely
+ * disconnected and then update the roaming notification once more to check if
+ * ONLY_ALLOWED_SINGLE_NETWORK disallow reason is disappeared.
+ */
+ private AtomicBoolean mWaitForInternetDisconnection = new AtomicBoolean(false);
+
+ /**
* Reasons that have already shown notification to prevent duplicate shows for the same reason.
*/
private ArraySet<String> mShownNotificationReasons = new ArraySet<>();
@@ -243,17 +253,18 @@
private final CarrierVvmPackageInstalledReceiver mCarrierVvmPackageInstalledReceiver =
new CarrierVvmPackageInstalledReceiver();
- private final SettingsObserver mSettingsObserver;
+ private SettingsObserver mSettingsObserver;
private BinderCallsStats.SettingsObserver mBinderCallsSettingsObserver;
// Mapping of phone ID to the associated TelephonyCallback. These should be registered without
// fine or coarse location since we only use ServiceState for
private PhoneAppCallback[] mTelephonyCallbacks;
- private FeatureFlags mFeatureFlags;
+ private FeatureFlags mFeatureFlags = new FeatureFlagsImpl();
private class PhoneAppCallback extends TelephonyCallback implements
- TelephonyCallback.ServiceStateListener {
+ TelephonyCallback.ServiceStateListener,
+ TelephonyCallback.DataConnectionStateListener {
private final int mSubId;
PhoneAppCallback(int subId) {
@@ -267,6 +278,23 @@
handleServiceStateChanged(serviceState, mSubId);
}
+ @Override
+ public void onDataConnectionStateChanged(int state, int networkType) {
+ if (mSubId == mDefaultDataSubId && state == TelephonyManager.DATA_DISCONNECTED) {
+ // onDataConnectionStateChanged is an event about the state of exact DataNetwork,
+ // but since the DataNetwork of internet may not have been completely removed from
+ // the DataNetworkController list, The post handler event expects the internet data
+ // network to be completely removed from the DataNetworkController list.
+ mHandler.post(() -> {
+ if (mWaitForInternetDisconnection.compareAndSet(true, false)) {
+ Log.d(LOG_TAG, "onDisconnectedInternetDataNetwork.");
+ updateDataRoamingStatus(
+ ROAMING_NOTIFICATION_REASON_DISCONNECTED_SINGLE_NETWORK);
+ }
+ });
+ }
+ }
+
public int getSubId() {
return mSubId;
}
@@ -344,11 +372,23 @@
break;
case EVENT_DATA_ROAMING_DISCONNECTED:
- notificationMgr.showDataRoamingNotification(msg.arg1, false);
+ if (SubscriptionManagerService.getInstance()
+ .isEsimBootStrapProvisioningActiveForSubId(msg.arg1)) {
+ Log.i(LOG_TAG,
+ "skip notification/warnings during esim bootstrap activation");
+ } else {
+ notificationMgr.showDataRoamingNotification(msg.arg1, false);
+ }
break;
case EVENT_DATA_ROAMING_CONNECTED:
- notificationMgr.showDataRoamingNotification(msg.arg1, true);
+ if (SubscriptionManagerService.getInstance()
+ .isEsimBootStrapProvisioningActiveForSubId(msg.arg1)) {
+ Log.i(LOG_TAG,
+ "skip notification/warnings during esim bootstrap activation");
+ } else {
+ notificationMgr.showDataRoamingNotification(msg.arg1, true);
+ }
break;
case EVENT_DATA_ROAMING_OK:
@@ -464,7 +504,13 @@
public PhoneGlobals(Context context) {
super(context);
sMe = this;
- mSettingsObserver = new SettingsObserver(context, mHandler);
+ if (mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()) {
+ if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ mSettingsObserver = new SettingsObserver(context, mHandler);
+ }
+ } else {
+ mSettingsObserver = new SettingsObserver(context, mHandler);
+ }
}
public void onCreate() {
@@ -472,6 +518,13 @@
ContentResolver resolver = getContentResolver();
+ if (mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()) {
+ if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ Log.v(LOG_TAG, "onCreate()... but not defined FEATURE_TELEPHONY");
+ return;
+ }
+ }
+
// Initialize the shim from frameworks/opt/telephony into packages/services/Telephony.
TelephonyLocalConnection.setInstance(new LocalConnectionImpl(this));
@@ -496,18 +549,17 @@
// 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));
+ String dssComponentName = getResources().getString(
+ R.string.config_domain_selection_service_component_name);
+ DomainSelectionResolver.make(this, dssComponentName);
// Initialize the telephony framework
- mFeatureFlags = new FeatureFlagsImpl();
PhoneFactory.makeDefaultPhones(this, mFeatureFlags);
// 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);
+ DomainSelectionResolver.getInstance().initialize();
// Initialize EmergencyStateTracker if domain selection is supported
boolean isSuplDdsSwitchRequiredForEmergencyCall = getResources()
.getBoolean(R.bool.config_gnss_supl_requires_default_data_for_emergency);
@@ -576,19 +628,20 @@
phoneMgr = PhoneInterfaceManager.init(this, mFeatureFlags);
- imsRcsController = ImsRcsController.init(this);
+ imsRcsController = ImsRcsController.init(this, mFeatureFlags);
- configLoader = CarrierConfigLoader.init(this);
+ configLoader = CarrierConfigLoader.init(this, mFeatureFlags);
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
mImsStateCallbackController =
ImsStateCallbackController.make(this, PhoneFactory.getPhones().length);
mTelephonyRcsService = new TelephonyRcsService(this,
- PhoneFactory.getPhones().length);
+ PhoneFactory.getPhones().length, mFeatureFlags);
mTelephonyRcsService.initialize();
imsRcsController.setRcsService(mTelephonyRcsService);
mImsProvisioningController =
- ImsProvisioningController.make(this, PhoneFactory.getPhones().length);
+ ImsProvisioningController.make(this, PhoneFactory.getPhones().length,
+ mFeatureFlags);
}
// Create the CallNotifier singleton, which handles
@@ -983,10 +1036,9 @@
* 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 reason to inform which event is called for notification update.
+ * @param notificationReason to inform which event is called for notification update.
*/
- private void updateDataRoamingStatus(@RoamingNotificationReason int reason) {
- if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
+ private void updateDataRoamingStatus(@RoamingNotificationReason int notificationReason) {
Phone phone = getPhone(mDefaultDataSubId);
if (phone == null) {
Log.w(LOG_TAG, "Can't get phone with sub id = " + mDefaultDataSubId);
@@ -994,20 +1046,64 @@
}
ServiceState serviceState = phone.getServiceState();
+ if (serviceState == null) {
+ Log.e(LOG_TAG, "updateDataRoamingStatus: serviceState is null");
+ return;
+ }
+
+ List<DataDisallowedReason> disallowReasons = phone.getDataNetworkController()
+ .getInternetDataDisallowedReasons();
+
+ if (mFeatureFlags.roamingNotificationForSingleDataNetwork()) {
+ if (disallowReasons.contains(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)
+ && disallowReasons.contains(DataDisallowedReason.ROAMING_DISABLED)
+ && (notificationReason == ROAMING_NOTIFICATION_REASON_DATA_SETTING_CHANGED
+ || notificationReason
+ == ROAMING_NOTIFICATION_REASON_DATA_ROAMING_SETTING_CHANGED)) {
+ // If the ONLY_ALLOWED_SINGLE_NETWORK disallow reason has not yet been removed due
+ // to a change in mobile_data (including roaming_data) settings, update roaming
+ // notification again after the Internet is completely disconnected to check
+ // ONLY_ALLOWED_SINGLE_NETWORK disallow reason is removed.
+ mWaitForInternetDisconnection.set(true);
+ Log.d(LOG_TAG, "updateDataRoamingStatus,"
+ + " wait for internet disconnection for single data network");
+ } else if (!disallowReasons.contains(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)
+ && mWaitForInternetDisconnection.compareAndSet(true, false)) {
+ // If the ONLY_ALLOWED_SINGLE_NETWORK disallow reason has been removed,
+ // no longer wait for Internet disconnection.
+ Log.d(LOG_TAG, "updateDataRoamingStatus,"
+ + " cancel to wait for internet disconnection for single data network");
+ }
+ }
+
+ updateDataRoamingStatus(notificationReason, disallowReasons, serviceState);
+ }
+
+ /**
+ * 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 notificationReason to inform which event is called for notification update.
+ * @param disallowReasons List of reasons why internet data is not allowed. An empty list if
+ * internet is allowed.
+ * @param serviceState Service state from phone
+ */
+ private void updateDataRoamingStatus(@RoamingNotificationReason int notificationReason,
+ List<DataDisallowedReason> disallowReasons, ServiceState serviceState) {
+
+ if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
String roamingNumeric = serviceState.getOperatorNumeric();
String roamingNumericReason = "RoamingNumeric=" + roamingNumeric;
- String callingReason = "CallingReason=" + reason;
+ String callingReason = "CallingReason=" + notificationReason;
boolean dataIsNowRoaming = serviceState.getDataRoaming();
boolean dataAllowed;
boolean notAllowedDueToRoamingOff;
- List<DataDisallowedReason> reasons = phone.getDataNetworkController()
- .getInternetDataDisallowedReasons();
- dataAllowed = reasons.isEmpty();
- notAllowedDueToRoamingOff = (reasons.size() == 1
- && reasons.contains(DataDisallowedReason.ROAMING_DISABLED));
+ dataAllowed = disallowReasons.isEmpty();
+ notAllowedDueToRoamingOff = (disallowReasons.size() == 1
+ && disallowReasons.contains(DataDisallowedReason.ROAMING_DISABLED));
StringBuilder sb = new StringBuilder("updateDataRoamingStatus");
sb.append(" dataAllowed=").append(dataAllowed);
- sb.append(", reasons=").append(reasons);
+ sb.append(", disallowReasons=").append(disallowReasons);
sb.append(", dataIsNowRoaming=").append(dataIsNowRoaming);
sb.append(", ").append(roamingNumericReason);
sb.append(", ").append(callingReason);
@@ -1018,8 +1114,8 @@
// Determine if a given roaming numeric has never been shown.
boolean shownInThisNumeric = false;
- if (reason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED
- || reason == ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED) {
+ if (notificationReason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED
+ || notificationReason == ROAMING_NOTIFICATION_REASON_SERVICE_STATE_CHANGED) {
shownInThisNumeric = mShownNotificationReasons.contains(roamingNumericReason);
}
// Determine if a notification has never been shown by given calling reason.
@@ -1030,7 +1126,7 @@
mShownNotificationReasons.add(roamingNumericReason);
}
if (!shownForThisReason
- && reason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
+ && notificationReason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
mShownNotificationReasons.add(callingReason);
}
// No need to show it again if we never cancelled it explicitly.
@@ -1057,7 +1153,7 @@
mShownNotificationReasons.add(roamingNumericReason);
}
if (!shownForThisReason
- && reason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
+ && notificationReason == ROAMING_NOTIFICATION_REASON_CARRIER_CONFIG_CHANGED) {
mShownNotificationReasons.add(callingReason);
}
boolean shouldShowRoamingNotification = shouldShowRoamingNotification(roamingNumeric);
@@ -1170,7 +1266,8 @@
msg.arg1 = mDefaultDataSubId;
msg.sendToTarget();
} else if (dataAllowed && dataIsNowRoaming(mDefaultDataSubId)) {
- if (!shouldShowRoamingNotification(roamingOperatorNumeric)) {
+ if (!shouldShowRoamingNotification(roamingOperatorNumeric != null
+ ? roamingOperatorNumeric : phone.getServiceState().getOperatorNumeric())) {
Log.d(LOG_TAG, "Skip showing roaming connected notification.");
return;
}
@@ -1385,9 +1482,6 @@
e.printStackTrace();
}
pw.decreaseIndent();
- if (mDomainSelectionService != null) {
- mDomainSelectionService.dump(fd, pw, args);
- }
pw.decreaseIndent();
if (mFeatureFlags.reorganizeRoamingNotification()) {
pw.println("mShownNotificationReasons=" + mShownNotificationReasons);
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 3bd29e3..2779bdb 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -16,10 +16,17 @@
package com.android.phone;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_IMS;
+import static android.content.pm.PackageManager.FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.permission.flags.Flags.opEnableMobileDataByUser;
+import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING;
import static android.telephony.TelephonyManager.HAL_SERVICE_NETWORK;
import static android.telephony.TelephonyManager.HAL_SERVICE_RADIO;
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ACCESS_BARRED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
@@ -150,8 +157,9 @@
import android.telephony.satellite.INtnSignalStrengthCallback;
import android.telephony.satellite.ISatelliteCapabilitiesCallback;
import android.telephony.satellite.ISatelliteDatagramCallback;
+import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
-import android.telephony.satellite.ISatelliteStateCallback;
+import android.telephony.satellite.ISatelliteSupportedStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.NtnSignalStrengthCallback;
@@ -207,6 +215,7 @@
import com.android.internal.telephony.SmsApplication;
import com.android.internal.telephony.SmsController;
import com.android.internal.telephony.SmsPermissions;
+import com.android.internal.telephony.TelephonyCountryDetector;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyPermissions;
import com.android.internal.telephony.data.DataUtils;
@@ -240,6 +249,8 @@
import com.android.phone.callcomposer.CallComposerPictureManager;
import com.android.phone.callcomposer.CallComposerPictureTransfer;
import com.android.phone.callcomposer.ImageData;
+import com.android.phone.satellite.accesscontrol.SatelliteAccessController;
+import com.android.phone.satellite.entitlement.SatelliteEntitlementController;
import com.android.phone.settings.PickSmsSubscriptionActivity;
import com.android.phone.slice.SlicePurchaseController;
import com.android.phone.utils.CarrierAllowListInfo;
@@ -247,6 +258,7 @@
import com.android.phone.vvm.RemoteVvmTaskManager;
import com.android.phone.vvm.VisualVoicemailSettingsUtil;
import com.android.phone.vvm.VisualVoicemailSmsFilterConfig;
+import com.android.server.feature.flags.Flags;
import com.android.services.telephony.TelecomAccountRegistry;
import com.android.services.telephony.TelephonyConnectionService;
import com.android.telephony.Rlog;
@@ -403,28 +415,32 @@
private static final int MIN_NULL_CIPHER_AND_INTEGRITY_VERSION = 201;
// Cellular identifier disclosure transparency was added in IRadioNetwork 2.2
private static final int MIN_IDENTIFIER_DISCLOSURE_VERSION = 202;
+ // Null cipher notification support was added in IRadioNetwork 2.2
+ private static final int MIN_NULL_CIPHER_NOTIFICATION_VERSION = 202;
/** The singleton instance. */
private static PhoneInterfaceManager sInstance;
private static List<String> sThermalMitigationAllowlistedPackages = new ArrayList<>();
private final PhoneGlobals mApp;
- private final FeatureFlags mFeatureFlags;
+ private FeatureFlags mFeatureFlags;
+ private com.android.server.telecom.flags.FeatureFlags mTelecomFeatureFlags;
private final CallManager mCM;
private final ImsResolver mImsResolver;
private final SatelliteController mSatelliteController;
+ private final SatelliteAccessController mSatelliteAccessController;
private final UserManager mUserManager;
- private final AppOpsManager mAppOps;
private final MainThreadHandler mMainThreadHandler;
private final SharedPreferences mTelephonySharedPreferences;
private final PhoneConfigurationManager mPhoneConfigurationManager;
private final RadioInterfaceCapabilityController mRadioInterfaceCapabilities;
+ private AppOpsManager mAppOps;
+ private PackageManager mPackageManager;
/** User Activity */
private final AtomicBoolean mNotifyUserActivity;
private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
-
private final Set<Integer> mCarrierPrivilegeTestOverrideSubIds = new ArraySet<>();
private static final String PREF_CARRIERS_ALPHATAG_PREFIX = "carrier_alphtag_";
@@ -1573,7 +1589,7 @@
// This is for the implementation of carrierRestrictionStatus.
CallerCallbackInfo callbackInfo = (CallerCallbackInfo) request.argument;
Consumer<Integer> callback = callbackInfo.getConsumer();
- int callerCarrierId = callbackInfo.getCarrierId();
+ Set<Integer> callerCarrierIds = callbackInfo.getCarrierIds();
int lockStatus = TelephonyManager.CARRIER_RESTRICTION_STATUS_UNKNOWN;
if (ar.exception == null && ar.result instanceof CarrierRestrictionRules) {
CarrierRestrictionRules carrierRestrictionRules =
@@ -1588,8 +1604,10 @@
Rlog.e(LOG_TAG, "CarrierIdentifier exception = " + ex);
}
lockStatus = carrierRestrictionRules.getCarrierRestrictionStatus();
- if (carrierId != -1 && callerCarrierId == carrierId && lockStatus
- == TelephonyManager.CARRIER_RESTRICTION_STATUS_RESTRICTED) {
+ int restrictedStatus =
+ TelephonyManager.CARRIER_RESTRICTION_STATUS_RESTRICTED;
+ if (carrierId != -1 && callerCarrierIds.contains(carrierId) &&
+ lockStatus == restrictedStatus) {
lockStatus = TelephonyManager
.CARRIER_RESTRICTION_STATUS_RESTRICTED_TO_CALLER;
}
@@ -2449,6 +2467,7 @@
private PhoneInterfaceManager(PhoneGlobals app, FeatureFlags featureFlags) {
mApp = app;
mFeatureFlags = featureFlags;
+ mTelecomFeatureFlags = new com.android.server.telecom.flags.FeatureFlagsImpl();
mCM = PhoneGlobals.getInstance().mCM;
mImsResolver = ImsResolver.getInstance();
mSatelliteController = SatelliteController.getInstance();
@@ -2460,9 +2479,16 @@
mPhoneConfigurationManager = PhoneConfigurationManager.getInstance();
mRadioInterfaceCapabilities = RadioInterfaceCapabilityController.getInstance();
mNotifyUserActivity = new AtomicBoolean(false);
+ mPackageManager = app.getPackageManager();
+ mSatelliteAccessController = SatelliteAccessController.getOrCreateInstance(
+ getDefaultPhone().getContext(), featureFlags);
PropertyInvalidatedCache.invalidateCache(TelephonyManager.CACHE_KEY_PHONE_ACCOUNT_TO_SUBID);
publish();
CarrierAllowListInfo.loadInstance(mApp);
+
+ // Create the SatelliteEntitlementController singleton, for using the get the
+ // entitlementStatus for satellite service.
+ SatelliteEntitlementController.make(mApp, mFeatureFlags);
}
@VisibleForTesting
@@ -2554,6 +2580,9 @@
}
public void dial(String number) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "dial");
+
dialForSubscriber(getPreferredVoiceSubscription(), number);
}
@@ -2599,6 +2628,9 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "call");
+
final long identity = Binder.clearCallingIdentity();
try {
String url = createTelUrl(number);
@@ -2642,6 +2674,10 @@
public int[] supplyPinReportResultForSubscriber(int subId, String pin) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "supplyPinReportResultForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -2656,6 +2692,9 @@
public int[] supplyPukReportResultForSubscriber(int subId, String puk, String pin) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "supplyPukForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -2861,6 +2900,9 @@
return false;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "isRadioOnWithFeature");
+
final long identity = Binder.clearCallingIdentity();
try {
return isRadioOnForSubscriber(subId);
@@ -2890,6 +2932,9 @@
public void toggleRadioOnOffForSubscriber(int subId) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "toggleRadioOnOffForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -2925,6 +2970,10 @@
public boolean needMobileRadioShutdown() {
enforceReadPrivilegedPermission("needMobileRadioShutdown");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "needMobileRadioShutdown");
+
/*
* If any of the Radios are available, it will need to be
* shutdown. So return true if any Radio is available.
@@ -2946,6 +2995,9 @@
public void shutdownMobileRadios() {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "shutdownMobileRadios");
+
final long identity = Binder.clearCallingIdentity();
try {
for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
@@ -3027,6 +3079,9 @@
@TelephonyManager.RadioPowerReason int reason) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "requestRadioPowerOffForReason");
+
log("requestRadioPowerOffForReason: subId=" + subId
+ ",reason=" + reason + ",callingPackage=" + getCurrentPackageName());
final long identity = Binder.clearCallingIdentity();
@@ -3057,6 +3112,9 @@
@TelephonyManager.RadioPowerReason int reason) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "clearRadioPowerOffForReason");
+
final long identity = Binder.clearCallingIdentity();
try {
boolean result = false;
@@ -3084,6 +3142,9 @@
public List getRadioPowerOffReasons(int subId, String callingPackage, String callingFeatureId) {
enforceReadPrivilegedPermission("getRadioPowerOffReasons");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getRadioPowerOffReasons");
+
final long identity = Binder.clearCallingIdentity();
List result = new ArrayList();
try {
@@ -3109,6 +3170,9 @@
public boolean enableDataConnectivity(String callingPackage) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_DATA, "enableDataConnectivity");
+
final long identity = Binder.clearCallingIdentity();
try {
int subId = SubscriptionManager.getDefaultDataSubscriptionId();
@@ -3130,6 +3194,9 @@
public boolean disableDataConnectivity(String callingPackage) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_DATA, "disableDataConnectivity");
+
final long identity = Binder.clearCallingIdentity();
try {
int subId = SubscriptionManager.getDefaultDataSubscriptionId();
@@ -3148,6 +3215,9 @@
@Override
public boolean isDataConnectivityPossible(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isDataConnectivityPossible");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3168,6 +3238,9 @@
public void handleUssdRequest(int subId, String ussdRequest, ResultReceiver wrappedCallback) {
enforceCallPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "handleUssdRequest");
+
final long identity = Binder.clearCallingIdentity();
try {
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -3183,6 +3256,9 @@
public boolean handlePinMmiForSubscriber(int subId, String dialString) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "handlePinMmiForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -3230,6 +3306,10 @@
+ "targeting API level 31+.");
}
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getCallStateForSubscription");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -3247,6 +3327,9 @@
@Override
public int getDataStateForSubId(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "getDataStateForSubId");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3268,6 +3351,9 @@
@Override
public @DataActivityType int getDataActivityForSubId(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "getDataActivityForSubId");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3305,6 +3391,9 @@
? new CellIdentityCdma() : new CellIdentityGsm();
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getCellLocation");
+
WorkSource workSource = getWorkSource(Binder.getCallingUid());
final long identity = Binder.clearCallingIdentity();
try {
@@ -3318,6 +3407,9 @@
@Override
public String getNetworkCountryIsoForPhone(int phoneId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getNetworkCountryIsoForPhone");
+
// Reporting the correct network country is ambiguous when IWLAN could conflict with
// registered cell info, so return a NULL country instead.
final long identity = Binder.clearCallingIdentity();
@@ -3388,6 +3480,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getNeighboringCellInfo");
+
if (DBG_LOC) log("getNeighboringCellInfo: is active user");
List<CellInfo> info = getAllCellInfo(callingPackage, callingFeatureId);
@@ -3441,6 +3536,9 @@
return getCachedCellInfo();
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getAllCellInfo");
+
if (DBG_LOC) log("getAllCellInfo: is active user");
WorkSource workSource = getWorkSource(Binder.getCallingUid());
final long identity = Binder.clearCallingIdentity();
@@ -3509,6 +3607,8 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "requestCellInfoUpdateInternal");
final Phone phone = getPhoneFromSubId(subId);
if (phone == null) throw new IllegalArgumentException("Invalid Subscription Id: " + subId);
@@ -3547,6 +3647,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_GSM, "getImeiForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
return phone.getImei();
@@ -3562,6 +3665,10 @@
callingFeatureId, "getPrimaryImei")) {
throw new SecurityException("Caller does not have permission");
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_GSM, "getPrimaryImei");
+
final long identity = Binder.clearCallingIdentity();
try {
for (Phone phone : PhoneFactory.getPhones()) {
@@ -3577,6 +3684,9 @@
@Override
public String getTypeAllocationCodeForSlot(int slotIndex) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_GSM, "getTypeAllocationCodeForSlot");
+
Phone phone = PhoneFactory.getPhone(slotIndex);
String tac = null;
if (phone != null) {
@@ -3611,6 +3721,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CDMA, "getMeidForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
return phone.getMeid();
@@ -3621,6 +3734,9 @@
@Override
public String getManufacturerCodeForSlot(int slotIndex) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CDMA, "getManufacturerCodeForSlot");
+
Phone phone = PhoneFactory.getPhone(slotIndex);
String manufacturerCode = null;
if (phone != null) {
@@ -3650,6 +3766,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY, "getDeviceSoftwareVersionForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
return phone.getDeviceSvn();
@@ -3660,6 +3779,9 @@
@Override
public int getSubscriptionCarrierId(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSubscriptionCarrierId");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3671,6 +3793,9 @@
@Override
public String getSubscriptionCarrierName(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSubscriptionCarrierName");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3682,6 +3807,9 @@
@Override
public int getSubscriptionSpecificCarrierId(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSubscriptionSpecificCarrierId");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3694,6 +3822,10 @@
@Override
public String getSubscriptionSpecificCarrierName(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getSubscriptionSpecificCarrierName");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3712,6 +3844,10 @@
if (phone == null) {
return TelephonyManager.UNKNOWN_CARRIER_ID;
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getCarrierIdFromMccMnc");
+
final long identity = Binder.clearCallingIdentity();
try {
return CarrierResolver.getCarrierIdFromMccMnc(phone.getContext(), mccmnc);
@@ -3832,6 +3968,9 @@
@Override
public int getActivePhoneTypeForSlot(int slotIndex) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY, "getActivePhoneTypeForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = PhoneFactory.getPhone(slotIndex);
@@ -3863,6 +4002,10 @@
return -1;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CDMA,
+ "getCdmaEriIconIndexForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3948,6 +4091,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "getCdmaMdn");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CDMA, "getCdmaMdn");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3970,6 +4116,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "getCdmaMin");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CDMA, "getCdmaMin");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3999,6 +4148,9 @@
+ ", configured package: " + authorizedPackage);
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "requestNumberVerification");
+
if (range == null) {
throw new NullPointerException("Range must be non-null");
}
@@ -4013,6 +4165,9 @@
* Returns true if CDMA provisioning needs to run.
*/
public boolean needsOtaServiceProvisioning() {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "needsOtaServiceProvisioning");
+
final long identity = Binder.clearCallingIdentity();
try {
return getDefaultPhone().needsOtaServiceProvisioning();
@@ -4029,6 +4184,9 @@
TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(
mApp, subId, "setVoiceMailNumber");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setVoiceMailNumber");
+
final long identity = Binder.clearCallingIdentity();
try {
Boolean success = (Boolean) sendRequest(CMD_SET_VOICEMAIL_NUMBER,
@@ -4048,6 +4206,9 @@
throw new SecurityException("caller must be system dialer");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getVisualVoicemailSettings");
+
final long identity = Binder.clearCallingIdentity();
try {
PhoneAccountHandle phoneAccountHandle = PhoneAccountHandleConverter.fromSubId(subId);
@@ -4070,6 +4231,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getVisualVoicemailPackageName");
+
final long identity = Binder.clearCallingIdentity();
try {
return RemoteVvmTaskManager.getRemotePackage(mApp, subId).getPackageName();
@@ -4083,6 +4247,9 @@
VisualVoicemailSmsFilterSettings settings) {
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "enableVisualVoicemailSmsFilter");
+
final long identity = Binder.clearCallingIdentity();
try {
VisualVoicemailSmsFilterConfig.enableVisualVoicemailSmsFilter(
@@ -4096,6 +4263,9 @@
public void disableVisualVoicemailSmsFilter(String callingPackage, int subId) {
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "disableVisualVoicemailSmsFilter");
+
final long identity = Binder.clearCallingIdentity();
try {
VisualVoicemailSmsFilterConfig.disableVisualVoicemailSmsFilter(
@@ -4139,6 +4309,10 @@
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
enforceVisualVoicemailPackage(callingPackage, subId);
enforceSendSmsPermission();
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "sendVisualVoicemailSmsForSubscriber");
+
SmsController smsController = PhoneFactory.getSmsController();
smsController.sendVisualVoicemailSmsForSubscriber(callingPackage, callingAttributionTag,
subId, number, port, text, sentIntent);
@@ -4152,6 +4326,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setVoiceActivationState");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setVoiceActivationState");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -4173,6 +4350,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setDataActivationState");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "setDataActivationState");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -4193,6 +4373,9 @@
public int getVoiceActivationState(int subId, String callingPackage) {
enforceReadPrivilegedPermission("getVoiceActivationState");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getVoiceActivationState");
+
final Phone phone = getPhone(subId);
final long identity = Binder.clearCallingIdentity();
try {
@@ -4213,6 +4396,9 @@
public int getDataActivationState(int subId, String callingPackage) {
enforceReadPrivilegedPermission("getDataActivationState");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_DATA, "getDataActivationState");
+
final Phone phone = getPhone(subId);
final long identity = Binder.clearCallingIdentity();
try {
@@ -4256,6 +4442,9 @@
*/
@Override
public boolean isConcurrentVoiceAndDataAllowed(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isConcurrentVoiceAndDataAllowed");
+
final long identity = Binder.clearCallingIdentity();
try {
return getPhoneFromSubIdOrDefault(subId).isConcurrentVoiceAndDataAllowed();
@@ -4280,6 +4469,9 @@
getDefaultSubscription(), "sendDialerSpecialCode");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "sendDialerSpecialCode");
+
final long identity = Binder.clearCallingIdentity();
try {
defaultPhone.sendDialerSpecialCode(inputCode);
@@ -4293,6 +4485,10 @@
TelephonyPermissions
.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getNetworkSelectionMode");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getNetworkSelectionMode");
+
final long identity = Binder.clearCallingIdentity();
try {
if (!isActiveSubscription(subId)) {
@@ -4307,6 +4503,10 @@
@Override
public boolean isInEmergencySmsMode() {
enforceReadPrivilegedPermission("isInEmergencySmsMode");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_MESSAGING, "isInEmergencySmsMode");
+
final long identity = Binder.clearCallingIdentity();
try {
for (Phone phone : PhoneFactory.getPhones()) {
@@ -4391,6 +4591,76 @@
}
/**
+ * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
+ * @param subId The subscription to use to check the configuration.
+ * @param c The callback that will be used to send the result.
+ */
+ @Override
+ public void registerImsEmergencyRegistrationCallback(int subId, IImsRegistrationCallback c)
+ throws RemoteException {
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "registerImsEmergencyRegistrationCallback");
+
+ if (!ImsManager.isImsSupportedOnDevice(mApp)) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "IMS not available on device.");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ int slotId = getSlotIndexOrException(subId);
+ verifyImsMmTelConfiguredOrThrow(slotId);
+
+ ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+ if (controller != null) {
+ ImsManager imsManager = controller.getImsManager(subId);
+ if (imsManager != null) {
+ imsManager.addEmergencyRegistrationCallbackForSubscription(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 {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ /**
+ * Requires carrier privileges or READ_PRECISE_PHONE_STATE permission.
+ * @param subId The subscription to use to check the configuration.
+ * @param c The callback that will be used to send the result.
+ */
+ @Override
+ public void unregisterImsEmergencyRegistrationCallback(int subId, IImsRegistrationCallback c) {
+ TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
+ mApp, subId, "unregisterImsEmergencyRegistrationCallback");
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
+ }
+ final long token = Binder.clearCallingIdentity();
+
+ try {
+ ImsStateCallbackController controller = ImsStateCallbackController.getInstance();
+ if (controller != null) {
+ ImsManager imsManager = controller.getImsManager(subId);
+ if (imsManager != null) {
+ imsManager.removeEmergencyRegistrationCallbackForSubscription(c, subId);
+ } else {
+ Log.i(LOG_TAG, "unregisterImsEmergencyRegistrationCallback: " + 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);
+ }
+ }
+
+ /**
* Get the IMS service registration state for the MmTelFeature associated with this sub id.
*/
@Override
@@ -4531,6 +4801,10 @@
@Override
public boolean isCapable(int subId, int capability, int regTech) {
enforceReadPrivilegedPermission("isCapable");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isCapable");
+
final long token = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4550,6 +4824,10 @@
@Override
public boolean isAvailable(int subId, int capability, int regTech) {
enforceReadPrivilegedPermission("isAvailable");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isAvailable");
+
final long token = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -4613,6 +4891,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isAdvancedCallingSettingEnabled");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isAdvancedCallingSettingEnabled");
+
final long token = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4629,6 +4910,10 @@
public void setAdvancedCallingSettingEnabled(int subId, boolean isEnabled) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setAdvancedCallingSettingEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setAdvancedCallingSettingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4650,6 +4935,10 @@
public boolean isVtSettingEnabled(int subId) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isVtSettingEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isVtSettingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4666,6 +4955,10 @@
public void setVtSettingEnabled(int subId, boolean isEnabled) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setVtSettingEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setVtSettingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4687,6 +4980,10 @@
public boolean isVoWiFiSettingEnabled(int subId) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isVoWiFiSettingEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isVoWiFiSettingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4703,6 +5000,10 @@
public void setVoWiFiSettingEnabled(int subId, boolean isEnabled) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setVoWiFiSettingEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setVoWiFiSettingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4725,6 +5026,10 @@
public boolean isCrossSimCallingEnabledByUser(int subId) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isCrossSimCallingEnabledByUser");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isCrossSimCallingEnabledByUser");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4748,6 +5053,10 @@
public void setCrossSimCallingEnabled(int subId, boolean isEnabled) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setCrossSimCallingEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setCrossSimCallingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4770,6 +5079,10 @@
public boolean isVoWiFiRoamingSettingEnabled(int subId) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isVoWiFiRoamingSettingEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isVoWiFiRoamingSettingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4786,6 +5099,10 @@
public void setVoWiFiRoamingSettingEnabled(int subId, boolean isEnabled) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setVoWiFiRoamingSettingEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setVoWiFiRoamingSettingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4803,6 +5120,10 @@
public void setVoWiFiNonPersistent(int subId, boolean isCapable, int mode) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setVoWiFiNonPersistent");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setVoWiFiNonPersistent");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4823,6 +5144,10 @@
public int getVoWiFiModeSetting(int subId) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getVoWiFiModeSetting");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getVoWiFiModeSetting");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4839,6 +5164,10 @@
public void setVoWiFiModeSetting(int subId, int mode) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setVoWiFiModeSetting");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setVoWiFiModeSetting");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4855,6 +5184,10 @@
@Override
public int getVoWiFiRoamingModeSetting(int subId) {
enforceReadPrivilegedPermission("getVoWiFiRoamingModeSetting");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getVoWiFiRoamingModeSetting");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4871,6 +5204,10 @@
public void setVoWiFiRoamingModeSetting(int subId, int mode) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setVoWiFiRoamingModeSetting");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setVoWiFiRoamingModeSetting");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4888,6 +5225,10 @@
public void setRttCapabilitySetting(int subId, boolean isEnabled) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setRttCapabilityEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setRttCapabilitySetting");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4909,6 +5250,10 @@
public boolean isTtyOverVolteEnabled(int subId) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isTtyOverVolteEnabled");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isTtyOverVolteEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -5034,6 +5379,9 @@
boolean isProvisioned) {
checkModifyPhoneStatePermission(subId, "setRcsProvisioningStatusForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setRcsProvisioningStatusForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5054,6 +5402,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getRcsProvisioningStatusForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getRcsProvisioningStatusForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5074,6 +5425,9 @@
boolean isProvisioned) {
checkModifyPhoneStatePermission(subId, "setImsProvisioningStatusForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setImsProvisioningStatusForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5093,6 +5447,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getProvisioningStatusForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getImsProvisioningStatusForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5113,6 +5470,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isProvisioningRequiredForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isProvisioningRequiredForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5133,6 +5493,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isProvisioningRequiredForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isRcsProvisioningRequiredForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5156,6 +5519,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getImsProvisioningInt");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getImsProvisioningInt");
+
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
@@ -5196,6 +5562,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getImsProvisioningString");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getImsProvisioningString");
+
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
@@ -5223,6 +5592,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setImsProvisioningInt");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setImsProvisioningInt");
+
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
@@ -5262,6 +5634,10 @@
}
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp, subId,
"setImsProvisioningString");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setImsProvisioningString");
+
final long identity = Binder.clearCallingIdentity();
try {
// TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
@@ -5335,6 +5711,9 @@
return TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getNetworkTypeForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -5372,6 +5751,9 @@
}
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getDataNetworkTypeForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -5400,6 +5782,9 @@
}
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getVoiceNetworkTypeForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -5427,6 +5812,9 @@
*/
@Override
public boolean hasIccCardUsingSlotIndex(int slotIndex) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "hasIccCardUsingSlotIndex");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = PhoneFactory.getPhone(slotIndex);
@@ -5464,6 +5852,9 @@
return PhoneConstants.LTE_ON_CDMA_UNKNOWN;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getLteOnCdmaModeForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -5545,6 +5936,7 @@
@Override
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(
@NonNull IccLogicalChannelRequest request) {
+
Phone phone = getPhoneFromValidIccLogicalChannelRequest(request,
/*message=*/ "iccOpenLogicalChannel");
@@ -5552,6 +5944,9 @@
// Verify that the callingPackage in the request belongs to the calling UID
mAppOps.checkPackage(Binder.getCallingUid(), request.callingPackage);
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "iccOpenLogicalChannel");
+
return iccOpenLogicalChannelWithPermission(phone, request);
}
@@ -5598,6 +5993,9 @@
@Override
public boolean iccCloseLogicalChannel(@NonNull IccLogicalChannelRequest request) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "iccCloseLogicalChannel");
+
Phone phone = getPhoneFromValidIccLogicalChannelRequest(request,
/*message=*/"iccCloseLogicalChannel");
@@ -5645,6 +6043,10 @@
int command, int p1, int p2, int p3, String data) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "iccTransmitApduLogicalChannel");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "iccTransmitApduLogicalChannel");
+
if (DBG) {
log("iccTransmitApduLogicalChannel: subId=" + subId + " chnl=" + channel
+ " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2=" + p2 + " p3="
@@ -5658,6 +6060,11 @@
public String iccTransmitApduLogicalChannelByPort(int slotIndex, int portIndex, int channel,
int cla, int command, int p1, int p2, int p3, String data) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "iccTransmitApduLogicalChannelBySlot");
+
if (DBG) {
log("iccTransmitApduLogicalChannelByPort: slotIndex=" + slotIndex + " portIndex="
+ portIndex + " chnl=" + channel + " cla=" + cla + " cmd=" + command + " p1="
@@ -5699,6 +6106,10 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "iccTransmitApduBasicChannel");
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "iccTransmitApduBasicChannel");
+
if (DBG) {
log("iccTransmitApduBasicChannel: subId=" + subId + " cla=" + cla + " cmd="
+ command + " p1=" + p1 + " p2=" + p2 + " p3=" + p3 + " data=" + data);
@@ -5712,6 +6123,10 @@
String callingPackage, int cla, int command, int p1, int p2, int p3, String data) {
enforceModifyPermission();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "iccTransmitApduBasicChannelBySlot");
+
if (DBG) {
log("iccTransmitApduBasicChannelByPort: slotIndex=" + slotIndex + " portIndex="
+ portIndex + " cla=" + cla + " cmd=" + command + " p1=" + p1 + " p2="
@@ -5764,6 +6179,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "iccExchangeSimIO");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "iccExchangeSimIO");
+
final long identity = Binder.clearCallingIdentity();
try {
if (DBG) {
@@ -5809,6 +6227,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getForbiddenPlmns");
+
final long identity = Binder.clearCallingIdentity();
try {
if (appType != TelephonyManager.APPTYPE_USIM
@@ -5845,6 +6266,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setForbiddenPlmns");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "setForbiddenPlmns");
+
if (appType != TelephonyManager.APPTYPE_USIM && appType != TelephonyManager.APPTYPE_SIM) {
loge("setForbiddenPlmnList(): App Type must be USIM or SIM");
throw new IllegalArgumentException("Invalid appType: App Type must be USIM or SIM");
@@ -5874,6 +6298,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "sendEnvelopeWithStatus");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "sendEnvelopeWithStatus");
+
final long identity = Binder.clearCallingIdentity();
try {
IccIoResult response = (IccIoResult) sendRequest(CMD_SEND_ENVELOPE, content, subId);
@@ -5979,6 +6406,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, phone.getSubId(), "resetModemConfig");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "resetModemConfig");
+
final long identity = Binder.clearCallingIdentity();
try {
Boolean success = (Boolean) sendRequest(CMD_RESET_MODEM_CONFIG, null);
@@ -6005,6 +6435,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, phone.getSubId(), "rebootModem");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "rebootModem");
+
final long identity = Binder.clearCallingIdentity();
try {
Boolean success = (Boolean) sendRequest(CMD_MODEM_REBOOT, null);
@@ -6025,6 +6458,9 @@
public void resetIms(int slotIndex) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_IMS, "resetIms");
+
final long identity = Binder.clearCallingIdentity();
try {
if (mImsResolver == null) {
@@ -6304,6 +6740,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setNetworkSelectionModeAutomatic");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "setNetworkSelectionModeAutomatic");
+
final long identity = Binder.clearCallingIdentity();
try {
if (!isActiveSubscription(subId)) {
@@ -6334,6 +6773,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setNetworkSelectionModeManual");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "setNetworkSelectionModeManual");
+
final long identity = Binder.clearCallingIdentity();
if (!isActiveSubscription(subId)) {
return false;
@@ -6364,6 +6806,9 @@
.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getManualNetworkSelectionPlmn");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getManualNetworkSelectionPlmn");
+
final long identity = Binder.clearCallingIdentity();
try {
if (!isActiveSubscription(subId)) {
@@ -6426,6 +6871,10 @@
public void getCallForwarding(int subId, int callForwardingReason,
ICallForwardingInfoCallback callback) {
enforceReadPrivilegedPermission("getCallForwarding");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getCallForwarding");
+
long identity = Binder.clearCallingIdentity();
try {
if (DBG) {
@@ -6478,6 +6927,10 @@
public void setCallForwarding(int subId, CallForwardingInfo callForwardingInfo,
IIntegerConsumer callback) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setCallForwarding");
+
long identity = Binder.clearCallingIdentity();
try {
if (DBG) {
@@ -6511,6 +6964,10 @@
@Override
public void getCallWaitingStatus(int subId, IIntegerConsumer callback) {
enforceReadPrivilegedPermission("getCallWaitingStatus");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getCallWaitingStatus");
+
long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -6562,6 +7019,10 @@
@Override
public void setCallWaitingStatus(int subId, boolean enable, IIntegerConsumer callback) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setCallWaitingStatus");
+
long identity = Binder.clearCallingIdentity();
try {
if (DBG) log("setCallWaitingStatus: subId " + subId + " enable: " + enable);
@@ -6658,6 +7119,10 @@
}
}
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "requestNetworkScan");
+
int callingUid = Binder.getCallingUid();
int callingPid = Binder.getCallingPid();
final long identity = Binder.clearCallingIdentity();
@@ -6733,6 +7198,9 @@
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getAllowedNetworkTypesBitmask");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getAllowedNetworkTypesBitmask");
+
final long identity = Binder.clearCallingIdentity();
try {
if (DBG) log("getAllowedNetworkTypesBitmask");
@@ -6757,6 +7225,10 @@
@TelephonyManager.AllowedNetworkTypesReason int reason) {
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getAllowedNetworkTypesForReason");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getAllowedNetworkTypesForReason");
+
final long identity = Binder.clearCallingIdentity();
try {
return getPhoneFromSubIdOrDefault(subId).getAllowedNetworkTypes(reason);
@@ -6850,6 +7322,10 @@
"setAllowedNetworkTypesForReason cannot be called with carrier privileges for"
+ " reason " + reason);
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "setAllowedNetworkTypesForReason");
+
if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
loge("setAllowedNetworkTypesForReason: Invalid allowed network type reason: " + reason);
return false;
@@ -6895,6 +7371,10 @@
@Override
public boolean isTetheringApnRequiredForSubscriber(int subId) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isTetheringApnRequiredForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
final Phone phone = getPhone(subId);
try {
@@ -6997,6 +7477,9 @@
enforceReadPrivilegedPermission(functionName);
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isDataEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -7043,6 +7526,8 @@
}
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isDataEnabledForReason");
final long identity = Binder.clearCallingIdentity();
try {
@@ -7071,6 +7556,9 @@
@Override
public int getCarrierPrivilegeStatus(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getCarrierPrivilegeStatus");
+
// No permission needed; this only lets the caller inspect their own status.
return getCarrierPrivilegeStatusForUidWithPermission(subId, Binder.getCallingUid());
}
@@ -7078,6 +7566,10 @@
@Override
public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
enforceReadPrivilegedPermission("getCarrierPrivilegeStatusForUid");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getCarrierPrivilegeStatusForUid");
+
return getCarrierPrivilegeStatusForUidWithPermission(subId, uid);
}
@@ -7098,6 +7590,10 @@
@Override
public int checkCarrierPrivilegesForPackage(int subId, String pkgName) {
enforceReadPrivilegedPermission("checkCarrierPrivilegesForPackage");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "checkCarrierPrivilegesForPackage");
+
if (TextUtils.isEmpty(pkgName)) {
return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
}
@@ -7117,6 +7613,11 @@
@Override
public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
enforceReadPrivilegedPermission("checkCarrierPrivilegesForPackageAnyPhone");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "checkCarrierPrivilegesForPackageAnyPhone");
+
return checkCarrierPrivilegesForPackageAnyPhoneWithPermission(pkgName);
}
@@ -7145,6 +7646,11 @@
@Override
public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) {
enforceReadPrivilegedPermission("getCarrierPackageNamesForIntentAndPhone");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getCarrierPackageNamesForIntentAndPhone");
+
Phone phone = PhoneFactory.getPhone(phoneId);
if (phone == null) {
return Collections.emptyList();
@@ -7173,6 +7679,11 @@
@Override
public List<String> getPackagesWithCarrierPrivilegesForAllPhones() {
enforceReadPrivilegedPermission("getPackagesWithCarrierPrivilegesForAllPhones");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getPackagesWithCarrierPrivilegesForAllPhones");
+
Set<String> privilegedPackages = new ArraySet<>();
final long identity = Binder.clearCallingIdentity();
try {
@@ -7189,6 +7700,10 @@
public @Nullable String getCarrierServicePackageNameForLogicalSlot(int logicalSlotIndex) {
enforceReadPrivilegedPermission("getCarrierServicePackageNameForLogicalSlot");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "getCarrierServicePackageNameForLogicalSlot");
+
final Phone phone = PhoneFactory.getPhone(logicalSlotIndex);
if (phone == null) {
return null;
@@ -7217,6 +7732,9 @@
public void setCallComposerStatus(int subId, int status) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setCallComposerStatus");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -7240,6 +7758,9 @@
public int getCallComposerStatus(int subId) {
enforceReadPrivilegedPermission("getCallComposerStatus");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getCallComposerStatus");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -7262,6 +7783,10 @@
TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
subId, "setLine1NumberForDisplayForSubscriber");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "setLine1NumberForDisplayForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final String iccId = getIccId(subId);
@@ -7318,6 +7843,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getLine1NumberForDisplay");
+
final long identity = Binder.clearCallingIdentity();
try {
String iccId = getIccId(subId);
@@ -7445,6 +7973,9 @@
public String[] getMergedImsisFromGroup(int subId, String callingPackage) {
enforceReadPrivilegedPermission("getMergedImsisFromGroup");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getMergedImsisFromGroup");
+
final long identity = Binder.clearCallingIdentity();
try {
final TelephonyManager telephonyManager = mApp.getSystemService(
@@ -7490,6 +8021,9 @@
TelephonyPermissions.enforceCallingOrSelfCarrierPrivilege(mApp,
subId, "setOperatorBrandOverride");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "setOperatorBrandOverride");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -7536,6 +8070,9 @@
throw e;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getRadioAccessFamily");
+
final long identity = Binder.clearCallingIdentity();
try {
raf = ProxyController.getInstance().getRadioAccessFamily(phoneId);
@@ -7556,6 +8093,10 @@
} catch (PackageManager.NameNotFoundException e) {
throw new SecurityException("Invalid package:" + callingPackage);
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "uploadCallComposerPicture");
+
RoleManager rm = mApp.getSystemService(RoleManager.class);
List<String> dialerRoleHolders = rm.getRoleHolders(RoleManager.ROLE_DIALER);
if (!dialerRoleHolders.contains(callingPackage)) {
@@ -7642,6 +8183,9 @@
final Phone defaultPhone = getDefaultPhone();
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_IMS, "enableVideoCalling");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsManager.getInstance(defaultPhone.getContext(),
@@ -7659,6 +8203,9 @@
return false;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_IMS, "isVideoCallingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
// Check the user preference and the system-level IMS setting. Even if the user has
@@ -7684,6 +8231,9 @@
return false;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "canChangeDtmfToneLength");
+
final long identity = Binder.clearCallingIdentity();
try {
CarrierConfigManager configManager =
@@ -7702,6 +8252,9 @@
return false;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY, "isWorldPhone");
+
final long identity = Binder.clearCallingIdentity();
try {
CarrierConfigManager configManager =
@@ -7721,6 +8274,9 @@
@Override
public boolean isHearingAidCompatibilitySupported() {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "isHearingAidCompatibilitySupported");
+
final long identity = Binder.clearCallingIdentity();
try {
return mApp.getResources().getBoolean(R.bool.hac_enabled);
@@ -7737,6 +8293,9 @@
*/
@Override
public boolean isRttSupported(int subscriptionId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_IMS, "isRttSupported");
+
final long identity = Binder.clearCallingIdentity();
final Phone phone = getPhone(subscriptionId);
if (phone == null) {
@@ -7746,8 +8305,9 @@
try {
boolean isCarrierSupported = mApp.getCarrierConfigForSubId(subscriptionId).getBoolean(
CarrierConfigManager.KEY_RTT_SUPPORTED_BOOL);
- boolean isDeviceSupported =
- phone.getContext().getResources().getBoolean(R.bool.config_support_rtt);
+ boolean isDeviceSupported = (phone.getContext().getResources() != null)
+ ? phone.getContext().getResources().getBoolean(R.bool.config_support_rtt)
+ : false;
return isCarrierSupported && isDeviceSupported;
} finally {
Binder.restoreCallingIdentity(identity);
@@ -7762,6 +8322,12 @@
public boolean isRttEnabled(int subscriptionId) {
final long identity = Binder.clearCallingIdentity();
try {
+ if (mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()) {
+ if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
+ return false;
+ }
+ }
+
boolean isRttSupported = isRttSupported(subscriptionId);
boolean isUserRttSettingOn = Settings.Secure.getInt(
mApp.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 0) != 0;
@@ -7851,6 +8417,10 @@
subscriptionId,
"getPhoneAccountHandleForSubscriptionId, " + "subscriptionId: "
+ subscriptionId);
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getPhoneAccountHandleForSubscriptionId");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subscriptionId);
@@ -7918,6 +8488,10 @@
@Override
public void factoryReset(int subId, String callingPackage) {
enforceSettingsPermission();
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY, "factoryReset");
+
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
return;
}
@@ -7936,7 +8510,8 @@
setNetworkSelectionModeAutomatic(subId);
Phone phone = getPhone(subId);
cleanUpAllowedNetworkTypes(phone, subId);
- setDataRoamingEnabled(subId, getDefaultDataRoamingEnabled(subId));
+ setDataRoamingEnabled(subId, phone == null ? false
+ : phone.getDataSettingsManager().isDefaultDataRoamingEnabled());
getPhone(subId).resetCarrierKeysForImsiEncryption();
}
// There has been issues when Sms raw table somehow stores orphan
@@ -7990,6 +8565,10 @@
@Override
public String getSimLocaleForSubscriber(int subId) {
enforceReadPrivilegedPermission("getSimLocaleForSubscriber, subId: " + subId);
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSimLocaleForSubscriber");
+
final Phone phone = getPhone(subId);
if (phone == null) {
log("getSimLocaleForSubscriber, invalid subId");
@@ -8072,6 +8651,10 @@
@Override
public void requestModemActivityInfo(ResultReceiver result) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY, "requestModemActivityInfo");
+
WorkSource workSource = getWorkSource(Binder.getCallingUid());
final long identity = Binder.clearCallingIdentity();
@@ -8216,6 +8799,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getServiceStateForSubscriber");
+
boolean hasFinePermission = false;
boolean hasCoarsePermission = false;
if (!renounceFineLocationAccess) {
@@ -8295,6 +8881,9 @@
*/
@Override
public Uri getVoicemailRingtoneUri(PhoneAccountHandle accountHandle) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getVoicemailRingtoneUri");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
@@ -8331,6 +8920,9 @@
"setVoicemailRingtoneUri");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setVoicemailRingtoneUri");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
@@ -8352,6 +8944,9 @@
*/
@Override
public boolean isVoicemailVibrationEnabled(PhoneAccountHandle accountHandle) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "isVoicemailVibrationEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(accountHandle);
@@ -8388,6 +8983,9 @@
"setVoicemailVibrationEnabled");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setVoicemailVibrationEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
@@ -8464,6 +9062,10 @@
@Override
public String getAidForAppType(int subId, int appType) {
enforceReadPrivilegedPermission("getAidForAppType");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getAidForAppType");
+
Phone phone = getPhone(subId);
final long identity = Binder.clearCallingIdentity();
@@ -8521,6 +9123,10 @@
@Override
public String getCdmaPrlVersion(int subId) {
enforceReadPrivilegedPermission("getCdmaPrlVersion");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CDMA, "getCdmaPrlVersion");
+
Phone phone = getPhone(subId);
final long identity = Binder.clearCallingIdentity();
@@ -8570,6 +9176,10 @@
@TelephonyManager.SetCarrierRestrictionResult
public int setAllowedCarriers(CarrierRestrictionRules carrierRestrictionRules) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CARRIERLOCK, "setAllowedCarriers");
+
WorkSource workSource = getWorkSource(Binder.getCallingUid());
if (carrierRestrictionRules == null) {
@@ -8596,6 +9206,10 @@
@Override
public CarrierRestrictionRules getAllowedCarriers() {
enforceReadPrivilegedPermission("getAllowedCarriers");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CARRIERLOCK, "getAllowedCarriers");
+
WorkSource workSource = getWorkSource(Binder.getCallingUid());
final long identity = Binder.clearCallingIdentity();
@@ -8626,15 +9240,19 @@
@Override
public void getCarrierRestrictionStatus(IIntegerConsumer callback, String packageName) {
enforceReadPermission("getCarrierRestrictionStatus");
- int carrierId = validateCallerAndGetCarrierId(packageName);
- if (carrierId == CarrierAllowListInfo.INVALID_CARRIER_ID) {
+
+ enforceTelephonyFeatureWithException(packageName,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getCarrierRestrictionStatus");
+
+ Set<Integer> carrierIds = validateCallerAndGetCarrierIds(packageName);
+ if (carrierIds.contains(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);
+ CallerCallbackInfo callbackInfo = new CallerCallbackInfo(consumer, carrierIds);
sendRequestAsync(CMD_GET_ALLOWED_CARRIERS, callbackInfo);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -8649,9 +9267,9 @@
}
@VisibleForTesting
- public int validateCallerAndGetCarrierId(String packageName) {
+ public Set<Integer> validateCallerAndGetCarrierIds(String packageName) {
CarrierAllowListInfo allowListInfo = CarrierAllowListInfo.loadInstance(mApp);
- return allowListInfo.validateCallerAndGetCarrierId(packageName);
+ return allowListInfo.validateCallerAndGetCarrierIds(packageName);
}
/**
@@ -8748,6 +9366,11 @@
@Override
public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS,
+ "carrierActionReportDefaultNetworkStatus");
+
final Phone phone = getPhone(subId);
final long identity = Binder.clearCallingIdentity();
@@ -8772,6 +9395,10 @@
@Override
public void carrierActionResetAll(int subId) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "carrierActionResetAll");
+
final Phone phone = getPhone(subId);
if (phone == null) {
loge("carrierAction: ResetAll fails with invalid sibId: " + subId);
@@ -8834,14 +9461,17 @@
enforceModifyPermission();
}
- if (reason == TelephonyManager.DATA_ENABLED_REASON_USER && enabled
- && null != callingPackage && opEnableMobileDataByUser()) {
- mAppOps.noteOp(AppOpsManager.OPSTR_ENABLE_MOBILE_DATA_BY_USER, Binder.getCallingUid(),
- callingPackage, null, null);
- }
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_DATA, "setDataEnabledForReason");
+ int callingUid = Binder.getCallingUid();
final long identity = Binder.clearCallingIdentity();
try {
+ if (reason == TelephonyManager.DATA_ENABLED_REASON_USER && enabled
+ && null != callingPackage && opEnableMobileDataByUser()) {
+ mAppOps.noteOpNoThrow(AppOpsManager.OPSTR_ENABLE_MOBILE_DATA_BY_USER,
+ callingUid, callingPackage, null, null);
+ }
Phone phone = getPhone(subId);
if (phone != null) {
if (reason == TelephonyManager.DATA_ENABLED_REASON_CARRIER) {
@@ -8910,6 +9540,10 @@
@Override
public void setSimPowerStateForSlot(int slotIndex, int state) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "setSimPowerStateForSlot");
+
Phone phone = PhoneFactory.getPhone(slotIndex);
WorkSource workSource = getWorkSource(Binder.getCallingUid());
@@ -8939,6 +9573,11 @@
public void setSimPowerStateForSlotWithCallback(int slotIndex, int state,
IIntegerConsumer callback) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "setSimPowerStateForSlotWithCallback");
+
Phone phone = PhoneFactory.getPhone(slotIndex);
WorkSource workSource = getWorkSource(Binder.getCallingUid());
@@ -8976,6 +9615,10 @@
@Override
public boolean getEmergencyCallbackMode(int subId) {
enforceReadPrivilegedPermission("getEmergencyCallbackMode");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getEmergencyCallbackMode");
+
final long identity = Binder.clearCallingIdentity();
try {
return getPhoneFromSubIdOrDefault(subId).isInEcm();
@@ -8993,6 +9636,9 @@
*/
@Override
public SignalStrength getSignalStrength(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getSignalStrength");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone p = getPhone(subId);
@@ -9022,6 +9668,9 @@
return TelephonyManager.RADIO_POWER_UNAVAILABLE;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getRadioPowerState");
+
final long identity = Binder.clearCallingIdentity();
try {
return phone.getRadioPowerState();
@@ -9062,6 +9711,9 @@
mApp, subId, functionName);
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isDataRoamingEnabled");
+
boolean isEnabled = false;
final long identity = Binder.clearCallingIdentity();
try {
@@ -9089,6 +9741,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setDataRoamingEnabled");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "setDataRoamingEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -9106,6 +9761,9 @@
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isManualNetworkSelectionAllowed");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "isManualNetworkSelectionAllowed");
+
boolean isAllowed = true;
final long identity = Binder.clearCallingIdentity();
try {
@@ -9152,6 +9810,10 @@
throw new SecurityException("Caller does not have permission.");
}
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getUiccCardsInfo");
+
// checking compatibility, if calling app's target SDK is T and beyond.
if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
Binder.getCallingUid())) {
@@ -9262,6 +9924,9 @@
// we are reading iccId which is PII data.
enforceReadPrivilegedPermission("getUiccSlotsInfo");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getUiccSlotsInfo");
+
// checking compatibility, if calling app's target SDK is T and beyond.
if (CompatChanges.isChangeEnabled(GET_API_SIGNATURES_FROM_UICC_PORT_INFO,
Binder.getCallingUid())) {
@@ -9364,6 +10029,9 @@
public boolean switchSlots(int[] physicalSlots) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "switchSlots");
+
final long identity = Binder.clearCallingIdentity();
try {
List<UiccSlotMapping> slotMappings = new ArrayList<>();
@@ -9383,6 +10051,9 @@
public boolean setSimSlotMapping(@NonNull List<UiccSlotMapping> slotMapping) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "setSimSlotMapping");
+
final long identity = Binder.clearCallingIdentity();
try {
return (Boolean) sendRequest(CMD_SWITCH_SLOTS, slotMapping);
@@ -9393,6 +10064,9 @@
@Override
public int getCardIdForDefaultEuicc(int subId, String callingPackage) {
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_EUICC, "getCardIdForDefaultEuicc");
+
final long identity = Binder.clearCallingIdentity();
try {
return UiccController.getInstance().getCardIdForDefaultEuicc();
@@ -9440,20 +10114,6 @@
}
/**
- * Returns true if the data roaming is enabled by default, i.e the system property
- * of {@link #DEFAULT_DATA_ROAMING_PROPERTY_NAME} is true or the config of
- * {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL} is true.
- */
- private boolean getDefaultDataRoamingEnabled(int subId) {
- final CarrierConfigManager configMgr = (CarrierConfigManager)
- mApp.getSystemService(Context.CARRIER_CONFIG_SERVICE);
- boolean isDataRoamingEnabled = TelephonyProperties.data_roaming().orElse(false);
- isDataRoamingEnabled |= configMgr.getConfigForSubId(subId).getBoolean(
- CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
- return isDataRoamingEnabled;
- }
-
- /**
* Returns the default network type for the given {@code subId}, if the default network type is
* not set, return {@link Phone#PREFERRED_NT_MODE}.
*/
@@ -9559,6 +10219,9 @@
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getCdmaRoamingMode");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CDMA, "getCdmaRoamingMode");
+
final long identity = Binder.clearCallingIdentity();
try {
return (int) sendRequest(CMD_GET_CDMA_ROAMING_MODE, null /* argument */, subId);
@@ -9572,6 +10235,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setCdmaRoamingMode");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CDMA, "setCdmaRoamingMode");
+
final long identity = Binder.clearCallingIdentity();
try {
return (boolean) sendRequest(CMD_SET_CDMA_ROAMING_MODE, mode, subId);
@@ -9586,6 +10252,9 @@
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getCdmaSubscriptionMode");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CDMA, "getCdmaSubscriptionMode");
+
final long identity = Binder.clearCallingIdentity();
try {
return (int) sendRequest(CMD_GET_CDMA_SUBSCRIPTION_MODE, null /* argument */, subId);
@@ -9599,6 +10268,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setCdmaSubscriptionMode");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CDMA, "setCdmaSubscriptionMode");
+
final long identity = Binder.clearCallingIdentity();
try {
return (boolean) sendRequest(CMD_SET_CDMA_SUBSCRIPTION_MODE, mode, subId);
@@ -9615,6 +10287,10 @@
"getEmergencyNumberList")) {
throw new SecurityException("Requires READ_PHONE_STATE permission.");
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getEmergencyNumberList");
+
final long identity = Binder.clearCallingIdentity();
try {
Map<Integer, List<EmergencyNumber>> emergencyNumberListInternal = new HashMap<>();
@@ -9640,6 +10316,10 @@
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, defaultPhone.getSubId(), "isEmergencyNumber(Potential)");
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "isEmergencyNumber");
+
final long identity = Binder.clearCallingIdentity();
try {
for (Phone phone: PhoneFactory.getPhones()) {
@@ -9732,6 +10412,9 @@
public int getEmergencyNumberDbVersion(int subId) {
enforceReadPrivilegedPermission("getEmergencyNumberDbVersion");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getEmergencyNumberDbVersion");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -9749,6 +10432,9 @@
public void notifyOtaEmergencyNumberDbInstalled() {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "notifyOtaEmergencyNumberDbInstalled");
+
final long identity = Binder.clearCallingIdentity();
try {
for (Phone phone: PhoneFactory.getPhones()) {
@@ -9766,6 +10452,9 @@
public void updateOtaEmergencyNumberDbFilePath(ParcelFileDescriptor otaParcelFileDescriptor) {
enforceActiveEmergencySessionPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "updateOtaEmergencyNumberDbFilePath");
+
final long identity = Binder.clearCallingIdentity();
try {
for (Phone phone: PhoneFactory.getPhones()) {
@@ -9783,6 +10472,9 @@
public void resetOtaEmergencyNumberDbFilePath() {
enforceActiveEmergencySessionPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "resetOtaEmergencyNumberDbFilePath");
+
final long identity = Binder.clearCallingIdentity();
try {
for (Phone phone: PhoneFactory.getPhones()) {
@@ -9823,6 +10515,9 @@
public boolean enableModemForSlot(int slotIndex, boolean enable) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY, "enableModemForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = PhoneFactory.getPhone(slotIndex);
@@ -9851,6 +10546,9 @@
throw new SecurityException("Requires READ_PHONE_STATE permission.");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY, "isModemEnabledForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
try {
@@ -9867,6 +10565,9 @@
public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CARRIERLOCK, "setMultiSimCarrierRestriction");
+
final long identity = Binder.clearCallingIdentity();
try {
mTelephonySharedPreferences.edit()
@@ -9886,6 +10587,9 @@
return TelephonyManager.MULTISIM_NOT_SUPPORTED_BY_HARDWARE;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "isMultiSimSupported");
+
final long identity = Binder.clearCallingIdentity();
try {
return isMultiSimSupportedInternal();
@@ -9937,6 +10641,10 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, "switchMultiSimConfig");
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "switchMultiSimConfig");
+
final long identity = Binder.clearCallingIdentity();
try {
@@ -9954,6 +10662,10 @@
@Override
public boolean isApplicationOnUicc(int subId, int appType) {
enforceReadPrivilegedPermission("isApplicationOnUicc");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "isApplicationOnUicc");
+
Phone phone = getPhone(subId);
if (phone == null) {
return false;
@@ -9990,6 +10702,11 @@
"doesSwitchMultiSimConfigTriggerReboot")) {
return false;
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "doesSwitchMultiSimConfigTriggerReboot");
+
final long identity = Binder.clearCallingIdentity();
try {
return mPhoneConfigurationManager.isRebootRequiredForModemConfigChange();
@@ -10010,6 +10727,10 @@
// Verify that the callingPackage belongs to the calling UID
mApp.getSystemService(AppOpsManager.class)
.checkPackage(Binder.getCallingUid(), callingPackage);
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSlotsMapping");
+
final long identity = Binder.clearCallingIdentity();
List<UiccSlotMapping> slotMap = new ArrayList<>();
try {
@@ -10054,11 +10775,14 @@
/**
* Get the current calling package name.
- * @return the current calling package name
+ *
+ * @return the current calling package name, or null if there is no known package.
*/
@Override
- public String getCurrentPackageName() {
- return mApp.getPackageManager().getPackagesForUid(Binder.getCallingUid())[0];
+ public @Nullable String getCurrentPackageName() {
+ PackageManager pm = mApp.getPackageManager();
+ String[] packageNames = pm == null ? null : pm.getPackagesForUid(Binder.getCallingUid());
+ return packageNames == null ? null : packageNames[0];
}
/**
@@ -10080,6 +10804,9 @@
enforceReadPrivilegedPermission("Needs READ_PRIVILEGED_PHONE_STATE for "
+ "isDataEnabledForApn");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_DATA, "isDataEnabledForApn");
+
// Now that all security checks passes, perform the operation as ourselves.
final long identity = Binder.clearCallingIdentity();
try {
@@ -10102,6 +10829,9 @@
public boolean isApnMetered(@ApnType int apnType, int subId) {
enforceReadPrivilegedPermission("isApnMetered");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isApnMetered");
+
// Now that all security checks passes, perform the operation as ourselves.
final long identity = Binder.clearCallingIdentity();
try {
@@ -10119,6 +10849,10 @@
public void setSystemSelectionChannels(List<RadioAccessSpecifier> specifiers,
int subscriptionId, IBooleanConsumer resultCallback) {
enforceModifyPermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "setSystemSelectionChannels");
+
long token = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subscriptionId);
@@ -10153,6 +10887,10 @@
TelephonyPermissions
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getSystemSelectionChannels");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getSystemSelectionChannels");
+
WorkSource workSource = getWorkSource(Binder.getCallingUid());
final long identity = Binder.clearCallingIdentity();
try {
@@ -10171,6 +10909,10 @@
@Override
public boolean isMvnoMatched(int slotIndex, int mvnoType, @NonNull String mvnoMatchData) {
enforceReadPrivilegedPermission("isMvnoMatched");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "isMvnoMatched");
+
return UiccController.getInstance().mvnoMatches(slotIndex, mvnoType, mvnoMatchData);
}
@@ -10218,6 +10960,9 @@
@Override
public String getMmsUAProfUrl(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_MESSAGING, "getMmsUAProfUrl");
+
//TODO investigate if this API should require proper permission check in R b/133791609
final long identity = Binder.clearCallingIdentity();
try {
@@ -10235,6 +10980,9 @@
@Override
public String getMmsUserAgent(int subId) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_MESSAGING, "getMmsUserAgent");
+
//TODO investigate if this API should require proper permission check in R b/133791609
final long identity = Binder.clearCallingIdentity();
try {
@@ -10254,6 +11002,9 @@
public boolean isMobileDataPolicyEnabled(int subscriptionId, int policy) {
enforceReadPrivilegedPermission("isMobileDataPolicyEnabled");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isMobileDataPolicyEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subscriptionId);
@@ -10270,6 +11021,9 @@
boolean enabled) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "setMobileDataPolicyEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subscriptionId);
@@ -10324,10 +11078,19 @@
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
- if (!isImsAvailableOnDevice()) {
- // ProvisioningManager can not handle ServiceSpecificException.
- // Throw the IllegalStateException and annotate ProvisioningManager.
- throw new IllegalStateException("IMS not available on device.");
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, getCurrentPackageName(),
+ Binder.getCallingUserHandle())) {
+ if (!isImsAvailableOnDevice()) {
+ // ProvisioningManager can not handle ServiceSpecificException.
+ // Throw the IllegalStateException and annotate ProvisioningManager.
+ throw new IllegalStateException("IMS not available on device.");
+ }
+ } else {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION,
+ "notifyRcsAutoConfigurationReceived");
}
final long identity = Binder.clearCallingIdentity();
@@ -10342,6 +11105,9 @@
public boolean isIccLockEnabled(int subId) {
enforceReadPrivilegedPermission("isIccLockEnabled");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "isIccLockEnabled");
+
// Now that all security checks passes, perform the operation as ourselves.
final long identity = Binder.clearCallingIdentity();
try {
@@ -10371,6 +11137,9 @@
public int setIccLockEnabled(int subId, boolean enabled, String password) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "setIccLockEnabled");
+
Phone phone = getPhone(subId);
if (phone == null) {
return 0;
@@ -10403,6 +11172,9 @@
public int changeIccLockPassword(int subId, String oldPassword, String newPassword) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "changeIccLockPassword");
+
Phone phone = getPhone(subId);
if (phone == null) {
return 0;
@@ -10473,6 +11245,9 @@
throw new SecurityException("Requires READ_PHONE_STATE permission.");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getEquivalentHomePlmns");
+
Phone phone = getPhone(subId);
if (phone == null) {
throw new RuntimeException("phone is not available");
@@ -10489,6 +11264,10 @@
@Override
public boolean isRadioInterfaceCapabilitySupported(
final @NonNull @TelephonyManager.RadioInterfaceCapability String capability) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS,
+ "isRadioInterfaceCapabilitySupported");
+
Set<String> radioInterfaceCapabilities =
mRadioInterfaceCapabilities.getCapabilities();
if (radioInterfaceCapabilities == null) {
@@ -10505,6 +11284,10 @@
Binder.getCallingUid(), "bootstrapAuthenticationRequest",
Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION,
Manifest.permission.MODIFY_PHONE_STATE);
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "bootstrapAuthenticationRequest");
+
if (DBG) {
log("bootstrapAuthenticationRequest, subId:" + subId + ", appType:"
+ appType + ", NAF:" + nafUrl + ", sp:" + securityProtocol
@@ -10664,6 +11447,10 @@
enforceModifyPermission();
mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "sendThermalMitigationRequest");
+
if (!getThermalMitigationAllowlist(getDefaultPhone().getContext())
.contains(callingPackage)) {
throw new SecurityException("Calling package must be configured in the device config. "
@@ -10894,9 +11681,16 @@
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
- if (!isImsAvailableOnDevice()) {
- throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
- "IMS not available on device.");
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, getCurrentPackageName(),
+ Binder.getCallingUserHandle())) {
+ if (!isImsAvailableOnDevice()) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "IMS not available on device.");
+ }
+ } else {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION, "registerRcsProvisioningCallback");
}
final long identity = Binder.clearCallingIdentity();
@@ -10925,10 +11719,19 @@
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
- if (!isImsAvailableOnDevice()) {
- // operation failed silently
- Rlog.w(LOG_TAG, "IMS not available on device.");
- return;
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, getCurrentPackageName(),
+ Binder.getCallingUserHandle())) {
+ if (!isImsAvailableOnDevice()) {
+ // operation failed silently
+ Rlog.w(LOG_TAG, "IMS not available on device.");
+ return;
+ }
+ } else {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION,
+ "unregisterRcsProvisioningCallback");
}
final long identity = Binder.clearCallingIdentity();
@@ -10951,10 +11754,17 @@
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
- if (!isImsAvailableOnDevice()) {
- // ProvisioningManager can not handle ServiceSpecificException.
- // Throw the IllegalStateException and annotate ProvisioningManager.
- throw new IllegalStateException("IMS not available on device.");
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, getCurrentPackageName(),
+ Binder.getCallingUserHandle())) {
+ if (!isImsAvailableOnDevice()) {
+ // ProvisioningManager can not handle ServiceSpecificException.
+ // Throw the IllegalStateException and annotate ProvisioningManager.
+ throw new IllegalStateException("IMS not available on device.");
+ }
+ } else {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION, "triggerRcsReconfiguration");
}
final long identity = Binder.clearCallingIdentity();
@@ -10976,9 +11786,16 @@
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
throw new IllegalArgumentException("Invalid Subscription ID: " + subId);
}
- if (!isImsAvailableOnDevice()) {
- throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
- "IMS not available on device.");
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, getCurrentPackageName(),
+ Binder.getCallingUserHandle())) {
+ if (!isImsAvailableOnDevice()) {
+ throw new ServiceSpecificException(ImsException.CODE_ERROR_UNSUPPORTED_OPERATION,
+ "IMS not available on device.");
+ }
+ } else {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION, "setRcsClientConfiguration");
}
final long identity = Binder.clearCallingIdentity();
@@ -11392,6 +12209,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setSignalStrengthUpdateRequest");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "setSignalStrengthUpdateRequest");
+
final int callingUid = Binder.getCallingUid();
// Verify that tha callingPackage belongs to the calling UID
mApp.getSystemService(AppOpsManager.class)
@@ -11418,6 +12238,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "clearSignalStrengthUpdateRequest");
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "clearSignalStrengthUpdateRequest");
+
final int callingUid = Binder.getCallingUid();
// Verify that tha callingPackage belongs to the calling UID
mApp.getSystemService(AppOpsManager.class)
@@ -11484,6 +12307,10 @@
@Override
public PhoneCapability getPhoneCapability() {
enforceReadPrivilegedPermission("getPhoneCapability");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY, "getPhoneCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
return mPhoneConfigurationManager.getCurrentPhoneCapability();
@@ -11502,6 +12329,9 @@
WorkSource workSource = getWorkSource(Binder.getCallingUid());
enforceRebootPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "prepareForUnattendedReboot");
+
final long identity = Binder.clearCallingIdentity();
try {
return (int) sendRequest(CMD_PREPARE_UNATTENDED_REBOOT, null, workSource);
@@ -11522,6 +12352,10 @@
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, SubscriptionManager.INVALID_SUBSCRIPTION_ID, "getSlicingConfig");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS,
+ "getSlicingConfig");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getDefaultPhone();
@@ -11550,6 +12384,9 @@
+ "permission READ_BASIC_PHONE_STATE.");
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isPremiumCapabilityAvailableForPurchase");
+
Phone phone = getPhone(subId);
if (phone == null) {
loge("isPremiumCapabilityAvailableForPurchase: phone is null, subId=" + subId);
@@ -11592,6 +12429,9 @@
throw new SecurityException("purchasePremiumCapability requires permission INTERNET.");
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "purchasePremiumCapability");
+
Phone phone = getPhone(subId);
if (phone == null) {
try {
@@ -11727,8 +12567,9 @@
* @return {@CellIdentity} last known cell identity {@CellIdentity}.
*
* Require {@link android.Manifest.permission#ACCESS_FINE_LOCATION} and
- * com.android.phone.permission.ACCESS_LAST_KNOWN_CELL_ID, otherwise throws
+ * {@link android.Manifest.permission#ACCESS_LAST_KNOWN_CELL_ID}, otherwise throws
* SecurityException.
+ *
* If there is current registered network this value will be same as the registered cell
* identity. If the device goes out of service the previous cell identity is cached and
* will be returned. If the cache age of the Cell identity is more than 24 hours
@@ -11804,6 +12645,27 @@
return result;
}
+ /**
+ * Get the aggregated satellite plmn list. This API collects plmn data from multiple sources,
+ * including carrier config, entitlement server, and config update.
+ *
+ * @param subId subId The subscription ID of the carrier.
+ *
+ * @return List of plmns for carrier satellite service. If no plmn is available, empty list will
+ * be returned.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @NonNull public List<String> getSatellitePlmnsForCarrier(int subId) {
+ enforceSatelliteCommunicationPermission("getSatellitePlmnsForCarrier");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mSatelliteController.getSatellitePlmnsForCarrier(subId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@Override
public void setVoiceServiceStateOverride(int subId, boolean hasService, String callingPackage) {
// Only telecom (and shell, for CTS purposes) is allowed to call this method.
@@ -11872,6 +12734,10 @@
boolean updateIfNeeded) {
enforceInteractAcrossUsersPermission("getDefaultRespondViaMessageApplication");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_MESSAGING,
+ "getDefaultRespondViaMessageApplication");
+
Context context = getPhoneFromSubIdOrDefault(subId).getContext();
UserHandle userHandle = null;
@@ -11952,6 +12818,17 @@
}
}
+ private void checkForNullCipherNotificationSupport() {
+ if (getHalVersion(HAL_SERVICE_NETWORK) < MIN_NULL_CIPHER_NOTIFICATION_VERSION) {
+ throw new UnsupportedOperationException(
+ "Null cipher notification operations require HAL 2.2 or above");
+ }
+ if (!getDefaultPhone().isNullCipherNotificationSupported()) {
+ throw new UnsupportedOperationException(
+ "Null cipher notification operations unsupported by modem");
+ }
+ }
+
/**
* Get the SIM state for the slot index.
* For Remote-SIMs, this method returns {@link IccCardConstants.State#UNKNOWN}
@@ -11961,6 +12838,9 @@
@Override
@SimState
public int getSimStateForSlotIndex(int slotIndex) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getSimStateForSlotIndex");
+
IccCardConstants.State simState;
if (slotIndex < 0) {
simState = IccCardConstants.State.UNKNOWN;
@@ -11990,22 +12870,26 @@
long logcatStartTimestampMillis, boolean enableTelecomDump,
boolean enableTelephonyDump) {
DropBoxManager db = mApp.getSystemService(DropBoxManager.class);
- TelephonyManager.EmergencyCallDiagnosticParams edp =
- new TelephonyManager.EmergencyCallDiagnosticParams();
- edp.setLogcatCollection(enableLogcat, logcatStartTimestampMillis);
- edp.setTelephonyDumpSysCollection(enableTelephonyDump);
- edp.setTelecomDumpSysCollection(enableTelecomDump);
- Log.d(LOG_TAG, "persisting with Params " + edp.toString());
+ TelephonyManager.EmergencyCallDiagnosticData.Builder ecdDataBuilder =
+ new TelephonyManager.EmergencyCallDiagnosticData.Builder();
+ ecdDataBuilder
+ .setTelecomDumpsysCollectionEnabled(enableTelecomDump)
+ .setTelephonyDumpsysCollectionEnabled(enableTelephonyDump);
+ if (enableLogcat) {
+ ecdDataBuilder.setLogcatCollectionStartTimeMillis(logcatStartTimestampMillis);
+ }
+ TelephonyManager.EmergencyCallDiagnosticData ecdData = ecdDataBuilder.build();
+ Log.d(LOG_TAG, "persisting with Params " + ecdData.toString());
DiagnosticDataCollector ddc = new DiagnosticDataCollector(Runtime.getRuntime(),
Executors.newCachedThreadPool(), db,
mApp.getSystemService(ActivityManager.class).isLowRamDevice());
- ddc.persistEmergencyDianosticData(new DataCollectorConfig.Adapter(), edp, dropboxTag);
+ ddc.persistEmergencyDianosticData(new DataCollectorConfig.Adapter(), ecdData, dropboxTag);
}
/**
* Request telephony to persist state for debugging emergency call failures.
*
- * @param dropBoxTag Tag to use when persisting data to dropbox service.
+ * @param dropboxTag Tag to use when persisting data to dropbox service.
* @param enableLogcat whether to collect logcat output
* @param logcatStartTimestampMillis timestamp from when logcat buffers would be persisted
* @param enableTelecomDump whether to collect telecom dumpsys
@@ -12016,8 +12900,16 @@
public void persistEmergencyCallDiagnosticData(@NonNull String dropboxTag, boolean enableLogcat,
long logcatStartTimestampMillis, boolean enableTelecomDump,
boolean enableTelephonyDump) {
- mApp.enforceCallingPermission(android.Manifest.permission.DUMP,
- "persistEmergencyCallDiagnosticData");
+ // Verify that the caller has READ_DROPBOX_DATA permission.
+ if (mTelecomFeatureFlags.telecomResolveHiddenDependencies()
+ && Flags.enableReadDropboxPermission()) {
+ mApp.enforceCallingPermission(permission.READ_DROPBOX_DATA,
+ "persistEmergencyCallDiagnosticData");
+ } else {
+ // Otherwise, enforce legacy permission.
+ mApp.enforceCallingPermission(android.Manifest.permission.DUMP,
+ "persistEmergencyCallDiagnosticData");
+ }
final long identity = Binder.clearCallingIdentity();
try {
persistEmergencyCallDiagnosticDataInternal(dropboxTag, enableLogcat,
@@ -12036,6 +12928,10 @@
public List<CellBroadcastIdRange> getCellBroadcastIdRanges(int subId) {
mApp.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
"getCellBroadcastIdRanges");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_MESSAGING, "getCellBroadcastIdRanges");
+
final long identity = Binder.clearCallingIdentity();
try {
return getPhone(subId).getCellBroadcastIdRanges();
@@ -12055,6 +12951,10 @@
@Nullable IIntegerConsumer callback) {
mApp.enforceCallingPermission(android.Manifest.permission.MODIFY_CELL_BROADCASTS,
"setCellBroadcastIdRanges");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_MESSAGING, "setCellBroadcastIdRanges");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhoneFromSubId(subId);
@@ -12102,16 +13002,50 @@
* @param enableSatellite {@code true} to enable the satellite modem and
* {@code false} to disable.
* @param enableDemoMode {@code true} to enable demo mode and {@code false} to disable.
+ * @param isEmergency {@code true} to enable emergency mode, {@code false} otherwise.
* @param callback The callback to get the result of the request.
*
* @throws SecurityException if the caller doesn't have the required permission.
*/
@Override
public void requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode,
- @NonNull IIntegerConsumer callback) {
+ boolean isEmergency, @NonNull IIntegerConsumer callback) {
enforceSatelliteCommunicationPermission("requestSatelliteEnabled");
- mSatelliteController.requestSatelliteEnabled(subId, enableSatellite, enableDemoMode,
- callback);
+ if (enableSatellite) {
+ ResultReceiver resultReceiver = new ResultReceiver(mMainThreadHandler) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ Log.d(LOG_TAG, "Satellite access restriction resultCode=" + resultCode
+ + ", resultData=" + resultData);
+ boolean isAllowed = false;
+ Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(
+ callback::accept);
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData != null
+ && resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
+ isAllowed = resultData.getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED);
+ } else {
+ loge("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist.");
+ }
+ } else {
+ result.accept(resultCode);
+ return;
+ }
+ if (isAllowed) {
+ mSatelliteController.requestSatelliteEnabled(
+ subId, enableSatellite, enableDemoMode, isEmergency, callback);
+ } else {
+ result.accept(SATELLITE_RESULT_ACCESS_BARRED);
+ }
+ }
+ };
+ mSatelliteAccessController.requestIsCommunicationAllowedForCurrentLocation(
+ subId, resultReceiver);
+ } else {
+ // No need to check if satellite is allowed at current location when disabling satellite
+ mSatelliteController.requestSatelliteEnabled(
+ subId, enableSatellite, enableDemoMode, isEmergency, callback);
+ }
}
/**
@@ -12146,6 +13080,22 @@
}
/**
+ * Request to get whether the satellite service is enabled with emergency mode.
+ *
+ * @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 emergency 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 requestIsEmergencyModeEnabled(int subId, @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission("requestIsEmergencyModeEnabled");
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ }
+
+ /**
* 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.
@@ -12315,7 +13265,7 @@
*/
@Override
@SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
- @NonNull ISatelliteStateCallback callback) {
+ @NonNull ISatelliteModemStateCallback callback) {
enforceSatelliteCommunicationPermission("registerForSatelliteModemStateChanged");
return mSatelliteController.registerForSatelliteModemStateChanged(subId, callback);
}
@@ -12326,15 +13276,15 @@
*
* @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)}.
+ * {@link #registerForModemStateChanged(int, ISatelliteModemStateCallback)}.
*
* @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);
+ public void unregisterForModemStateChanged(int subId,
+ @NonNull ISatelliteModemStateCallback callback) {
+ enforceSatelliteCommunicationPermission("unregisterForModemStateChanged");
+ mSatelliteController.unregisterForModemStateChanged(subId, callback);
}
/**
@@ -12348,10 +13298,10 @@
* @throws SecurityException if the caller doesn't have the required permission.
*/
@Override
- @SatelliteManager.SatelliteResult public int registerForSatelliteDatagram(int subId,
+ @SatelliteManager.SatelliteResult public int registerForIncomingDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
- enforceSatelliteCommunicationPermission("registerForSatelliteDatagram");
- return mSatelliteController.registerForSatelliteDatagram(subId, callback);
+ enforceSatelliteCommunicationPermission("registerForIncomingDatagram");
+ return mSatelliteController.registerForIncomingDatagram(subId, callback);
}
/**
@@ -12360,15 +13310,15 @@
*
* @param subId The subId of the subscription to unregister for incoming satellite datagrams.
* @param callback The callback that was passed to
- * {@link #registerForSatelliteDatagram(int, ISatelliteDatagramCallback)}.
+ * {@link #registerForIncomingDatagram(int, ISatelliteDatagramCallback)}.
*
* @throws SecurityException if the caller doesn't have the required permission.
*/
@Override
- public void unregisterForSatelliteDatagram(int subId,
+ public void unregisterForIncomingDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
- enforceSatelliteCommunicationPermission("unregisterForSatelliteDatagram");
- mSatelliteController.unregisterForSatelliteDatagram(subId, callback);
+ enforceSatelliteCommunicationPermission("unregisterForIncomingDatagram");
+ mSatelliteController.unregisterForIncomingDatagram(subId, callback);
}
/**
@@ -12383,10 +13333,9 @@
*
* @throws SecurityException if the caller doesn't have required permission.
*/
- @Override
- public void pollPendingSatelliteDatagrams(int subId, IIntegerConsumer callback) {
- enforceSatelliteCommunicationPermission("pollPendingSatelliteDatagrams");
- mSatelliteController.pollPendingSatelliteDatagrams(subId, callback);
+ public void pollPendingDatagrams(int subId, IIntegerConsumer callback) {
+ enforceSatelliteCommunicationPermission("pollPendingDatagrams");
+ mSatelliteController.pollPendingDatagrams(subId, callback);
}
/**
@@ -12408,12 +13357,12 @@
* @throws SecurityException if the caller doesn't have required permission.
*/
@Override
- public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
+ public void sendDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
@NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
@NonNull IIntegerConsumer callback) {
- enforceSatelliteCommunicationPermission("sendSatelliteDatagram");
- mSatelliteController.sendSatelliteDatagram(subId, datagramType, datagram,
- needFullScreenPointingUI, callback);
+ enforceSatelliteCommunicationPermission("sendDatagram");
+ mSatelliteController.sendDatagram(subId, datagramType, datagram, needFullScreenPointingUI,
+ callback);
}
/**
@@ -12428,11 +13377,10 @@
* @throws SecurityException if the caller doesn't have the required permission.
*/
@Override
- public void requestIsSatelliteCommunicationAllowedForCurrentLocation(int subId,
+ public void requestIsCommunicationAllowedForCurrentLocation(int subId,
@NonNull ResultReceiver result) {
- enforceSatelliteCommunicationPermission(
- "requestIsSatelliteCommunicationAllowedForCurrentLocation");
- mSatelliteController.requestIsSatelliteCommunicationAllowedForCurrentLocation(subId,
+ enforceSatelliteCommunicationPermission("requestIsCommunicationAllowedForCurrentLocation");
+ mSatelliteAccessController.requestIsCommunicationAllowedForCurrentLocation(subId,
result);
}
@@ -12473,18 +13421,18 @@
*
* @param subId The subId of the subscription to request for.
* @param reason Reason for disallowing satellite communication for carrier.
- * @param callback Listener for the {@link SatelliteManager.SatelliteError} result of the
+ * @param callback Listener for the {@link SatelliteManager.SatelliteResult} result of the
* operation.
*
* @throws SecurityException if the caller doesn't have required permission.
*/
- public void addSatelliteAttachRestrictionForCarrier(int subId,
+ public void addAttachRestrictionForCarrier(int subId,
@SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
@NonNull IIntegerConsumer callback) {
- enforceSatelliteCommunicationPermission("addSatelliteAttachRestrictionForCarrier");
+ enforceSatelliteCommunicationPermission("addAttachRestrictionForCarrier");
final long identity = Binder.clearCallingIdentity();
try {
- mSatelliteController.addSatelliteAttachRestrictionForCarrier(subId, reason, callback);
+ mSatelliteController.addAttachRestrictionForCarrier(subId, reason, callback);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -12496,19 +13444,18 @@
*
* @param subId The subId of the subscription to request for.
* @param reason Reason for disallowing satellite communication.
- * @param callback Listener for the {@link SatelliteManager.SatelliteError} result of the
+ * @param callback Listener for the {@link SatelliteManager.SatelliteResult} result of the
* operation.
*
* @throws SecurityException if the caller doesn't have required permission.
*/
- public void removeSatelliteAttachRestrictionForCarrier(int subId,
+ public void removeAttachRestrictionForCarrier(int subId,
@SatelliteManager.SatelliteCommunicationRestrictionReason int reason,
@NonNull IIntegerConsumer callback) {
- enforceSatelliteCommunicationPermission("removeSatelliteAttachRestrictionForCarrier");
+ enforceSatelliteCommunicationPermission("removeAttachRestrictionForCarrier");
final long identity = Binder.clearCallingIdentity();
try {
- mSatelliteController.removeSatelliteAttachRestrictionForCarrier(subId, reason,
- callback);
+ mSatelliteController.removeAttachRestrictionForCarrier(subId, reason, callback);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -12516,7 +13463,7 @@
/**
* Get reasons for disallowing satellite communication, as requested by
- * {@link #addSatelliteAttachRestrictionForCarrier(int, int, IIntegerConsumer)}.
+ * {@link #addAttachRestrictionForCarrier(int, int, IIntegerConsumer)}.
*
* @param subId The subId of the subscription to request for.
*
@@ -12524,13 +13471,13 @@
*
* @throws SecurityException if the caller doesn't have the required permission.
*/
- public @NonNull int[] getSatelliteAttachRestrictionReasonsForCarrier(
+ public @NonNull int[] getAttachRestrictionReasonsForCarrier(
int subId) {
- enforceSatelliteCommunicationPermission("getSatelliteAttachRestrictionReasonsForCarrier");
+ enforceSatelliteCommunicationPermission("getAttachRestrictionReasonsForCarrier");
final long identity = Binder.clearCallingIdentity();
try {
Set<Integer> reasonSet =
- mSatelliteController.getSatelliteAttachRestrictionReasonsForCarrier(subId);
+ mSatelliteController.getAttachRestrictionReasonsForCarrier(subId);
return reasonSet.stream().mapToInt(i->i).toArray();
} finally {
Binder.restoreCallingIdentity(identity);
@@ -12618,12 +13565,12 @@
* @throws SecurityException if the caller doesn't have required permission.
*/
@Override
- @SatelliteManager.SatelliteResult public int registerForSatelliteCapabilitiesChanged(
+ @SatelliteManager.SatelliteResult public int registerForCapabilitiesChanged(
int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
- enforceSatelliteCommunicationPermission("registerForSatelliteCapabilitiesChanged");
+ enforceSatelliteCommunicationPermission("registerForCapabilitiesChanged");
final long identity = Binder.clearCallingIdentity();
try {
- return mSatelliteController.registerForSatelliteCapabilitiesChanged(subId, callback);
+ return mSatelliteController.registerForCapabilitiesChanged(subId, callback);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -12635,23 +13582,57 @@
*
* @param subId The subId of the subscription to unregister for satellite capabilities change.
* @param callback The callback that was passed to.
- * {@link #registerForSatelliteCapabilitiesChanged(int, ISatelliteCapabilitiesCallback)}.
+ * {@link #registerForCapabilitiesChanged(int, ISatelliteCapabilitiesCallback)}.
*
* @throws SecurityException if the caller doesn't have required permission.
*/
@Override
- public void unregisterForSatelliteCapabilitiesChanged(
- int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
- enforceSatelliteCommunicationPermission("unregisterForSatelliteCapabilitiesChanged");
+ public void unregisterForCapabilitiesChanged(int subId,
+ @NonNull ISatelliteCapabilitiesCallback callback) {
+ enforceSatelliteCommunicationPermission("unregisterForCapabilitiesChanged");
final long identity = Binder.clearCallingIdentity();
try {
- mSatelliteController.unregisterForSatelliteCapabilitiesChanged(subId, callback);
+ mSatelliteController.unregisterForCapabilitiesChanged(subId, callback);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
/**
+ * Registers for the satellite supported state changed.
+ *
+ * @param subId The subId of the subscription to register for supported state changed.
+ * @param callback The callback to handle the satellite supported state changed event.
+ *
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ @SatelliteManager.SatelliteResult public int registerForSatelliteSupportedStateChanged(
+ int subId, @NonNull ISatelliteSupportedStateCallback callback) {
+ enforceSatelliteCommunicationPermission("registerForSatelliteSupportedStateChanged");
+ return mSatelliteController.registerForSatelliteSupportedStateChanged(subId, callback);
+ }
+
+ /**
+ * Unregisters for the satellite supported state changed.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for supported state changed.
+ * @param callback The callback that was passed to
+ * {@link #registerForSatelliteSupportedStateChanged(int, ISatelliteSupportedStateCallback)}.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void unregisterForSatelliteSupportedStateChanged(
+ int subId, @NonNull ISatelliteSupportedStateCallback callback) {
+ enforceSatelliteCommunicationPermission("unregisterForSatelliteSupportedStateChanged");
+ mSatelliteController.unregisterForSatelliteSupportedStateChanged(subId, callback);
+ }
+
+ /**
* This API can be used by only CTS to update satellite vendor service package name.
*
* @param servicePackageName The package name of the satellite vendor service.
@@ -12724,20 +13705,43 @@
}
/**
- * This API can be used by only CTS to update the timeout duration in milliseconds whether
- * the device is aligned with the satellite for demo mode
+ * This API can be used by only CTS to override the timeout durations used by the
+ * DatagramController module.
*
* @param timeoutMillis The timeout duration in millisecond.
* @return {@code true} if the timeout duration is set successfully, {@code false} otherwise.
*/
- public boolean setSatelliteDeviceAlignedTimeoutDuration(long timeoutMillis) {
- Log.d(LOG_TAG, "setDeviceAlignedTimeoutDuration - " + timeoutMillis);
+ public boolean setDatagramControllerTimeoutDuration(
+ boolean reset, int timeoutType, long timeoutMillis) {
+ Log.d(LOG_TAG, "setDatagramControllerTimeoutDuration - " + timeoutMillis + ", reset="
+ + reset + ", timeoutMillis=" + timeoutMillis);
TelephonyPermissions.enforceShellOnly(
- Binder.getCallingUid(), "setDeviceAlignedTimeoutDuration");
+ Binder.getCallingUid(), "setDatagramControllerTimeoutDuration");
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
SubscriptionManager.INVALID_SUBSCRIPTION_ID,
- "setDeviceAlignedTimeoutDuration");
- return mSatelliteController.setSatelliteDeviceAlignedTimeoutDuration(timeoutMillis);
+ "setDatagramControllerTimeoutDuration");
+ return mSatelliteController.setDatagramControllerTimeoutDuration(
+ reset, timeoutType, timeoutMillis);
+ }
+
+ /**
+ * This API can be used by only CTS to override the timeout durations used by the
+ * SatelliteController module.
+ *
+ * @param timeoutMillis The timeout duration in millisecond.
+ * @return {@code true} if the timeout duration is set successfully, {@code false} otherwise.
+ */
+ public boolean setSatelliteControllerTimeoutDuration(
+ boolean reset, int timeoutType, long timeoutMillis) {
+ Log.d(LOG_TAG, "setSatelliteControllerTimeoutDuration - " + timeoutMillis + ", reset="
+ + reset + ", timeoutMillis=" + timeoutMillis);
+ TelephonyPermissions.enforceShellOnly(
+ Binder.getCallingUid(), "setSatelliteControllerTimeoutDuration");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ "setSatelliteControllerTimeoutDuration");
+ return mSatelliteController.setSatelliteControllerTimeoutDuration(
+ reset, timeoutType, timeoutMillis);
}
/**
@@ -12765,6 +13769,74 @@
}
/**
+ * This API can be used in only testing to override oem-enabled satellite provision status.
+ *
+ * @param reset {@code true} mean the overriding status should not be used, {@code false}
+ * otherwise.
+ * @param isProvisioned The overriding provision status.
+ * @return {@code true} if the provision status is set successfully, {@code false} otherwise.
+ */
+ public boolean setOemEnabledSatelliteProvisionStatus(boolean reset, boolean isProvisioned) {
+ Log.d(LOG_TAG, "setOemEnabledSatelliteProvisionStatus - reset=" + reset
+ + ", isProvisioned=" + isProvisioned);
+ TelephonyPermissions.enforceShellOnly(
+ Binder.getCallingUid(), "setOemEnabledSatelliteProvisionStatus");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ "setOemEnabledSatelliteProvisionStatus");
+ return mSatelliteController.setOemEnabledSatelliteProvisionStatus(reset, isProvisioned);
+ }
+
+ /**
+ * This API should be used by only CTS tests to forcefully set telephony country codes.
+ *
+ * @return {@code true} if the country code is set successfully, {@code false} otherwise.
+ */
+ public boolean setCountryCodes(boolean reset, List<String> currentNetworkCountryCodes,
+ Map cachedNetworkCountryCodes, String locationCountryCode,
+ long locationCountryCodeTimestampNanos) {
+ Log.d(LOG_TAG, "setCountryCodes: currentNetworkCountryCodes="
+ + String.join(", ", currentNetworkCountryCodes)
+ + ", locationCountryCode=" + locationCountryCode
+ + ", locationCountryCodeTimestampNanos" + locationCountryCodeTimestampNanos
+ + ", reset=" + reset + ", cachedNetworkCountryCodes="
+ + String.join(", ", cachedNetworkCountryCodes.keySet()));
+ TelephonyPermissions.enforceShellOnly(
+ Binder.getCallingUid(), "setCachedLocationCountryCode");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ "setCachedLocationCountryCode");
+ return TelephonyCountryDetector.getInstance(getDefaultPhone().getContext()).setCountryCodes(
+ reset, currentNetworkCountryCodes, cachedNetworkCountryCodes, locationCountryCode,
+ locationCountryCodeTimestampNanos);
+ }
+
+ /**
+ * This API should be used by only CTS tests to override the overlay configs of satellite
+ * access controller.
+ *
+ * @param reset {@code true} mean the overridden configs should not be used, {@code false}
+ * otherwise.
+ * @return {@code true} if the overlay configs are set successfully, {@code false} otherwise.
+ */
+ public boolean setSatelliteAccessControlOverlayConfigs(boolean reset, boolean isAllowed,
+ String s2CellFile, long locationFreshDurationNanos,
+ List<String> satelliteCountryCodes) {
+ Log.d(LOG_TAG, "setSatelliteAccessControlOverlayConfigs: reset=" + reset
+ + ", isAllowed" + isAllowed + ", s2CellFile=" + s2CellFile
+ + ", locationFreshDurationNanos=" + locationFreshDurationNanos
+ + ", satelliteCountryCodes=" + ((satelliteCountryCodes != null)
+ ? String.join(", ", satelliteCountryCodes) : null));
+ TelephonyPermissions.enforceShellOnly(
+ Binder.getCallingUid(), "setSatelliteAccessControlOverlayConfigs");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+ "setSatelliteAccessControlOverlayConfigs");
+ return mSatelliteAccessController.setSatelliteAccessControlOverlayConfigs(reset, isAllowed,
+ s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
+ }
+
+ /**
* This API can be used by only CTS to override the cached value for the device overlay config
* value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
* outgoing satellite datagrams should be sent to modem in demo mode.
@@ -12791,6 +13863,62 @@
}
/**
+ * Sets the service defined in ComponentName to be bound.
+ *
+ * This should only be used for testing.
+ * @return {@code true} if the DomainSelectionService to bind to was set,
+ * {@code false} otherwise.
+ */
+ @Override
+ public boolean setDomainSelectionServiceOverride(ComponentName componentName) {
+ Log.i(LOG_TAG, "setDomainSelectionServiceOverride component=" + componentName);
+
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "setDomainSelectionServiceOverride");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ getDefaultSubscription(), "setDomainSelectionServiceOverride");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
+ return DomainSelectionResolver.getInstance()
+ .setDomainSelectionServiceOverride(componentName);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return false;
+ }
+
+ /**
+ * Clears the DomainSelectionService override.
+ *
+ * This should only be used for testing.
+ * @return {@code true} if the DomainSelectionService override was cleared,
+ * {@code false} otherwise.
+ */
+ @Override
+ public boolean clearDomainSelectionServiceOverride() {
+ Log.i(LOG_TAG, "clearDomainSelectionServiceOverride");
+
+ TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(),
+ "clearDomainSelectionServiceOverride");
+ TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
+ getDefaultSubscription(), "clearDomainSelectionServiceOverride");
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
+ return DomainSelectionResolver.getInstance()
+ .clearDomainSelectionServiceOverride();
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return false;
+ }
+
+ /**
* Enable or disable notifications sent for cellular identifier disclosure events.
*
* Disclosure events are defined as instances where a device has sent a cellular identifier
@@ -12802,7 +13930,7 @@
* @throws UnsupportedOperationException if the modem does not support this feature.
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
- public void enableCellularIdentifierDisclosureNotifications(boolean enable) {
+ public void setEnableCellularIdentifierDisclosureNotifications(boolean enable) {
enforceModifyPermission();
checkForIdentifierDisclosureNotificationSupport();
@@ -12824,13 +13952,56 @@
* @throws UnsupportedOperationException if the modem does not support this feature.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isCellularIdentifierDisclosureNotificationEnabled() {
+ public boolean isCellularIdentifierDisclosureNotificationsEnabled() {
enforceReadPrivilegedPermission("isCellularIdentifierDisclosureNotificationEnabled");
checkForIdentifierDisclosureNotificationSupport();
return getDefaultPhone().getIdentifierDisclosureNotificationsPreferenceEnabled();
}
/**
+ * Enables or disables notifications sent when cellular null cipher or integrity algorithms
+ * are in use by the cellular modem.
+ *
+ * @throws IllegalStateException if the Telephony process is not currently available
+ * @throws SecurityException if the caller does not have the required privileges
+ * @throws UnsupportedOperationException if the modem does not support reporting on ciphering
+ * and integrity algorithms in use
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
+ public void setNullCipherNotificationsEnabled(boolean enable) {
+ enforceModifyPermission();
+ checkForNullCipherNotificationSupport();
+
+ SharedPreferences.Editor editor = mTelephonySharedPreferences.edit();
+ editor.putBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, enable);
+ editor.apply();
+
+ // Each phone instance is responsible for updating its respective modem immediately
+ // after a preference change.
+ for (Phone phone : PhoneFactory.getPhones()) {
+ phone.handleNullCipherNotificationPreferenceChanged();
+ }
+ }
+
+ /**
+ * Get whether notifications are enabled for null cipher or integrity algorithms in use by the
+ * cellular modem.
+ *
+ * @throws IllegalStateException if the Telephony process is not currently available
+ * @throws SecurityException if the caller does not have the required privileges
+ * @throws UnsupportedOperationException if the modem does not support reporting on ciphering
+ * and integrity algorithms in use
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public boolean isNullCipherNotificationsEnabled() {
+ enforceReadPrivilegedPermission("isNullCipherNotificationsEnabled");
+ checkForNullCipherNotificationSupport();
+ return getDefaultPhone().getNullCipherNotificationsPreferenceEnabled();
+ }
+
+ /**
* 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:
@@ -12866,19 +14037,72 @@
*/
private static class CallerCallbackInfo {
private final Consumer<Integer> mConsumer;
- private final int mCarrierId;
+ private final Set<Integer> mCarrierIds;
- public CallerCallbackInfo(Consumer<Integer> consumer, int carrierId) {
+ public CallerCallbackInfo(Consumer<Integer> consumer, Set<Integer> carrierIds) {
mConsumer = consumer;
- mCarrierId = carrierId;
+ mCarrierIds = carrierIds;
}
public Consumer<Integer> getConsumer() {
return mConsumer;
}
- public int getCarrierId() {
- return mCarrierId;
+ public Set<Integer> getCarrierIds() {
+ return mCarrierIds;
+ }
+ }
+
+ /*
+ * PhoneInterfaceManager is a singleton. Unit test calls the init() with context.
+ * But the context that is passed in is unused if the phone app is already alive.
+ * In this case PackageManager object is different in PhoneInterfaceManager and Unit test.
+ */
+ @VisibleForTesting
+ public void setPackageManager(PackageManager packageManager) {
+ mPackageManager = packageManager;
+ }
+
+ /*
+ * PhoneInterfaceManager is a singleton. Unit test calls the init() with context.
+ * But the context that is passed in is unused if the phone app is already alive.
+ * In this case PackageManager object is different in PhoneInterfaceManager and Unit test.
+ */
+ @VisibleForTesting
+ public void setAppOpsManager(AppOpsManager appOps) {
+ mAppOps = appOps;
+ }
+
+ /*
+ * PhoneInterfaceManager is a singleton. Unit test calls the init() with FeatureFlags.
+ * But the FeatureFlags that is passed in is unused if the phone app is already alive.
+ * In this case FeatureFlags object is different in PhoneInterfaceManager and Unit test.
+ */
+ @VisibleForTesting
+ public void setFeatureFlags(FeatureFlags featureFlags) {
+ mFeatureFlags = featureFlags;
+ }
+
+ /**
+ * Make sure the device has required telephony feature
+ *
+ * @throws UnsupportedOperationException if the device does not have required telephony feature
+ */
+ private void enforceTelephonyFeatureWithException(@Nullable String callingPackage,
+ @NonNull String telephonyFeature, @NonNull String methodName) {
+ if (callingPackage == null || mPackageManager == null) {
+ return;
+ }
+
+ if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis()
+ || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage,
+ Binder.getCallingUserHandle())) {
+ return;
+ }
+
+ if (!mPackageManager.hasSystemFeature(telephonyFeature)) {
+ throw new UnsupportedOperationException(
+ methodName + " is unsupported without " + telephonyFeature);
}
}
}
diff --git a/src/com/android/phone/ServiceStateProvider.java b/src/com/android/phone/ServiceStateProvider.java
index 3fa1e58..894d1c7 100644
--- a/src/com/android/phone/ServiceStateProvider.java
+++ b/src/com/android/phone/ServiceStateProvider.java
@@ -41,6 +41,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.Parcel;
+import android.os.UserHandle;
import android.telephony.LocationAccessPolicy;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -577,27 +578,31 @@
ServiceState newSS, int subId) {
final boolean firstUpdate = (oldSS == null) ? true : false;
- // for every field, if the field has changed values, notify via the provider
+ // For every field, if the field has changed values, notify via the provider to all users
if (firstUpdate || voiceRegStateChanged(oldSS, newSS)) {
context.getContentResolver().notifyChange(
getUriForSubscriptionIdAndField(subId, VOICE_REG_STATE),
- /* observer= */ null, /* syncToNetwork= */ false);
+ /* observer= */ null, /* syncToNetwork= */ false, UserHandle.USER_ALL);
}
if (firstUpdate || dataRegStateChanged(oldSS, newSS)) {
context.getContentResolver().notifyChange(
- getUriForSubscriptionIdAndField(subId, DATA_REG_STATE), null, false);
+ getUriForSubscriptionIdAndField(subId, DATA_REG_STATE),
+ /* observer= */ null, /* syncToNetwork= */ false, UserHandle.USER_ALL);
}
if (firstUpdate || voiceRoamingTypeChanged(oldSS, newSS)) {
context.getContentResolver().notifyChange(
- getUriForSubscriptionIdAndField(subId, VOICE_ROAMING_TYPE), null, false);
+ getUriForSubscriptionIdAndField(subId, VOICE_ROAMING_TYPE),
+ /* observer= */ null, /* syncToNetwork= */ false, UserHandle.USER_ALL);
}
if (firstUpdate || dataRoamingTypeChanged(oldSS, newSS)) {
context.getContentResolver().notifyChange(
- getUriForSubscriptionIdAndField(subId, DATA_ROAMING_TYPE), null, false);
+ getUriForSubscriptionIdAndField(subId, DATA_ROAMING_TYPE),
+ /* observer= */ null, /* syncToNetwork= */ false, UserHandle.USER_ALL);
}
if (firstUpdate || dataNetworkTypeChanged(oldSS, newSS)) {
context.getContentResolver().notifyChange(
- getUriForSubscriptionIdAndField(subId, DATA_NETWORK_TYPE), null, false);
+ getUriForSubscriptionIdAndField(subId, DATA_NETWORK_TYPE),
+ /* observer= */ null, /* syncToNetwork= */ false, UserHandle.USER_ALL);
}
}
@@ -635,14 +640,15 @@
@VisibleForTesting
public static void notifyChangeForSubId(Context context, ServiceState oldSS, ServiceState newSS,
int subId) {
- // if the voice or data registration or roaming state field has changed values, notify via
- // the provider.
+ // If the voice or data registration or roaming state field has changed values, notify via
+ // the provider to all users.
// If oldSS is null and newSS is not (e.g. first update of service state) this will also
- // notify
+ // notify to all users.
if (oldSS == null || voiceRegStateChanged(oldSS, newSS) || dataRegStateChanged(oldSS, newSS)
|| voiceRoamingTypeChanged(oldSS, newSS) || dataRoamingTypeChanged(oldSS, newSS)
|| dataNetworkTypeChanged(oldSS, newSS)) {
- context.getContentResolver().notifyChange(getUriForSubscriptionId(subId), null, false);
+ context.getContentResolver().notifyChange(getUriForSubscriptionId(subId),
+ /* observer= */ null, /* syncToNetwork= */ false, UserHandle.USER_ALL);
}
}
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 5986a7c..80304b2 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -24,6 +24,9 @@
import static java.util.Map.entry;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
import android.net.Uri;
import android.os.Binder;
@@ -65,6 +68,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -187,13 +191,25 @@
"set-satellite-listening-timeout-duration";
private static final String SET_SATELLITE_POINTING_UI_CLASS_NAME =
"set-satellite-pointing-ui-class-name";
- private static final String SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION =
- "set-satellite-device-aligned-timeout-duration";
+ private static final String SET_DATAGRAM_CONTROLLER_TIMEOUT_DURATION =
+ "set-datagram-controller-timeout-duration";
+
+ private static final String SET_SATELLITE_CONTROLLER_TIMEOUT_DURATION =
+ "set-satellite-controller-timeout-duration";
private static final String SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE =
"set-emergency-call-to-satellite-handover-type";
+ private static final String SET_COUNTRY_CODES = "set-country-codes";
+ private static final String SET_SATELLITE_ACCESS_CONTROL_OVERLAY_CONFIGS =
+ "set-satellite-access-control-overlay-configs";
+ private static final String SET_OEM_ENABLED_SATELLITE_PROVISION_STATUS =
+ "set-oem-enabled-satellite-provision-status";
private static final String SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE =
"set-should-send-datagram-to-modem-in-demo-mode";
+ private static final String DOMAIN_SELECTION_SUBCOMMAND = "domainselection";
+ private static final String DOMAIN_SELECTION_SET_SERVICE_OVERRIDE = "set-dss-override";
+ private static final String DOMAIN_SELECTION_CLEAR_SERVICE_OVERRIDE = "clear-dss-override";
+
private static final String INVALID_ENTRY_ERROR = "An emergency number (only allow '0'-'9', "
+ "'*', '#' or '+') needs to be specified after -a in the command ";
@@ -374,6 +390,8 @@
return setCarrierServicePackageOverride();
case CLEAR_CARRIER_SERVICE_PACKAGE_OVERRIDE:
return clearCarrierServicePackageOverride();
+ case DOMAIN_SELECTION_SUBCOMMAND:
+ return handleDomainSelectionCommand();
case SET_SATELLITE_SERVICE_PACKAGE_NAME:
return handleSetSatelliteServicePackageNameCommand();
case SET_SATELLITE_GATEWAY_SERVICE_PACKAGE_NAME:
@@ -382,12 +400,20 @@
return handleSetSatelliteListeningTimeoutDuration();
case SET_SATELLITE_POINTING_UI_CLASS_NAME:
return handleSetSatellitePointingUiClassNameCommand();
- case SET_SATELLITE_DEVICE_ALIGNED_TIMEOUT_DURATION:
- return handleSettSatelliteDeviceAlignedTimeoutDuration();
+ case SET_DATAGRAM_CONTROLLER_TIMEOUT_DURATION:
+ return handleSetDatagramControllerTimeoutDuration();
+ case SET_SATELLITE_CONTROLLER_TIMEOUT_DURATION:
+ return handleSetSatelliteControllerTimeoutDuration();
case SET_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE:
return handleSetEmergencyCallToSatelliteHandoverType();
case SET_SHOULD_SEND_DATAGRAM_TO_MODEM_IN_DEMO_MODE:
return handleSetShouldSendDatagramToModemInDemoMode();
+ case SET_SATELLITE_ACCESS_CONTROL_OVERLAY_CONFIGS:
+ return handleSetSatelliteAccessControlOverlayConfigs();
+ case SET_COUNTRY_CODES:
+ return handleSetCountryCodes();
+ case SET_OEM_ENABLED_SATELLITE_PROVISION_STATUS:
+ return handleSetOemEnabledSatelliteProvisionStatus();
default: {
return handleDefaultCommands(cmd);
}
@@ -442,6 +468,7 @@
onHelpRadio();
onHelpImei();
onHelpSatellite();
+ onHelpDomainSelection();
}
private void onHelpD2D() {
@@ -795,6 +822,29 @@
pw.println(" If no option is specified, override is disabled.");
pw.println(" -d: the delay in seconds in sending EVENT_DISPLAY_EMERGENCY_MESSAGE.");
pw.println(" If no option is specified, there is no delay in sending the event.");
+ pw.println(" set-satellite-access-control-overlay-configs [-r -a -f SATELLITE_S2_FILE ");
+ pw.println(" -d LOCATION_FRESH_DURATION_NANOS -c COUNTRY_CODES] Override the overlay");
+ pw.println(" configs of satellite access controller.");
+ pw.println(" Options are:");
+ pw.println(" -r: clear the overriding. Absent means enable overriding.");
+ pw.println(" -a: the country codes is an allowed list. Absent means disallowed.");
+ pw.println(" -f: the satellite s2 file.");
+ pw.println(" -d: the location fresh duration nanos.");
+ pw.println(" -c: the list of satellite country codes separated by comma.");
+ pw.println(" set-country-codes [-r -n CURRENT_NETWORK_COUNTRY_CODES -c");
+ pw.println(" CACHED_NETWORK_COUNTRY_CODES -l LOCATION_COUNTRY_CODE -t");
+ pw.println(" LOCATION_COUNTRY_CODE_TIMESTAMP] ");
+ pw.println(" Override the cached location country code and its update timestamp. ");
+ pw.println(" Options are:");
+ pw.println(" -r: clear the overriding. Absent means enable overriding.");
+ pw.println(" -n: the current network country code ISOs.");
+ pw.println(" -c: the cached network country code ISOs.");
+ pw.println(" -l: the location country code ISO.");
+ pw.println(" -t: the update timestamp nanos of the location country code.");
+ pw.println(" set-oem-enabled-satellite-provision-status [-p true/false]");
+ pw.println(" Sets the OEM-enabled satellite provision status. Options are:");
+ pw.println(" -p: the overriding satellite provision status. If no option is ");
+ pw.println(" specified, reset the overridden provision status.");
}
private void onHelpImei() {
@@ -806,6 +856,15 @@
pw.println(" is specified, it will choose the default voice SIM slot.");
}
+ private void onHelpDomainSelection() {
+ PrintWriter pw = getOutPrintWriter();
+ pw.println("Domain Selection Commands:");
+ pw.println(" domainselection set-dss-override COMPONENT_NAME");
+ pw.println(" Sets the service defined in COMPONENT_NAME to be bound");
+ pw.println(" domainselection clear-dss-override");
+ pw.println(" Clears DomainSelectionService override.");
+ }
+
private int handleImsCommand() {
String arg = getNextArg();
if (arg == null) {
@@ -3314,31 +3373,85 @@
return 0;
}
- private int handleSettSatelliteDeviceAlignedTimeoutDuration() {
+ private int handleSetDatagramControllerTimeoutDuration() {
PrintWriter errPw = getErrPrintWriter();
+ boolean reset = false;
+ int timeoutType = 0;
long timeoutMillis = 0;
String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
- case "-t": {
+ case "-d": {
timeoutMillis = Long.parseLong(getNextArgRequired());
break;
}
+ case "-r": {
+ reset = true;
+ break;
+ }
+ case "-t": {
+ timeoutType = Integer.parseInt(getNextArgRequired());
+ break;
+ }
}
}
- Log.d(LOG_TAG, "handleSettSatelliteDeviceAlignedTimeoutDuration: timeoutMillis="
- + timeoutMillis);
+ Log.d(LOG_TAG, "setDatagramControllerTimeoutDuration: timeoutMillis="
+ + timeoutMillis + ", reset=" + reset + ", timeoutType=" + timeoutType);
try {
- boolean result = mInterface.setSatelliteDeviceAlignedTimeoutDuration(timeoutMillis);
+ boolean result = mInterface.setDatagramControllerTimeoutDuration(
+ reset, timeoutType, timeoutMillis);
if (VDBG) {
- Log.v(LOG_TAG, "setSatelliteDeviceAlignedTimeoutDuration " + timeoutMillis
+ Log.v(LOG_TAG, "setDatagramControllerTimeoutDuration " + timeoutMillis
+ ", result = " + result);
}
getOutPrintWriter().println(result);
} catch (RemoteException e) {
- Log.w(LOG_TAG, "setSatelliteDeviceAlignedTimeoutDuration: " + timeoutMillis
+ Log.w(LOG_TAG, "setDatagramControllerTimeoutDuration: " + timeoutMillis
+ + ", error = " + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
+ private int handleSetSatelliteControllerTimeoutDuration() {
+ PrintWriter errPw = getErrPrintWriter();
+ boolean reset = false;
+ int timeoutType = 0;
+ long timeoutMillis = 0;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-d": {
+ timeoutMillis = Long.parseLong(getNextArgRequired());
+ break;
+ }
+ case "-r": {
+ reset = true;
+ break;
+ }
+ case "-t": {
+ timeoutType = Integer.parseInt(getNextArgRequired());
+ break;
+ }
+ }
+ }
+ Log.d(LOG_TAG, "setSatelliteControllerTimeoutDuration: timeoutMillis="
+ + timeoutMillis + ", reset=" + reset + ", timeoutType=" + timeoutType);
+
+ try {
+ boolean result = mInterface.setSatelliteControllerTimeoutDuration(
+ reset, timeoutType, timeoutMillis);
+ if (VDBG) {
+ Log.v(LOG_TAG, "setSatelliteControllerTimeoutDuration " + timeoutMillis
+ + ", result = " + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "setSatelliteControllerTimeoutDuration: " + timeoutMillis
+ ", error = " + e.getMessage());
errPw.println("Exception: " + e.getMessage());
return -1;
@@ -3394,6 +3507,186 @@
return 0;
}
+ private int handleSetSatelliteAccessControlOverlayConfigs() {
+ PrintWriter errPw = getErrPrintWriter();
+ boolean reset = false;
+ boolean isAllowed = false;
+ String s2CellFile = null;
+ long locationFreshDurationNanos = 0;
+ List<String> satelliteCountryCodes = null;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-r": {
+ reset = true;
+ break;
+ }
+ case "-a": {
+ isAllowed = true;
+ break;
+ }
+ case "-f": {
+ s2CellFile = getNextArgRequired();
+ break;
+ }
+ case "-d": {
+ locationFreshDurationNanos = Long.parseLong(getNextArgRequired());
+ break;
+ }
+ case "-c": {
+ String countryCodeStr = getNextArgRequired();
+ satelliteCountryCodes = Arrays.asList(countryCodeStr.split(","));
+ break;
+ }
+ }
+ }
+ Log.d(LOG_TAG, "handleSetSatelliteAccessControlOverlayConfigs: reset=" + reset
+ + ", isAllowed=" + isAllowed + ", s2CellFile=" + s2CellFile
+ + ", locationFreshDurationNanos=" + locationFreshDurationNanos
+ + ", satelliteCountryCodes=" + satelliteCountryCodes);
+
+ try {
+ boolean result = mInterface.setSatelliteAccessControlOverlayConfigs(reset, isAllowed,
+ s2CellFile, locationFreshDurationNanos, satelliteCountryCodes);
+ if (VDBG) {
+ Log.v(LOG_TAG, "setSatelliteAccessControlOverlayConfigs result =" + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "setSatelliteAccessControlOverlayConfigs: ex=" + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
+ private int handleSetCountryCodes() {
+ PrintWriter errPw = getErrPrintWriter();
+ List<String> currentNetworkCountryCodes = new ArrayList<>();
+ String locationCountryCode = null;
+ long locationCountryCodeTimestampNanos = 0;
+ Map<String, Long> cachedNetworkCountryCodes = new HashMap<>();
+ boolean reset = false;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-r": {
+ reset = true;
+ break;
+ }
+ case "-n": {
+ String countryCodeStr = getNextArgRequired();
+ currentNetworkCountryCodes = Arrays.asList(countryCodeStr.split(","));
+ break;
+ }
+ case "-c": {
+ String cachedNetworkCountryCodeStr = getNextArgRequired();
+ cachedNetworkCountryCodes = parseStringLongMap(cachedNetworkCountryCodeStr);
+ break;
+ }
+ case "-l": {
+ locationCountryCode = getNextArgRequired();
+ break;
+ }
+ case "-t": {
+ locationCountryCodeTimestampNanos = Long.parseLong(getNextArgRequired());
+ break;
+ }
+ }
+ }
+ Log.d(LOG_TAG, "setCountryCodes: locationCountryCode="
+ + locationCountryCode + ", locationCountryCodeTimestampNanos="
+ + locationCountryCodeTimestampNanos + ", currentNetworkCountryCodes="
+ + currentNetworkCountryCodes);
+
+ try {
+ boolean result = mInterface.setCountryCodes(reset, currentNetworkCountryCodes,
+ cachedNetworkCountryCodes, locationCountryCode,
+ locationCountryCodeTimestampNanos);
+ if (VDBG) {
+ Log.v(LOG_TAG, "setCountryCodes result =" + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (RemoteException e) {
+ Log.e(LOG_TAG, "setCountryCodes: ex=" + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
+ private int handleSetOemEnabledSatelliteProvisionStatus() {
+ PrintWriter errPw = getErrPrintWriter();
+ boolean isProvisioned = false;
+ boolean reset = true;
+
+ String opt;
+ while ((opt = getNextOption()) != null) {
+ switch (opt) {
+ case "-p": {
+ try {
+ isProvisioned = Boolean.parseBoolean(getNextArgRequired());
+ reset = false;
+ } catch (Exception e) {
+ errPw.println("setOemEnabledSatelliteProvisionStatus requires a boolean "
+ + "after -p indicating provision status");
+ return -1;
+ }
+ }
+ }
+ }
+ Log.d(LOG_TAG, "setOemEnabledSatelliteProvisionStatus: reset=" + reset
+ + ", isProvisioned=" + isProvisioned);
+
+ try {
+ boolean result = mInterface.setOemEnabledSatelliteProvisionStatus(reset, isProvisioned);
+ if (VDBG) {
+ Log.v(LOG_TAG, "setOemEnabledSatelliteProvisionStatus result = " + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "setOemEnabledSatelliteProvisionStatus: error = " + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
+ /**
+ * Sample inputStr = "US,UK,CA;2,1,3"
+ * Sample output: {[US,2], [UK,1], [CA,3]}
+ */
+ @NonNull private Map<String, Long> parseStringLongMap(@Nullable String inputStr) {
+ Map<String, Long> result = new HashMap<>();
+ if (!TextUtils.isEmpty(inputStr)) {
+ String[] stringLongArr = inputStr.split(";");
+ if (stringLongArr.length != 2) {
+ Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr);
+ return result;
+ }
+
+ String[] stringArr = stringLongArr[0].split(",");
+ String[] longArr = stringLongArr[1].split(",");
+ if (stringArr.length != longArr.length) {
+ Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr);
+ return result;
+ }
+
+ for (int i = 0; i < stringArr.length; i++) {
+ try {
+ result.put(stringArr[i], Long.parseLong(longArr[i]));
+ } catch (Exception ex) {
+ Log.e(LOG_TAG, "parseStringLongMap: invalid inputStr=" + inputStr
+ + ", ex=" + ex);
+ return result;
+ }
+ }
+ }
+ return result;
+ }
+
private int handleCarrierRestrictionStatusCommand() {
try {
String MOCK_MODEM_SERVICE_NAME = "android.telephony.mockmodem.MockModemService";
@@ -3527,10 +3820,70 @@
return 0;
}
+ private int handleDomainSelectionCommand() {
+ String arg = getNextArg();
+ if (arg == null) {
+ onHelpDomainSelection();
+ return 0;
+ }
+
+ switch (arg) {
+ case DOMAIN_SELECTION_SET_SERVICE_OVERRIDE: {
+ return handleDomainSelectionSetServiceOverrideCommand();
+ }
+ case DOMAIN_SELECTION_CLEAR_SERVICE_OVERRIDE: {
+ return handleDomainSelectionClearServiceOverrideCommand();
+ }
+ }
+
+ return -1;
+ }
+
+ // domainselection set-dss-override
+ private int handleDomainSelectionSetServiceOverrideCommand() {
+ PrintWriter errPw = getErrPrintWriter();
+
+ String componentName = getNextArg();
+
+ try {
+ boolean result = mInterface.setDomainSelectionServiceOverride(
+ ComponentName.unflattenFromString(componentName));
+ if (VDBG) {
+ Log.v(LOG_TAG, "domainselection set-dss-override "
+ + componentName + ", result=" + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (Exception e) {
+ Log.w(LOG_TAG, "domainselection set-dss-override "
+ + componentName + ", error=" + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
+ // domainselection clear-dss-override
+ private int handleDomainSelectionClearServiceOverrideCommand() {
+ PrintWriter errPw = getErrPrintWriter();
+
+ try {
+ boolean result = mInterface.clearDomainSelectionServiceOverride();
+ if (VDBG) {
+ Log.v(LOG_TAG, "domainselection clear-dss-override result=" + result);
+ }
+ getOutPrintWriter().println(result);
+ } catch (RemoteException e) {
+ Log.w(LOG_TAG, "domainselection clear-dss-override error=" + e.getMessage());
+ errPw.println("Exception: " + e.getMessage());
+ return -1;
+ }
+ return 0;
+ }
+
/**
* 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"]}}
+ * {"com.android.example":{"carrierIds":[10000],"callerSHA256Ids":["XXXXXXXXXXXXXX"]}}
*/
private String convertToJsonString(int index, String param) {
@@ -3542,7 +3895,7 @@
break;
case 1:
jSonString =
- "{" + QUOTES + token[0] + QUOTES + ":" + QUOTES + token[1] + QUOTES + ",";
+ "{" + QUOTES + token[0] + QUOTES + ":" + "[" + token[1] + "],";
break;
case 2:
jSonString =
diff --git a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
index 5da52d6..3e44062 100644
--- a/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
+++ b/src/com/android/phone/euicc/EuiccUiDispatcherActivity.java
@@ -113,7 +113,7 @@
@Nullable
Intent resolveEuiccUiIntent() {
EuiccManager euiccManager = (EuiccManager) getSystemService(Context.EUICC_SERVICE);
- if (!euiccManager.isEnabled()) {
+ if (euiccManager == null || !euiccManager.isEnabled()) {
Log.w(TAG, "eUICC not enabled");
return null;
}
diff --git a/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessController.java b/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessController.java
index 62fbd18..4490460 100644
--- a/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessController.java
@@ -63,9 +63,9 @@
return new S2RangeSatelliteOnDeviceAccessController(reader, s2Level);
}
- @Override
- public LocationToken createLocationTokenForLatLng(double latDegrees, double lngDegrees) {
- return new LocationTokenImpl(getS2CellId(latDegrees, lngDegrees).id());
+ public static LocationToken createLocationTokenForLatLng(
+ double latDegrees, double lngDegrees, int s2Level) {
+ return new LocationTokenImpl(getS2CellId(latDegrees, lngDegrees, s2Level).id());
}
@Override
@@ -78,6 +78,11 @@
return isSatCommunicationAllowedAtLocation(locationTokenImpl.getS2CellId());
}
+ @Override
+ public int getS2Level() {
+ return mS2Level;
+ }
+
private boolean isSatCommunicationAllowedAtLocation(long s2CellId) throws IOException {
S2LevelRange entry = mSatS2RangeFileReader.findEntryByCellId(s2CellId);
if (mSatS2RangeFileReader.isAllowedList()) {
@@ -91,12 +96,12 @@
}
}
- private S2CellId getS2CellId(double latDegrees, double lngDegrees) {
+ private static S2CellId getS2CellId(double latDegrees, double lngDegrees, int s2Level) {
// Create the leaf S2 cell containing the given S2LatLng
S2CellId cellId = S2CellId.fromLatLng(S2LatLng.fromDegrees(latDegrees, lngDegrees));
// Return the S2 cell at the expected S2 level
- return cellId.parent(mS2Level);
+ return cellId.parent(s2Level);
}
@Override
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index 7f9c1aa..8353861 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -16,17 +16,71 @@
package com.android.phone.satellite.accesscontrol;
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_SHARED_PREF;
+
+import android.annotation.ArrayRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+import android.os.AsyncResult;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.CancellationSignal;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.ResultReceiver;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.provider.DeviceConfig;
+import android.telecom.TelecomManager;
+import android.telephony.AnomalyReporter;
import android.telephony.Rlog;
import android.telephony.satellite.SatelliteManager;
+import android.text.TextUtils;
+import android.util.Pair;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyCountryDetector;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.SatelliteConfig;
+import com.android.internal.telephony.satellite.SatelliteController;
+import com.android.internal.telephony.util.TelephonyUtils;
+import com.android.phone.PhoneGlobals;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
/**
* This module is responsible for making sure that satellite communication can be used by devices
@@ -34,34 +88,178 @@
*/
public class SatelliteAccessController extends Handler {
private static final String TAG = "SatelliteAccessController";
+ /**
+ * UUID to report an anomaly when getting an exception in looking up on-device data for the
+ * current location.
+ */
+ private static final String UUID_ON_DEVICE_LOOKUP_EXCEPTION =
+ "dbea1641-630e-4780-9f25-8337ba6c3563";
+ /**
+ * UUID to report an anomaly when getting an exception in creating the on-device access
+ * controller.
+ */
+ private static final String UUID_CREATE_ON_DEVICE_ACCESS_CONTROLLER_EXCEPTION =
+ "3ac767d8-2867-4d60-97c2-ae9d378a5521";
+ protected static final long WAIT_FOR_CURRENT_LOCATION_TIMEOUT_MILLIS =
+ TimeUnit.SECONDS.toMillis(180);
+ protected static final long KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT_MILLIS =
+ TimeUnit.MINUTES.toMillis(30);
+ protected static final int DEFAULT_S2_LEVEL = 12;
+ private static final int DEFAULT_LOCATION_FRESH_DURATION_SECONDS = 600;
+ private static final boolean DEFAULT_SATELLITE_ACCESS_ALLOW = true;
+ private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
+ private static final String BOOT_ALLOW_MOCK_MODEM_PROPERTY = "ro.boot.radio.allow_mock_modem";
+ private static final boolean DEBUG = !"user".equals(Build.TYPE);
+ private static final int MAX_CACHE_SIZE = 50;
private static final int CMD_IS_SATELLITE_COMMUNICATION_ALLOWED = 1;
+ protected static final int EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT = 2;
+ protected static final int EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT = 3;
+ protected static final int EVENT_CONFIG_DATA_UPDATED = 4;
+
+ private static SatelliteAccessController sInstance;
/** Feature flags to control behavior and errors. */
- @NonNull private final FeatureFlags mFeatureFlags;
- @Nullable private final SatelliteOnDeviceAccessController mSatelliteOnDeviceAccessController;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
+ @GuardedBy("mLock")
+ @Nullable
+ protected SatelliteOnDeviceAccessController mSatelliteOnDeviceAccessController;
+ @NonNull
+ private final LocationManager mLocationManager;
+ @NonNull
+ private final TelecomManager mTelecomManager;
+ @NonNull
+ private final TelephonyCountryDetector mCountryDetector;
+ @NonNull
+ private final SatelliteController mSatelliteController;
+ @NonNull
+ private final ResultReceiver mInternalSatelliteSupportedResultReceiver;
+ @NonNull
+ protected final Object mLock = new Object();
+ @GuardedBy("mLock")
+ @NonNull
+ private final Set<ResultReceiver> mSatelliteAllowResultReceivers = new HashSet<>();
+ @NonNull
+ private List<String> mSatelliteCountryCodes;
+ private boolean mIsSatelliteAllowAccessControl;
+ @Nullable
+ private File mSatelliteS2CellFile;
+ private long mLocationFreshDurationNanos;
+ @GuardedBy("mLock")
+ private boolean mIsOverlayConfigOverridden = false;
+ @NonNull
+ private List<String> mOverriddenSatelliteCountryCodes;
+ private boolean mOverriddenIsSatelliteAllowAccessControl;
+ @Nullable
+ private File mOverriddenSatelliteS2CellFile;
+ private long mOverriddenLocationFreshDurationNanos;
+ @GuardedBy("mLock")
+ @NonNull
+ private final Map<SatelliteOnDeviceAccessController.LocationToken, Boolean>
+ mCachedAccessRestrictionMap = new LinkedHashMap<>() {
+ @Override
+ protected boolean removeEldestEntry(
+ Entry<SatelliteOnDeviceAccessController.LocationToken, Boolean> eldest) {
+ return size() > MAX_CACHE_SIZE;
+ }
+ };
+ @GuardedBy("mLock")
+ @Nullable
+ CancellationSignal mLocationRequestCancellationSignal = null;
+ private int mS2Level = DEFAULT_S2_LEVEL;
+ @GuardedBy("mLock")
+ @Nullable
+ private Location mFreshLastKnownLocation = null;
+
+ /** These are used for CTS test */
+ private Path mCtsSatS2FilePath = null;
+ protected static final String GOOGLE_US_SAN_SAT_S2_FILE_NAME = "google_us_san_sat_s2.dat";
+
+ /** These are for config updater config data */
+ private static final String SATELLITE_ACCESS_CONTROL_DATA_DIR = "satellite_access_control";
+ private static final String CONFIG_UPDATER_S2_CELL_FILE_NAME = "config_updater_sat_s2.dat";
+ private static final int MIN_S2_LEVEL = 0;
+ private static final int MAX_S2_LEVEL = 30;
+ private static final String CONFIG_UPDATER_SATELLITE_COUNTRY_CODES_KEY =
+ "config_updater_satellite_country_codes";
+ private static final String CONFIG_UPDATER_SATELLITE_IS_ALLOW_ACCESS_CONTROL_KEY =
+ "config_updater_satellite_is_allow_access_control";
+ private SharedPreferences mSharedPreferences;
/**
* Create a SatelliteAccessController instance.
*
- * @param featureFlags The FeatureFlags that are supported.
- * @param looper The Looper to run the SatelliteAccessController on.
- * @param satelliteOnDeviceAccessController The location-based satellite restriction lookup.
+ * @param context The context associated with the
+ * {@link SatelliteAccessController} instance.
+ * @param featureFlags The FeatureFlags that are supported.
+ * @param locationManager The LocationManager for querying current location of
+ * the device.
+ * @param looper The Looper to run the SatelliteAccessController on.
+ * @param satelliteOnDeviceAccessController The on-device satellite access controller instance.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public SatelliteAccessController(@NonNull FeatureFlags featureFlags, @NonNull Looper looper,
- @Nullable SatelliteOnDeviceAccessController satelliteOnDeviceAccessController) {
+ protected SatelliteAccessController(@NonNull Context context,
+ @NonNull FeatureFlags featureFlags, @NonNull Looper looper,
+ @NonNull LocationManager locationManager, @NonNull TelecomManager telecomManager,
+ @Nullable SatelliteOnDeviceAccessController satelliteOnDeviceAccessController,
+ @Nullable File s2CellFile) {
super(looper);
mFeatureFlags = featureFlags;
+ mLocationManager = locationManager;
+ mTelecomManager = telecomManager;
mSatelliteOnDeviceAccessController = satelliteOnDeviceAccessController;
+ mCountryDetector = TelephonyCountryDetector.getInstance(context);
+ mSatelliteController = SatelliteController.getInstance();
+ initSharedPreferences(context);
+ loadOverlayConfigs(context);
+ // loadConfigUpdaterConfigs has to be called after loadOverlayConfigs
+ // since config updater config has higher priority and thus can override overlay config
+ loadConfigUpdaterConfigs();
+ mSatelliteController.registerForConfigUpdateChanged(this, EVENT_CONFIG_DATA_UPDATED,
+ context);
+ if (s2CellFile != null) {
+ mSatelliteS2CellFile = s2CellFile;
+ }
+ mInternalSatelliteSupportedResultReceiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ handleIsSatelliteSupportedResult(resultCode, resultData);
+ }
+ };
+ // Init the SatelliteOnDeviceAccessController so that the S2 level can be cached
+ initSatelliteOnDeviceAccessController();
+ }
+
+ /** @return the singleton instance of {@link SatelliteAccessController} */
+ public static synchronized SatelliteAccessController getOrCreateInstance(
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (sInstance == null) {
+ HandlerThread handlerThread = new HandlerThread("SatelliteAccessController");
+ handlerThread.start();
+ sInstance = new SatelliteAccessController(context, featureFlags,
+ handlerThread.getLooper(), context.getSystemService(LocationManager.class),
+ context.getSystemService(TelecomManager.class), null, null);
+ }
+ return sInstance;
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case CMD_IS_SATELLITE_COMMUNICATION_ALLOWED:
- handleRequestIsSatelliteCommunicationAllowedForCurrentLocation(
- (ResultReceiver) msg.obj);
+ handleCmdIsSatelliteAllowedForCurrentLocation(
+ (Pair<Integer, ResultReceiver>) msg.obj);
+ break;
+ case EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT:
+ handleWaitForCurrentLocationTimedOutEvent();
+ break;
+ case EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT:
+ cleanupOnDeviceAccessControllerResources();
+ break;
+ case EVENT_CONFIG_DATA_UPDATED:
+ AsyncResult ar = (AsyncResult) msg.obj;
+ updateSatelliteConfigData((Context) ar.userObj);
break;
default:
logw("SatelliteAccessControllerHandler: unexpected message code: " + msg.what);
@@ -72,29 +270,910 @@
/**
* 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.
*/
- public void requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ public void requestIsCommunicationAllowedForCurrentLocation(int subId,
@NonNull ResultReceiver result) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
logd("oemEnabledSatelliteFlag is disabled");
- result.send(SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
return;
}
- sendRequestAsync(CMD_IS_SATELLITE_COMMUNICATION_ALLOWED, result);
+ sendRequestAsync(CMD_IS_SATELLITE_COMMUNICATION_ALLOWED, new Pair<>(subId, result));
}
- private void handleRequestIsSatelliteCommunicationAllowedForCurrentLocation(
- @NonNull ResultReceiver result) {
- // To be implemented
+ /**
+ * This API should be used by only CTS tests to override the overlay configs of satellite
+ * access controller.
+ */
+ public boolean setSatelliteAccessControlOverlayConfigs(boolean reset, boolean isAllowed,
+ @Nullable String s2CellFile, long locationFreshDurationNanos,
+ @Nullable List<String> satelliteCountryCodes) {
+ if (!isMockModemAllowed()) {
+ logd("setSatelliteAccessControllerOverlayConfigs: mock modem is not allowed");
+ return false;
+ }
+ logd("setSatelliteAccessControlOverlayConfigs: reset=" + reset
+ + ", isAllowed" + isAllowed + ", s2CellFile=" + s2CellFile
+ + ", locationFreshDurationNanos=" + locationFreshDurationNanos
+ + ", satelliteCountryCodes=" + ((satelliteCountryCodes != null)
+ ? String.join(", ", satelliteCountryCodes) : null));
+ synchronized (mLock) {
+ if (reset) {
+ mIsOverlayConfigOverridden = false;
+ cleanUpCtsResources();
+ } else {
+ mIsOverlayConfigOverridden = true;
+ mOverriddenIsSatelliteAllowAccessControl = isAllowed;
+ if (!TextUtils.isEmpty(s2CellFile)) {
+ mOverriddenSatelliteS2CellFile = getTestSatelliteS2File(s2CellFile);
+ if (!mOverriddenSatelliteS2CellFile.exists()) {
+ logd("The overriding file "
+ + mOverriddenSatelliteS2CellFile.getAbsolutePath()
+ + " does not exist");
+ mOverriddenSatelliteS2CellFile = null;
+ }
+ } else {
+ mOverriddenSatelliteS2CellFile = null;
+ }
+ mOverriddenLocationFreshDurationNanos = locationFreshDurationNanos;
+ if (satelliteCountryCodes != null) {
+ mOverriddenSatelliteCountryCodes = satelliteCountryCodes;
+ } else {
+ mOverriddenSatelliteCountryCodes = new ArrayList<>();
+ }
+ }
+ cleanupOnDeviceAccessControllerResources();
+ initSatelliteOnDeviceAccessController();
+ }
+ return true;
+ }
+
+ protected File getTestSatelliteS2File(String fileName) {
+ logd("getTestSatelliteS2File: fileName=" + fileName);
+ if (TextUtils.equals(fileName, GOOGLE_US_SAN_SAT_S2_FILE_NAME)) {
+ mCtsSatS2FilePath = copyTestSatS2FileToPhoneDirectory(GOOGLE_US_SAN_SAT_S2_FILE_NAME);
+ if (mCtsSatS2FilePath != null) {
+ return mCtsSatS2FilePath.toFile();
+ } else {
+ loge("getTestSatelliteS2File: mCtsSatS2FilePath is null");
+ }
+ }
+ return new File(fileName);
+ }
+
+ @Nullable
+ private static Path copyTestSatS2FileToPhoneDirectory(String sourceFileName) {
+ PhoneGlobals phoneGlobals = PhoneGlobals.getInstance();
+ File ctsFile = phoneGlobals.getDir("cts", Context.MODE_PRIVATE);
+ if (!ctsFile.exists()) {
+ ctsFile.mkdirs();
+ }
+
+ Path targetDir = ctsFile.toPath();
+ Path targetSatS2FilePath = targetDir.resolve(sourceFileName);
+ try {
+ InputStream inputStream = phoneGlobals.getAssets().open(sourceFileName);
+ if (inputStream == null) {
+ loge("copyTestSatS2FileToPhoneDirectory: Resource=" + sourceFileName
+ + " not found");
+ } else {
+ Files.copy(inputStream, targetSatS2FilePath, StandardCopyOption.REPLACE_EXISTING);
+ }
+ } catch (IOException ex) {
+ loge("copyTestSatS2FileToPhoneDirectory: ex=" + ex);
+ }
+ return targetSatS2FilePath;
+ }
+
+ @Nullable
+ private static File copySatS2FileToLocalDirectory(@NonNull File sourceFile) {
+ PhoneGlobals phoneGlobals = PhoneGlobals.getInstance();
+ File satelliteAccessControlFile = phoneGlobals.getDir(
+ SATELLITE_ACCESS_CONTROL_DATA_DIR, Context.MODE_PRIVATE);
+ if (!satelliteAccessControlFile.exists()) {
+ satelliteAccessControlFile.mkdirs();
+ }
+
+ Path targetDir = satelliteAccessControlFile.toPath();
+ Path targetSatS2FilePath = targetDir.resolve(CONFIG_UPDATER_S2_CELL_FILE_NAME);
+ try {
+ InputStream inputStream = new FileInputStream(sourceFile);
+ if (inputStream == null) {
+ loge("copySatS2FileToPhoneDirectory: Resource=" + sourceFile.getAbsolutePath()
+ + " not found");
+ return null;
+ } else {
+ Files.copy(inputStream, targetSatS2FilePath, StandardCopyOption.REPLACE_EXISTING);
+ }
+ } catch (IOException ex) {
+ loge("copySatS2FileToPhoneDirectory: ex=" + ex);
+ return null;
+ }
+ return targetSatS2FilePath.toFile();
+ }
+
+ @Nullable
+ private File getConfigUpdaterSatS2CellFileFromLocalDirectory() {
+ PhoneGlobals phoneGlobals = PhoneGlobals.getInstance();
+ File satelliteAccessControlFile = phoneGlobals.getDir(
+ SATELLITE_ACCESS_CONTROL_DATA_DIR, Context.MODE_PRIVATE);
+ if (!satelliteAccessControlFile.exists()) {
+ return null;
+ }
+
+ Path satelliteAccessControlFileDir = satelliteAccessControlFile.toPath();
+ Path configUpdaterSatS2FilePath = satelliteAccessControlFileDir.resolve(
+ CONFIG_UPDATER_S2_CELL_FILE_NAME);
+ return configUpdaterSatS2FilePath.toFile();
+ }
+
+ private boolean isS2CellFileValid(@NonNull File s2CellFile) {
+ try {
+ SatelliteOnDeviceAccessController satelliteOnDeviceAccessController =
+ SatelliteOnDeviceAccessController.create(s2CellFile);
+ int s2Level = satelliteOnDeviceAccessController.getS2Level();
+ if (s2Level < MIN_S2_LEVEL || s2Level > MAX_S2_LEVEL) {
+ loge("isS2CellFileValid: invalid s2 level = " + s2Level);
+ satelliteOnDeviceAccessController.close();
+ return false;
+ }
+ satelliteOnDeviceAccessController.close();
+ } catch (Exception ex) {
+ loge("isS2CellFileValid: Got exception in reading the file, ex=" + ex);
+ return false;
+ }
+ return true;
+ }
+
+ private void cleanUpCtsResources() {
+ if (mCtsSatS2FilePath != null) {
+ try {
+ Files.delete(mCtsSatS2FilePath);
+ } catch (IOException ex) {
+ loge("cleanUpCtsResources: ex=" + ex);
+ }
+ }
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected long getElapsedRealtimeNanos() {
+ return SystemClock.elapsedRealtimeNanos();
+ }
+
+ /**
+ * @param countryCodes list of country code (two letters based on the ISO 3166-1).
+ * @return {@code true} if the countryCode is valid {@code false} otherwise.
+ */
+ private boolean isValidCountryCodes(@Nullable List<String> countryCodes) {
+ if (countryCodes == null || countryCodes.isEmpty()) {
+ return false;
+ }
+ for (String countryCode : countryCodes) {
+ if (!TelephonyUtils.isValidCountryCode(countryCode)) {
+ loge("invalid country code : " + countryCode);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private boolean updateSharedPreferencesCountryCodes(
+ @NonNull Context context, @NonNull List<String> value) {
+ if (mSharedPreferences == null) {
+ logd("updateSharedPreferencesCountryCodes: mSharedPreferences is null");
+ initSharedPreferences(context);
+ }
+ if (mSharedPreferences == null) {
+ loge("updateSharedPreferencesCountryCodes: mSharedPreferences is null");
+ return false;
+ }
+ try {
+ mSharedPreferences.edit().putStringSet(
+ CONFIG_UPDATER_SATELLITE_COUNTRY_CODES_KEY, new HashSet<>(value)).apply();
+ return true;
+ } catch (Exception ex) {
+ loge("updateSharedPreferencesCountryCodes error : " + ex);
+ return false;
+ }
+ }
+
+ private boolean updateSharedPreferencesIsAllowAccessControl(
+ @NonNull Context context, boolean value) {
+ if (mSharedPreferences == null) {
+ logd("updateSharedPreferencesIsAllowAccessControl: mSharedPreferences is null");
+ initSharedPreferences(context);
+ }
+ if (mSharedPreferences == null) {
+ loge("updateSharedPreferencesIsAllowAccessControl: mSharedPreferences is null");
+ return false;
+ }
+ try {
+ mSharedPreferences.edit().putBoolean(
+ CONFIG_UPDATER_SATELLITE_IS_ALLOW_ACCESS_CONTROL_KEY,
+ value).apply();
+ return true;
+ } catch (Exception ex) {
+ loge("updateSharedPreferencesAllowRegion : " + ex);
+ return false;
+ }
+ }
+
+ /**
+ * Update country codes and S2CellFile with the new data from ConfigUpdater
+ */
+ private void updateSatelliteConfigData(Context context) {
+ logd("updateSatelliteConfigData");
+
+ SatelliteConfig satelliteConfig = mSatelliteController.getSatelliteConfig();
+ if (satelliteConfig == null) {
+ loge("satelliteConfig is null");
+ return;
+ }
+
+ List<String> satelliteCountryCodes = satelliteConfig.getDeviceSatelliteCountryCodes();
+ if (!isValidCountryCodes(satelliteCountryCodes)) {
+ logd("country codes is invalid");
+ return;
+ }
+
+ Boolean isSatelliteDataForAllowedRegion = satelliteConfig.isSatelliteDataForAllowedRegion();
+ if (isSatelliteDataForAllowedRegion == null) {
+ loge("Satellite allowed is not configured with country codes");
+ return;
+ }
+
+ File configUpdaterS2CellFile = satelliteConfig.getSatelliteS2CellFile(context);
+ if (configUpdaterS2CellFile == null || !configUpdaterS2CellFile.exists()) {
+ logd("No S2 cell file configured or the file does not exist");
+ return;
+ }
+
+ if (!isS2CellFileValid(configUpdaterS2CellFile)) {
+ loge("The configured S2 cell file is not valid");
+ return;
+ }
+
+ File localS2CellFile = copySatS2FileToLocalDirectory(configUpdaterS2CellFile);
+ if (localS2CellFile == null || !localS2CellFile.exists()) {
+ loge("Fail to copy S2 cell file to local directory");
+ return;
+ }
+
+ if (!updateSharedPreferencesCountryCodes(context, satelliteCountryCodes)) {
+ loge("Fail to copy country coeds into shared preferences");
+ localS2CellFile.delete();
+ return;
+ }
+
+ if (!updateSharedPreferencesIsAllowAccessControl(
+ context, isSatelliteDataForAllowedRegion.booleanValue())) {
+ loge("Fail to copy allow access control into shared preferences");
+ localS2CellFile.delete();
+ return;
+ }
+
+ mSatelliteS2CellFile = localS2CellFile;
+ mSatelliteCountryCodes = satelliteCountryCodes;
+ mIsSatelliteAllowAccessControl = satelliteConfig.isSatelliteDataForAllowedRegion();
+ logd("Use s2 cell file=" + mSatelliteS2CellFile.getAbsolutePath() + ", country codes="
+ + String.join(",", mSatelliteCountryCodes)
+ + ", mIsSatelliteAllowAccessControl=" + mIsSatelliteAllowAccessControl
+ + " from ConfigUpdater");
+
+ // Clean up resources so that the new config data will be used when serving new requests
+ cleanupOnDeviceAccessControllerResources();
+ }
+
+ private void loadOverlayConfigs(@NonNull Context context) {
+ mSatelliteCountryCodes = getSatelliteCountryCodesFromOverlayConfig(context);
+ mIsSatelliteAllowAccessControl = getSatelliteAccessAllowFromOverlayConfig(context);
+ String satelliteS2CellFileName = getSatelliteS2CellFileFromOverlayConfig(context);
+ mSatelliteS2CellFile = TextUtils.isEmpty(satelliteS2CellFileName)
+ ? null : new File(satelliteS2CellFileName);
+ if (mSatelliteS2CellFile != null && !mSatelliteS2CellFile.exists()) {
+ loge("The satellite S2 cell file " + satelliteS2CellFileName + " does not exist");
+ mSatelliteS2CellFile = null;
+ }
+ mLocationFreshDurationNanos = getSatelliteLocationFreshDurationFromOverlayConfig(context);
+ }
+
+ private void loadConfigUpdaterConfigs() {
+ if (mSharedPreferences == null) {
+ loge("loadConfigUpdaterConfigs : mSharedPreferences is null");
+ return;
+ }
+
+ Set<String> countryCodes =
+ mSharedPreferences.getStringSet(CONFIG_UPDATER_SATELLITE_COUNTRY_CODES_KEY, null);
+
+ if (countryCodes == null || countryCodes.isEmpty()) {
+ loge("config updater country codes are either null or empty");
+ return;
+ }
+
+ boolean isSatelliteAllowAccessControl =
+ mSharedPreferences.getBoolean(
+ CONFIG_UPDATER_SATELLITE_IS_ALLOW_ACCESS_CONTROL_KEY, true);
+
+ File s2CellFile = getConfigUpdaterSatS2CellFileFromLocalDirectory();
+ if (s2CellFile == null) {
+ loge("s2CellFile is null");
+ return;
+ }
+
+ logd("use config updater config data");
+ mSatelliteS2CellFile = s2CellFile;
+ mSatelliteCountryCodes = countryCodes.stream().collect(Collectors.toList());
+ mIsSatelliteAllowAccessControl = isSatelliteAllowAccessControl;
+ }
+
+ private long getLocationFreshDurationNanos() {
+ synchronized (mLock) {
+ if (mIsOverlayConfigOverridden) {
+ return mOverriddenLocationFreshDurationNanos;
+ }
+ return mLocationFreshDurationNanos;
+ }
+ }
+
+ @NonNull
+ private List<String> getSatelliteCountryCodes() {
+ synchronized (mLock) {
+ if (mIsOverlayConfigOverridden) {
+ return mOverriddenSatelliteCountryCodes;
+ }
+ return mSatelliteCountryCodes;
+ }
+ }
+
+ @Nullable
+ private File getSatelliteS2CellFile() {
+ synchronized (mLock) {
+ if (mIsOverlayConfigOverridden) {
+ return mOverriddenSatelliteS2CellFile;
+ }
+ return mSatelliteS2CellFile;
+ }
+ }
+
+ private boolean isSatelliteAllowAccessControl() {
+ synchronized (mLock) {
+ if (mIsOverlayConfigOverridden) {
+ return mOverriddenIsSatelliteAllowAccessControl;
+ }
+ return mIsSatelliteAllowAccessControl;
+ }
+ }
+
+ private void handleCmdIsSatelliteAllowedForCurrentLocation(
+ @NonNull Pair<Integer, ResultReceiver> requestArguments) {
+ synchronized (mLock) {
+ mSatelliteAllowResultReceivers.add(requestArguments.second);
+ if (mSatelliteAllowResultReceivers.size() > 1) {
+ logd("requestIsCommunicationAllowedForCurrentLocation is already being "
+ + "processed");
+ return;
+ }
+ mSatelliteController.requestIsSatelliteSupported(
+ requestArguments.first, mInternalSatelliteSupportedResultReceiver);
+ }
+ }
+
+ private void handleWaitForCurrentLocationTimedOutEvent() {
+ logd("Timed out to wait for current location");
+ synchronized (mLock) {
+ if (mLocationRequestCancellationSignal != null) {
+ mLocationRequestCancellationSignal.cancel();
+ mLocationRequestCancellationSignal = null;
+ onCurrentLocationAvailable(null);
+ } else {
+ loge("handleWaitForCurrentLocationTimedOutEvent: "
+ + "mLocationRequestCancellationSignal is null");
+ }
+ }
+ }
+
+ private void handleIsSatelliteSupportedResult(int resultCode, Bundle resultData) {
+ logd("handleIsSatelliteSupportedResult: resultCode=" + resultCode);
+ synchronized (mLock) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_SATELLITE_SUPPORTED)) {
+ boolean isSatelliteSupported = resultData.getBoolean(KEY_SATELLITE_SUPPORTED);
+ if (!isSatelliteSupported) {
+ logd("Satellite is not supported");
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED,
+ false);
+ sendSatelliteAllowResultToReceivers(resultCode, bundle);
+ } else {
+ checkSatelliteAccessRestrictionForCurrentLocation();
+ }
+ } else {
+ loge("KEY_SATELLITE_SUPPORTED does not exist.");
+ sendSatelliteAllowResultToReceivers(resultCode, resultData);
+ }
+ } else {
+ sendSatelliteAllowResultToReceivers(resultCode, resultData);
+ }
+ }
+ }
+
+ private void sendSatelliteAllowResultToReceivers(int resultCode, Bundle resultData) {
+ synchronized (mLock) {
+ for (ResultReceiver resultReceiver : mSatelliteAllowResultReceivers) {
+ resultReceiver.send(resultCode, resultData);
+ }
+ mSatelliteAllowResultReceivers.clear();
+ }
+ }
+
+ /**
+ * Telephony-internal logic to verify if satellite access is restricted at the current location.
+ */
+ private void checkSatelliteAccessRestrictionForCurrentLocation() {
+ synchronized (mLock) {
+ List<String> networkCountryIsoList = mCountryDetector.getCurrentNetworkCountryIso();
+ if (!networkCountryIsoList.isEmpty()) {
+ logd("Use current network country codes=" + String.join(", ",
+ networkCountryIsoList));
+
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED,
+ isSatelliteAccessAllowedForLocation(networkCountryIsoList));
+ sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle);
+ } else {
+ if (shouldUseOnDeviceAccessController()) {
+ // This will be an asynchronous check when it needs to wait for the current
+ // location from location service
+ checkSatelliteAccessRestrictionUsingOnDeviceData();
+ } else {
+ // This is always a synchronous check
+ checkSatelliteAccessRestrictionUsingCachedCountryCodes();
+ }
+ }
+ }
+ }
+
+ /**
+ * This function synchronously checks if satellite is allowed at current location using cached
+ * country codes.
+ */
+ private void checkSatelliteAccessRestrictionUsingCachedCountryCodes() {
+ Pair<String, Long> locationCountryCodeInfo =
+ mCountryDetector.getCachedLocationCountryIsoInfo();
+ Map<String, Long> networkCountryCodeInfoMap =
+ mCountryDetector.getCachedNetworkCountryIsoInfo();
+ List<String> countryCodeList;
+
+ // Check if the cached location country code's timestamp is newer than all cached network
+ // country codes
+ if (!TextUtils.isEmpty(locationCountryCodeInfo.first) && isGreaterThanAll(
+ locationCountryCodeInfo.second, networkCountryCodeInfoMap.values())) {
+ // Use cached location country code
+ countryCodeList = Arrays.asList(locationCountryCodeInfo.first);
+ } else {
+ // Use cached network country codes
+ countryCodeList = networkCountryCodeInfoMap.keySet().stream().toList();
+ }
+ logd("Use cached country codes=" + String.join(", ", countryCodeList));
+
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED,
+ isSatelliteAccessAllowedForLocation(countryCodeList));
+ sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle);
+ }
+
+ /**
+ * This function asynchronously checks if satellite is allowed at the current location using
+ * on-device data. Asynchronous check happens when it needs to wait for the current location
+ * from location service.
+ */
+ private void checkSatelliteAccessRestrictionUsingOnDeviceData() {
+ synchronized (mLock) {
+ logd("Use on-device data");
+ if (mFreshLastKnownLocation != null) {
+ checkSatelliteAccessRestrictionForLocation(mFreshLastKnownLocation);
+ mFreshLastKnownLocation = null;
+ } else {
+ Location freshLastKnownLocation = getFreshLastKnownLocation();
+ if (freshLastKnownLocation != null) {
+ checkSatelliteAccessRestrictionForLocation(freshLastKnownLocation);
+ } else {
+ queryCurrentLocation();
+ }
+ }
+ }
+ }
+
+ private void queryCurrentLocation() {
+ synchronized (mLock) {
+ if (mLocationRequestCancellationSignal != null) {
+ logd("Request for current location was already sent to LocationManager");
+ return;
+ }
+ mLocationRequestCancellationSignal = new CancellationSignal();
+ mLocationManager.getCurrentLocation(LocationManager.GPS_PROVIDER,
+ new LocationRequest.Builder(0)
+ .setQuality(LocationRequest.QUALITY_HIGH_ACCURACY)
+ .setLocationSettingsIgnored(true)
+ .build(),
+ mLocationRequestCancellationSignal, this::post,
+ this::onCurrentLocationAvailable);
+ startWaitForCurrentLocationTimer();
+ }
+ }
+
+ private void onCurrentLocationAvailable(@Nullable Location location) {
+ logd("onCurrentLocationAvailable " + (location != null));
+ synchronized (mLock) {
+ stopWaitForCurrentLocationTimer();
+ mLocationRequestCancellationSignal = null;
+ if (location != null) {
+ checkSatelliteAccessRestrictionForLocation(location);
+ } else {
+ checkSatelliteAccessRestrictionUsingCachedCountryCodes();
+ }
+ }
+ }
+
+ private void checkSatelliteAccessRestrictionForLocation(@NonNull Location location) {
+ synchronized (mLock) {
+ try {
+ SatelliteOnDeviceAccessController.LocationToken locationToken =
+ SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ location.getLatitude(),
+ location.getLongitude(), mS2Level);
+ boolean satelliteAllowed;
+ if (mCachedAccessRestrictionMap.containsKey(locationToken)) {
+ satelliteAllowed = mCachedAccessRestrictionMap.get(locationToken);
+ } else {
+ if (!initSatelliteOnDeviceAccessController()) {
+ loge("Failed to init SatelliteOnDeviceAccessController");
+ checkSatelliteAccessRestrictionUsingCachedCountryCodes();
+ return;
+ }
+ satelliteAllowed = mSatelliteOnDeviceAccessController
+ .isSatCommunicationAllowedAtLocation(locationToken);
+ updateCachedAccessRestrictionMap(locationToken, satelliteAllowed);
+ }
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, satelliteAllowed);
+ sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle);
+ } catch (Exception ex) {
+ loge("checkSatelliteAccessRestrictionForLocation: ex=" + ex);
+ reportAnomaly(UUID_ON_DEVICE_LOOKUP_EXCEPTION,
+ "On-device satellite lookup exception");
+ checkSatelliteAccessRestrictionUsingCachedCountryCodes();
+ }
+ }
+ }
+
+ private void updateCachedAccessRestrictionMap(
+ @NonNull SatelliteOnDeviceAccessController.LocationToken locationToken,
+ boolean satelliteAllowed) {
+ synchronized (mLock) {
+ mCachedAccessRestrictionMap.put(locationToken, satelliteAllowed);
+ }
+ }
+
+ private boolean isGreaterThanAll(
+ long comparedItem, @NonNull Collection<Long> itemCollection) {
+ for (long item : itemCollection) {
+ if (comparedItem <= item) return false;
+ }
+ return true;
+ }
+
+ private boolean isSatelliteAccessAllowedForLocation(
+ @NonNull List<String> networkCountryIsoList) {
+ if (isSatelliteAllowAccessControl()) {
+ // The current country is unidentified, we're uncertain and thus returning false
+ if (networkCountryIsoList.isEmpty()) {
+ return false;
+ }
+
+ // In case of allowed list, satellite is allowed if all country codes are be in the
+ // allowed list
+ return getSatelliteCountryCodes().containsAll(networkCountryIsoList);
+ } else {
+ // No country is barred, thus returning true
+ if (getSatelliteCountryCodes().isEmpty()) {
+ return true;
+ }
+
+ // The current country is unidentified, we're uncertain and thus returning false
+ if (networkCountryIsoList.isEmpty()) {
+ return false;
+ }
+
+ // In case of disallowed list, if any country code is in the list, satellite will be
+ // disallowed
+ for (String countryCode : networkCountryIsoList) {
+ if (getSatelliteCountryCodes().contains(countryCode)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ private boolean shouldUseOnDeviceAccessController() {
+ if (getSatelliteS2CellFile() == null) {
+ return false;
+ }
+
+ if (isInEmergency() || mLocationManager.isLocationEnabled()) {
+ return true;
+ }
+
+ Location freshLastKnownLocation = getFreshLastKnownLocation();
+ if (freshLastKnownLocation != null) {
+ synchronized (mLock) {
+ mFreshLastKnownLocation = freshLastKnownLocation;
+ }
+ return true;
+ } else {
+ synchronized (mLock) {
+ mFreshLastKnownLocation = null;
+ }
+ }
+ return false;
+ }
+
+ @Nullable
+ private Location getFreshLastKnownLocation() {
+ Location lastKnownLocation = getLastKnownLocation();
+ if (lastKnownLocation != null) {
+ long lastKnownLocationAge =
+ getElapsedRealtimeNanos() - lastKnownLocation.getElapsedRealtimeNanos();
+ if (lastKnownLocationAge <= getLocationFreshDurationNanos()) {
+ return lastKnownLocation;
+ }
+ }
+ return null;
+ }
+
+ private boolean isInEmergency() {
+ // Check if emergency call is ongoing
+ if (mTelecomManager.isInEmergencyCall()) {
+ return true;
+ }
+ // Check if the device is in emergency callback mode
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (phone.isInEcm()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Nullable
+ private Location getLastKnownLocation() {
+ Location result = null;
+ for (String provider : mLocationManager.getProviders(true)) {
+ Location location = mLocationManager.getLastKnownLocation(provider);
+ if (location != null && (result == null
+ || result.getElapsedRealtimeNanos() < location.getElapsedRealtimeNanos())) {
+ result = location;
+ }
+ }
+ return result;
+ }
+
+ private void initSharedPreferences(@NonNull Context context) {
+ try {
+ mSharedPreferences =
+ context.getSharedPreferences(SATELLITE_SHARED_PREF, Context.MODE_PRIVATE);
+ } catch (Exception e) {
+ loge("Cannot get default shared preferences: " + e);
+ }
+ }
+
+ /**
+ * @return {@code true} if successfully initialize the {@link SatelliteOnDeviceAccessController}
+ * instance, {@code false} otherwise.
+ * @throws IllegalStateException in case of getting any exception in creating the
+ * {@link SatelliteOnDeviceAccessController} instance and the
+ * device is using a user build.
+ */
+ private boolean initSatelliteOnDeviceAccessController() throws IllegalStateException {
+ synchronized (mLock) {
+ if (getSatelliteS2CellFile() == null) return false;
+
+ // mSatelliteOnDeviceAccessController was already initialized successfully
+ if (mSatelliteOnDeviceAccessController != null) {
+ restartKeepOnDeviceAccessControllerResourcesTimer();
+ return true;
+ }
+
+ try {
+ mSatelliteOnDeviceAccessController =
+ SatelliteOnDeviceAccessController.create(getSatelliteS2CellFile());
+ restartKeepOnDeviceAccessControllerResourcesTimer();
+ mS2Level = mSatelliteOnDeviceAccessController.getS2Level();
+ logd("mS2Level=" + mS2Level);
+ } catch (Exception ex) {
+ loge("Got exception in creating an instance of SatelliteOnDeviceAccessController,"
+ + " ex=" + ex + ", sat s2 file="
+ + getSatelliteS2CellFile().getAbsolutePath());
+ reportAnomaly(UUID_CREATE_ON_DEVICE_ACCESS_CONTROLLER_EXCEPTION,
+ "Exception in creating on-device satellite access controller");
+ mSatelliteOnDeviceAccessController = null;
+ if (!mIsOverlayConfigOverridden) {
+ mSatelliteS2CellFile = null;
+ }
+ return false;
+ }
+ return true;
+ }
+ }
+
+ private void cleanupOnDeviceAccessControllerResources() {
+ synchronized (mLock) {
+ logd("cleanupOnDeviceAccessControllerResources="
+ + (mSatelliteOnDeviceAccessController != null));
+ if (mSatelliteOnDeviceAccessController != null) {
+ try {
+ mSatelliteOnDeviceAccessController.close();
+ } catch (Exception ex) {
+ loge("cleanupOnDeviceAccessControllerResources: ex=" + ex);
+ }
+ mSatelliteOnDeviceAccessController = null;
+ stopKeepOnDeviceAccessControllerResourcesTimer();
+ }
+ }
+ }
+
+ private static boolean getSatelliteAccessAllowFromOverlayConfig(@NonNull Context context) {
+ Boolean accessAllowed = null;
+ try {
+ accessAllowed = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_oem_enabled_satellite_access_allow);
+ } catch (Resources.NotFoundException ex) {
+ loge("getSatelliteAccessAllowFromOverlayConfig: got ex=" + ex);
+ }
+ if (accessAllowed == null && isMockModemAllowed()) {
+ logd("getSatelliteAccessAllowFromOverlayConfig: Read "
+ + "config_oem_enabled_satellite_access_allow from device config");
+ accessAllowed = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TELEPHONY,
+ "config_oem_enabled_satellite_access_allow", DEFAULT_SATELLITE_ACCESS_ALLOW);
+ }
+ if (accessAllowed == null) {
+ logd("Use default satellite access allow=true control");
+ accessAllowed = true;
+ }
+ return accessAllowed;
+ }
+
+ @Nullable
+ private static String getSatelliteS2CellFileFromOverlayConfig(@NonNull Context context) {
+ String s2CellFile = null;
+ try {
+ s2CellFile = context.getResources().getString(
+ com.android.internal.R.string.config_oem_enabled_satellite_s2cell_file);
+ } catch (Resources.NotFoundException ex) {
+ loge("getSatelliteS2CellFileFromOverlayConfig: got ex=" + ex);
+ }
+ if (TextUtils.isEmpty(s2CellFile) && isMockModemAllowed()) {
+ logd("getSatelliteS2CellFileFromOverlayConfig: Read "
+ + "config_oem_enabled_satellite_s2cell_file from device config");
+ s2CellFile = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY,
+ "config_oem_enabled_satellite_s2cell_file", null);
+ }
+ logd("s2CellFile=" + s2CellFile);
+ return s2CellFile;
+ }
+
+ @NonNull
+ private static List<String> getSatelliteCountryCodesFromOverlayConfig(
+ @NonNull Context context) {
+ String[] countryCodes = readStringArrayFromOverlayConfig(context,
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes);
+ if (countryCodes.length == 0 && isMockModemAllowed()) {
+ logd("getSatelliteCountryCodesFromOverlayConfig: Read "
+ + "config_oem_enabled_satellite_country_codes from device config");
+ String countryCodesStr = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY,
+ "config_oem_enabled_satellite_country_codes", "");
+ countryCodes = countryCodesStr.split(",");
+ }
+ return Arrays.stream(countryCodes)
+ .map(x -> x.toUpperCase(Locale.US))
+ .collect(Collectors.toList());
+ }
+
+ @NonNull
+ private static String[] readStringArrayFromOverlayConfig(
+ @NonNull Context context, @ArrayRes int id) {
+ String[] strArray = null;
+ try {
+ strArray = context.getResources().getStringArray(id);
+ } catch (Resources.NotFoundException ex) {
+ loge("readStringArrayFromOverlayConfig: id= " + id + ", ex=" + ex);
+ }
+ if (strArray == null) {
+ strArray = new String[0];
+ }
+ return strArray;
+ }
+
+ private static long getSatelliteLocationFreshDurationFromOverlayConfig(
+ @NonNull Context context) {
+ Integer freshDuration = null;
+ try {
+ freshDuration = context.getResources().getInteger(com.android.internal.R.integer
+ .config_oem_enabled_satellite_location_fresh_duration);
+ } catch (Resources.NotFoundException ex) {
+ loge("getSatelliteLocationFreshDurationFromOverlayConfig: got ex=" + ex);
+ }
+ if (freshDuration == null && isMockModemAllowed()) {
+ logd("getSatelliteLocationFreshDurationFromOverlayConfig: Read "
+ + "config_oem_enabled_satellite_location_fresh_duration from device config");
+ freshDuration = DeviceConfig.getInt(DeviceConfig.NAMESPACE_TELEPHONY,
+ "config_oem_enabled_satellite_location_fresh_duration",
+ DEFAULT_LOCATION_FRESH_DURATION_SECONDS);
+ }
+ if (freshDuration == null) {
+ logd("Use default satellite location fresh duration="
+ + DEFAULT_LOCATION_FRESH_DURATION_SECONDS);
+ freshDuration = DEFAULT_LOCATION_FRESH_DURATION_SECONDS;
+ }
+ return TimeUnit.SECONDS.toNanos(freshDuration);
+ }
+
+ private void startWaitForCurrentLocationTimer() {
+ synchronized (mLock) {
+ if (hasMessages(EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT)) {
+ logw("WaitForCurrentLocationTimer is already started");
+ removeMessages(EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT);
+ }
+ sendEmptyMessageDelayed(EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT,
+ WAIT_FOR_CURRENT_LOCATION_TIMEOUT_MILLIS);
+ }
+ }
+
+ private void stopWaitForCurrentLocationTimer() {
+ synchronized (mLock) {
+ removeMessages(EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT);
+ }
+ }
+
+ private void restartKeepOnDeviceAccessControllerResourcesTimer() {
+ synchronized (mLock) {
+ if (hasMessages(EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT)) {
+ logd("KeepOnDeviceAccessControllerResourcesTimer is already started. "
+ + "Restarting it...");
+ removeMessages(EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT);
+ }
+ sendEmptyMessageDelayed(EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT,
+ KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT_MILLIS);
+ }
+ }
+
+ private void stopKeepOnDeviceAccessControllerResourcesTimer() {
+ synchronized (mLock) {
+ removeMessages(EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT);
+ }
+ }
+
+ private void reportAnomaly(@NonNull String uuid, @NonNull String log) {
+ loge(log);
+ AnomalyReporter.reportAnomaly(UUID.fromString(uuid), log);
+ }
+
+ private static boolean isMockModemAllowed() {
+ return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false)
+ || SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false));
}
/**
* Posts the specified command to be executed on the main thread and returns immediately.
*
- * @param command command to be executed on the main thread
+ * @param command command to be executed on the main thread
* @param argument additional parameters required to perform of the operation
*/
private void sendRequestAsync(int command, @NonNull Object argument) {
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteOnDeviceAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteOnDeviceAccessController.java
index 9292f33..520699f 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteOnDeviceAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteOnDeviceAccessController.java
@@ -45,11 +45,12 @@
/**
* Returns a token for a given location. See {@link LocationToken} for details.
- *
- * @throws IOException in the unlikely event of errors when reading the underlying file
*/
- public abstract LocationToken createLocationTokenForLatLng(double latDegrees, double lngDegrees)
- throws IOException;
+ public static LocationToken createLocationTokenForLatLng(double latDegrees, double lngDegrees,
+ int s2Level) {
+ return S2RangeSatelliteOnDeviceAccessController
+ .createLocationTokenForLatLng(latDegrees, lngDegrees, s2Level);
+ }
/**
* Returns {@code true} if the satellite communication is allowed at the provided location,
@@ -61,6 +62,11 @@
throws IOException;
/**
+ * Returns the S2 level of the file.
+ */
+ public abstract int getS2Level();
+
+ /**
* A class that represents an area with the same value. Two locations with tokens that
* {@link #equals(Object) equal each other} will definitely return the same value.
*
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApi.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApi.java
new file mode 100644
index 0000000..6c55709
--- /dev/null
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApi.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2024 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.satellite.entitlement;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+
+import com.android.libraries.entitlement.CarrierConfig;
+import com.android.libraries.entitlement.ServiceEntitlement;
+import com.android.libraries.entitlement.ServiceEntitlementException;
+import com.android.libraries.entitlement.ServiceEntitlementRequest;
+
+/**
+ * Class that sends an HTTP request to the entitlement server and processes the response to check
+ * whether satellite service can be activated.
+ * @hide
+ */
+public class SatelliteEntitlementApi {
+ private static final String DEFAULT_APP_NAME = "androidSatmode";
+ @NonNull
+ private final ServiceEntitlement mServiceEntitlement;
+ private final Context mContext;
+ private final PersistableBundle mCarrierConfig;
+
+ public SatelliteEntitlementApi(@NonNull Context context,
+ @NonNull PersistableBundle carrierConfig, @NonNull int subId) {
+ mContext = context;
+ mServiceEntitlement = new ServiceEntitlement(mContext,
+ getCarrierConfigFromEntitlementServerUrl(carrierConfig), subId);
+ mCarrierConfig = carrierConfig;
+ }
+
+ /**
+ * Returns satellite entitlement result from the entitlement server.
+ * @return The SatelliteEntitlementResult
+ */
+ public SatelliteEntitlementResult checkEntitlementStatus() throws ServiceEntitlementException {
+ ServiceEntitlementRequest.Builder requestBuilder = ServiceEntitlementRequest.builder();
+ requestBuilder.setAcceptContentType(ServiceEntitlementRequest.ACCEPT_CONTENT_TYPE_JSON);
+ requestBuilder.setAppName(getSatelliteEntitlementAppName(mCarrierConfig));
+ ServiceEntitlementRequest request = requestBuilder.build();
+
+ String response = mServiceEntitlement.queryEntitlementStatus(
+ ServiceEntitlement.APP_SATELLITE_ENTITLEMENT, request);
+ SatelliteEntitlementResponse satelliteEntitlementResponse =
+ new SatelliteEntitlementResponse(response);
+ return new SatelliteEntitlementResult(satelliteEntitlementResponse.getEntitlementStatus(),
+ satelliteEntitlementResponse.getPlmnAllowed(),
+ satelliteEntitlementResponse.getPlmnBarredList());
+ }
+
+ @NonNull
+ private CarrierConfig getCarrierConfigFromEntitlementServerUrl(
+ @NonNull PersistableBundle carrierConfig) {
+ String entitlementServiceUrl = carrierConfig.getString(
+ CarrierConfigManager.ImsServiceEntitlement.KEY_ENTITLEMENT_SERVER_URL_STRING,
+ "");
+ return CarrierConfig.builder().setServerUrl(entitlementServiceUrl).build();
+ }
+
+ @NonNull
+ private String getSatelliteEntitlementAppName(@NonNull PersistableBundle carrierConfig) {
+ return carrierConfig.getString(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_APP_NAME_STRING, DEFAULT_APP_NAME);
+ }
+}
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
new file mode 100644
index 0000000..d193a7d
--- /dev/null
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
@@ -0,0 +1,544 @@
+/*
+ * Copyright (C) 2024 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.satellite.entitlement;
+
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_ENABLED;
+
+import static java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME;
+import static java.time.temporal.ChronoUnit.SECONDS;
+
+import android.annotation.NonNull;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
+
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.SatelliteController;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.libraries.entitlement.ServiceEntitlementException;
+
+import java.time.Instant;
+import java.time.format.DateTimeParseException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This class query the entitlement server to receive values for satellite services and passes the
+ * response to the {@link com.android.internal.telephony.satellite.SatelliteController}.
+ * @hide
+ */
+public class SatelliteEntitlementController extends Handler {
+ private static final String TAG = "SatelliteEntitlementController";
+ @NonNull private static SatelliteEntitlementController sInstance;
+ /** Message code used in handleMessage() */
+ private static final int CMD_START_QUERY_ENTITLEMENT = 1;
+ private static final int CMD_RETRY_QUERY_ENTITLEMENT = 2;
+ private static final int CMD_STOP_RETRY_QUERY_ENTITLEMENT = 3;
+
+ /** Retry on next trigger event. */
+ private static final int HTTP_RESPONSE_500 = 500;
+ /** Retry after the time specified in the “Retry-After” header. After retry count doesn't exceed
+ * MAX_RETRY_COUNT. */
+ private static final int HTTP_RESPONSE_503 = 503;
+ /** Default query refresh time is 1 month. */
+
+ private static final int DEFAULT_QUERY_REFRESH_DAYS = 30;
+ private static final long INITIAL_DELAY_MILLIS = TimeUnit.MINUTES.toMillis(10); // 10 min
+ private static final long MAX_DELAY_MILLIS = TimeUnit.DAYS.toMillis(5); // 5 days
+ private static final int MULTIPLIER = 2;
+ private static final int MAX_RETRY_COUNT = 5;
+ @NonNull private final SubscriptionManagerService mSubscriptionManagerService;
+ @NonNull private final CarrierConfigManager mCarrierConfigManager;
+ @NonNull private final CarrierConfigManager.CarrierConfigChangeListener
+ mCarrierConfigChangeListener;
+ @NonNull private final ConnectivityManager mConnectivityManager;
+ @NonNull private final ConnectivityManager.NetworkCallback mNetworkCallback;
+ @NonNull private final BroadcastReceiver mReceiver;
+ @NonNull private final Context mContext;
+ private final Object mLock = new Object();
+ /** Map key : subId, value : ExponentialBackoff. */
+ private Map<Integer, ExponentialBackoff> mExponentialBackoffPerSub = new HashMap<>();
+ /** Map key : subId, value : SatelliteEntitlementResult. */
+ private Map<Integer, SatelliteEntitlementResult> mSatelliteEntitlementResultPerSub =
+ new HashMap<>();
+ /** Map key : subId, value : the last query time to millis. */
+ private Map<Integer, Long> mLastQueryTimePerSub = new HashMap<>();
+ /** Map key : subId, value : Count the number of retries caused by the 'ExponentialBackoff' and
+ * '503 error case with the Retry-After header'. */
+ private Map<Integer, Integer> mRetryCountPerSub = new HashMap<>();
+
+ /**
+ * Create the SatelliteEntitlementController singleton instance.
+ * @param context The Context to use to create the SatelliteEntitlementController.
+ * @param featureFlags The feature flag.
+ */
+ public static void make(@NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (!featureFlags.carrierEnabledSatelliteFlag()) {
+ logd("carrierEnabledSatelliteFlag is disabled. don't created this.");
+ return;
+ }
+ if (sInstance == null) {
+ HandlerThread handlerThread = new HandlerThread(TAG);
+ handlerThread.start();
+ sInstance =
+ new SatelliteEntitlementController(context, handlerThread.getLooper());
+ }
+ }
+
+ /**
+ * Create a SatelliteEntitlementController to request query to the entitlement server for
+ * satellite services and receive responses.
+ *
+ * @param context The Context for the SatelliteEntitlementController.
+ * @param looper The looper for the handler. It does not run on main thread.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public SatelliteEntitlementController(@NonNull Context context, @NonNull Looper looper) {
+ super(looper);
+ mContext = context;
+ mSubscriptionManagerService = SubscriptionManagerService.getInstance();
+ mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
+ mCarrierConfigChangeListener = (slotIndex, subId, carrierId, specificCarrierId) ->
+ handleCarrierConfigChanged(slotIndex, subId, carrierId, specificCarrierId);
+ mCarrierConfigManager.registerCarrierConfigChangeListener(this::post,
+ mCarrierConfigChangeListener);
+ mConnectivityManager = context.getSystemService(ConnectivityManager.class);
+ mNetworkCallback = new ConnectivityManager.NetworkCallback() {
+ @Override
+ public void onAvailable(Network network) {
+ handleInternetConnected();
+ }
+
+ @Override
+ public void onLost(Network network) {
+ handleInternetDisconnected();
+ }
+ };
+ NetworkRequest networkrequest = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();
+ mConnectivityManager.registerNetworkCallback(networkrequest, mNetworkCallback, this);
+ mReceiver = new SatelliteEntitlementControllerReceiver();
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ context.registerReceiver(mReceiver, intentFilter);
+ }
+
+ @Override
+ public void handleMessage(@NonNull Message msg) {
+ switch (msg.what) {
+ case CMD_START_QUERY_ENTITLEMENT:
+ handleCmdStartQueryEntitlement();
+ break;
+ case CMD_RETRY_QUERY_ENTITLEMENT:
+ handleCmdRetryQueryEntitlement(msg.arg1);
+ break;
+ case CMD_STOP_RETRY_QUERY_ENTITLEMENT:
+ stopExponentialBackoff(msg.arg1);
+ break;
+ default:
+ logd("do not used this message");
+ }
+ }
+
+ private void handleCarrierConfigChanged(int slotIndex, int subId, int carrierId,
+ int specificCarrierId) {
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return;
+ }
+ logd("handleCarrierConfigChanged(): slotIndex(" + slotIndex + "), subId("
+ + subId + "), carrierId(" + carrierId + "), specificCarrierId("
+ + specificCarrierId + ")");
+
+ sendEmptyMessage(CMD_START_QUERY_ENTITLEMENT);
+ }
+
+ private class SatelliteEntitlementControllerReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
+ boolean airplaneMode = intent.getBooleanExtra("state", false);
+ handleAirplaneModeChange(airplaneMode);
+ }
+ }
+ }
+
+ private void handleAirplaneModeChange(boolean airplaneMode) {
+ if (!airplaneMode) {
+ resetEntitlementQueryCounts(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ }
+ }
+
+ private boolean isInternetConnected() {
+ Network activeNetwork = mConnectivityManager.getActiveNetwork();
+ NetworkCapabilities networkCapabilities =
+ mConnectivityManager.getNetworkCapabilities(activeNetwork);
+ // TODO b/319780796 Add checking if it is not a satellite.
+ return networkCapabilities != null
+ && networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ }
+
+ private void handleInternetConnected() {
+ sendEmptyMessage(CMD_START_QUERY_ENTITLEMENT);
+ }
+
+ private void handleInternetDisconnected() {
+ mExponentialBackoffPerSub.forEach((key, value) -> {
+ Message message = obtainMessage();
+ message.what = CMD_STOP_RETRY_QUERY_ENTITLEMENT;
+ message.arg1 = key;
+ sendMessage(message);
+ });
+ }
+
+ /**
+ * Check if the device can request to entitlement server (if there is an internet connection and
+ * if the throttle time has passed since the last request), and then pass the response to
+ * SatelliteController if the response is received.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public void handleCmdStartQueryEntitlement() {
+ if (!isInternetConnected()) {
+ logd("Internet disconnected");
+ return;
+ }
+
+ for (int subId : mSubscriptionManagerService.getActiveSubIdList(true)) {
+ if (!shouldQueryEntitlement(subId)) {
+ return;
+ }
+
+ // Check the satellite service query result from the entitlement server for the
+ // satellite service.
+ try {
+ mSatelliteEntitlementResultPerSub.remove(subId);
+ mSatelliteEntitlementResultPerSub.put(subId, getSatelliteEntitlementApi(
+ subId).checkEntitlementStatus());
+ } catch (ServiceEntitlementException e) {
+ loge(e.toString());
+ if (!isInternetConnected()) {
+ logd("handleCmdStartQueryEntitlement: disconnected. " + e);
+ return;
+ }
+ if (shouldHandleErrorResponse(e, subId)) {
+ logd("handleCmdStartQueryEntitlement: handle response.");
+ return;
+ }
+ startExponentialBackoff(subId);
+ return;
+ }
+ queryCompleted(subId);
+ }
+ }
+
+ /** When airplane mode changes from on to off, reset the values required to start the first
+ * query. */
+ private void resetEntitlementQueryCounts(String event) {
+ logd("resetEntitlementQueryCounts: " + event);
+ mLastQueryTimePerSub = new HashMap<>();
+ mExponentialBackoffPerSub = new HashMap<>();
+ mRetryCountPerSub = new HashMap<>();
+ }
+
+ /**
+ * If the HTTP response does not receive a body containing the 200 ok with sat mode
+ * configuration,
+ *
+ * 1. If the 500 response received, then no more retry until next event occurred.
+ * 2. If the 503 response with Retry-After header received, then the query is retried until
+ * MAX_RETRY_COUNT.
+ * 3. If other response or exception is occurred, then the query is retried until
+ * MAX_RETRY_COUNT is reached using the ExponentialBackoff.
+ */
+ private void handleCmdRetryQueryEntitlement(int subId) {
+ logd("handleCmdRetryQueryEntitlement: " + subId);
+ try {
+ synchronized (mLock) {
+ mSatelliteEntitlementResultPerSub.put(subId, getSatelliteEntitlementApi(
+ subId).checkEntitlementStatus());
+ }
+ } catch (ServiceEntitlementException e) {
+ if (!isInternetConnected()) {
+ logd("retryQuery: Internet disconnected. reset the retry and after the "
+ + "internet is connected then the first query is triggered." + e);
+ stopExponentialBackoff(subId);
+ return;
+ }
+ if (shouldHandleErrorResponse(e, subId)) {
+ logd("retryQuery: handle response.");
+ stopExponentialBackoff(subId);
+ return;
+ }
+ mExponentialBackoffPerSub.get(subId).notifyFailed();
+ mRetryCountPerSub.put(subId,
+ mRetryCountPerSub.getOrDefault(subId, 0) + 1);
+ logd("handleCmdRetryQueryEntitlement:" + e + "[" + subId + "] cnt="
+ + mRetryCountPerSub.getOrDefault(subId, 0) + "] Retrying in "
+ + mExponentialBackoffPerSub.get(subId).getCurrentDelay() + " ms.");
+ }
+ }
+
+ /** Only handle '500' and '503 with retry-after header' error responses received.
+ * If the 500 response is received, no retry until the next trigger event occurs.
+ * If the 503 response with Retry-After header, retry is attempted according to the value in the
+ * Retry-After header up to MAX_RETRY_COUNT.
+ * In other cases, it performs an exponential backoff process. */
+ private boolean shouldHandleErrorResponse(ServiceEntitlementException e, int subId) {
+ int responseCode = e.getHttpStatus();
+ logd("shouldHandleErrorResponse: received the " + responseCode);
+ if (responseCode == HTTP_RESPONSE_503 && e.getRetryAfter() != null
+ && !e.getRetryAfter().isEmpty()) {
+ if (mRetryCountPerSub.getOrDefault(subId, 0) >= MAX_RETRY_COUNT) {
+ logd("The 503 retry after reaching the " + MAX_RETRY_COUNT
+ + "The retry will not be attempted until the next trigger event.");
+ queryCompleted(subId);
+ return true;
+ }
+ long retryAfterSeconds = parseSecondsFromRetryAfter(e.getRetryAfter());
+ if (retryAfterSeconds == -1) {
+ logd("Unable parsing the retry-after. try to exponential backoff.");
+ return false;
+ }
+ mRetryCountPerSub.put(subId, mRetryCountPerSub.getOrDefault(subId, 0) + 1);
+ logd("[" + subId + "] cnt=" + mRetryCountPerSub.getOrDefault(subId, 0)
+ + " Retrying in " + TimeUnit.SECONDS.toMillis(retryAfterSeconds) + " sec");
+ Message message = obtainMessage();
+ message.what = CMD_RETRY_QUERY_ENTITLEMENT;
+ message.arg1 = subId;
+ sendMessageDelayed(message, TimeUnit.SECONDS.toMillis(retryAfterSeconds));
+ return true;
+ } else if (responseCode == HTTP_RESPONSE_500) {
+ logd("The retry on the next trigger event.");
+ queryCompleted(subId);
+ return true;
+ }
+ return false;
+ }
+
+ /** Parse the HTTP-date or a number of seconds in the retry-after value. */
+ private long parseSecondsFromRetryAfter(String retryAfter) {
+ try {
+ return Long.parseLong(retryAfter);
+ } catch (NumberFormatException numberFormatException) {
+ }
+
+ try {
+ return SECONDS.between(
+ Instant.now(), RFC_1123_DATE_TIME.parse(retryAfter, Instant::from));
+ } catch (DateTimeParseException dateTimeParseException) {
+ }
+
+ return -1;
+ }
+
+ private void startExponentialBackoff(int subId) {
+ stopExponentialBackoff(subId);
+ mExponentialBackoffPerSub.put(subId,
+ new ExponentialBackoff(INITIAL_DELAY_MILLIS, MAX_DELAY_MILLIS,
+ MULTIPLIER, this.getLooper(), () -> {
+ synchronized (mLock) {
+ if (mSatelliteEntitlementResultPerSub.containsKey(subId)) {
+ logd("handleCmdStartQueryEntitlement: get the response "
+ + "successfully.");
+ mExponentialBackoffPerSub.get(subId).stop();
+ queryCompleted(subId);
+ return;
+ }
+
+ if (mRetryCountPerSub.getOrDefault(subId, 0) >= MAX_RETRY_COUNT) {
+ logd("The ExponentialBackoff is stopped after reaching the "
+ + MAX_RETRY_COUNT + ". The retry don't attempted until the"
+ + " refresh time expires.");
+ mExponentialBackoffPerSub.get(subId).stop();
+ queryCompleted(subId);
+ return;
+ }
+ if (!mSatelliteEntitlementResultPerSub.containsKey(subId)) {
+ handleCmdRetryQueryEntitlement(subId);
+ }
+ }
+ }));
+ mExponentialBackoffPerSub.get(subId).start();
+ mRetryCountPerSub.put(subId, mRetryCountPerSub.getOrDefault(subId, 0) + 1);
+ logd("start ExponentialBackoff [" + mRetryCountPerSub.getOrDefault(subId, 0)
+ + "] Retrying in " + mExponentialBackoffPerSub.get(subId).getCurrentDelay()
+ + " ms.");
+ }
+
+ /** If the Internet connection is lost during the ExponentialBackoff, stop the
+ * ExponentialBackoff and reset it. */
+ private void stopExponentialBackoff(int subId) {
+ if (isExponentialBackoffInProgress(subId)) {
+ logd("stopExponentialBackoff: reset ExponentialBackoff");
+ mExponentialBackoffPerSub.get(subId).stop();
+ mExponentialBackoffPerSub.remove(subId);
+ }
+ }
+
+ /**
+ * No more query retry, update the result. If there is no response from the server, then used
+ * the default value - 'satellite disabled' and empty 'PLMN allowed list'.
+ * And then it send a delayed message to trigger the query again after A refresh day has passed.
+ */
+ private void queryCompleted(int subId) {
+ if (!mSatelliteEntitlementResultPerSub.containsKey(subId)) {
+ logd("queryCompleted: create default SatelliteEntitlementResult");
+ mSatelliteEntitlementResultPerSub.put(subId,
+ SatelliteEntitlementResult.getDefaultResult());
+ }
+
+ saveLastQueryTime(subId);
+ Message message = obtainMessage();
+ message.what = CMD_START_QUERY_ENTITLEMENT;
+ message.arg1 = subId;
+ sendMessageDelayed(message, TimeUnit.DAYS.toMillis(
+ getSatelliteEntitlementStatusRefreshDays(subId)));
+ logd("queryCompleted: updateSatelliteEntitlementStatus");
+ updateSatelliteEntitlementStatus(subId,
+ mSatelliteEntitlementResultPerSub.get(subId).getEntitlementStatus()
+ == SATELLITE_ENTITLEMENT_STATUS_ENABLED,
+ mSatelliteEntitlementResultPerSub.get(subId).getAllowedPLMNList(),
+ mSatelliteEntitlementResultPerSub.get(subId).getBarredPLMNList());
+ stopExponentialBackoff(subId);
+ mRetryCountPerSub.remove(subId);
+ }
+
+ /** Check whether there is a saved subId. Returns true if there is a saved subId,
+ * otherwise return false.*/
+ private boolean isExponentialBackoffInProgress(int subId) {
+ return mExponentialBackoffPerSub.containsKey(subId);
+ }
+
+ /**
+ * Check if the subId can query the entitlement server to get the satellite configuration.
+ */
+ private boolean shouldQueryEntitlement(int subId) {
+ if (!isSatelliteEntitlementSupported(subId)) {
+ logd("Doesn't support entitlement query for satellite.");
+ return false;
+ }
+
+ if (isExponentialBackoffInProgress(subId)) {
+ logd("In progress ExponentialBackoff.");
+ return false;
+ }
+
+ return shouldRefreshEntitlementStatus(subId);
+ }
+
+ /**
+ * Compare the last query time to the refresh time from the CarrierConfig to see if the device
+ * can query the entitlement server.
+ */
+ private boolean shouldRefreshEntitlementStatus(int subId) {
+ long lastQueryTimeMillis = getLastQueryTime(subId);
+ long refreshTimeMillis = TimeUnit.DAYS.toMillis(
+ getSatelliteEntitlementStatusRefreshDays(subId));
+ boolean isAvailable =
+ (System.currentTimeMillis() - lastQueryTimeMillis) > refreshTimeMillis;
+ if (!isAvailable) {
+ logd("query is already done. can query after " + Instant.ofEpochMilli(
+ refreshTimeMillis + lastQueryTimeMillis));
+ }
+ return isAvailable;
+ }
+
+ /**
+ * Get the SatelliteEntitlementApi.
+ *
+ * @param subId The subId of the subscription for creating SatelliteEntitlementApi
+ * @return A new SatelliteEntitlementApi object.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public SatelliteEntitlementApi getSatelliteEntitlementApi(int subId) {
+ return new SatelliteEntitlementApi(mContext, getConfigForSubId(subId), subId);
+ }
+
+ /** If there is a value stored in the cache, it is used. If there is no value stored in the
+ * cache, it is considered the first query. */
+ private long getLastQueryTime(int subId) {
+ return mLastQueryTimePerSub.getOrDefault(subId, 0L);
+ }
+
+ /** Return the satellite entitlement status refresh days from carrier config. */
+ private int getSatelliteEntitlementStatusRefreshDays(int subId) {
+ return getConfigForSubId(subId).getInt(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT,
+ DEFAULT_QUERY_REFRESH_DAYS);
+ }
+
+ /** Return the satellite entitlement supported bool from carrier config. */
+ private boolean isSatelliteEntitlementSupported(int subId) {
+ return getConfigForSubId(subId).getBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL);
+ }
+
+ @NonNull
+ private PersistableBundle getConfigForSubId(int subId) {
+ PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId,
+ CarrierConfigManager.ImsServiceEntitlement.KEY_ENTITLEMENT_SERVER_URL_STRING,
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT,
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_APP_NAME_STRING);
+ if (config == null || config.isEmpty()) {
+ config = CarrierConfigManager.getDefaultConfig();
+ }
+ return config;
+ }
+
+ private void saveLastQueryTime(int subId) {
+ long lastQueryTimeMillis = System.currentTimeMillis();
+ mLastQueryTimePerSub.put(subId, lastQueryTimeMillis);
+ }
+
+ /**
+ * Send to satelliteController for update the satellite service enabled or not and plmn Allowed
+ * list.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public void updateSatelliteEntitlementStatus(int subId, boolean enabled,
+ List<String> plmnAllowedList, List<String> plmnBarredList) {
+ SatelliteController.getInstance().onSatelliteEntitlementStatusUpdated(subId, enabled,
+ plmnAllowedList, plmnBarredList, null);
+ }
+
+ private static void logd(String log) {
+ Rlog.d(TAG, log);
+ }
+
+ private static void loge(String log) {
+ Rlog.e(TAG, log);
+ }
+}
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
new file mode 100644
index 0000000..97cb355
--- /dev/null
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2024 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.satellite.entitlement;
+
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_DISABLED;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.satellite.SatelliteNetworkInfo;
+import com.android.libraries.entitlement.ServiceEntitlement;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * This class parses whether the satellite service configuration.
+ * @hide
+ */
+public class SatelliteEntitlementResponse {
+ private static final String TAG = "SatelliteEntitlementResponse";
+
+ /** Overall status of the SatMode entitlement, stating if the satellite service can be offered
+ * on the device, and if it can be activated or not by the user. */
+ private static final String ENTITLEMENT_STATUS_KEY = "EntitlementStatus";
+ /** List of allowed PLMNs where the service can be used. */
+ private static final String PLMN_ALLOWED_KEY = "PLMNAllowed";
+ /** List of barred PLMNs where the service can’t be used. */
+ private static final String PLMN_BARRED_KEY = "PLMNBarred";
+ /** allowed PLMN-ID where the service can be used or is barred. */
+ private static final String PLMN_KEY = "PLMN";
+ /** The data plan is of the metered or un-metered type. This value is optional. */
+ private static final String DATA_PLAN_TYPE_KEY = "DataPlanType";
+
+ @SatelliteEntitlementResult.SatelliteEntitlementStatus private int mEntitlementStatus;
+
+ /**
+ * <p> Available options are :
+ * "PLMNAllowed":[{ "PLMN": "XXXXXX", “DataPlanType”: "unmetered"},
+ * {"PLMN": "XXXXXX", “DataPlanType”: "metered"},
+ * {"PLMN": "XXXXXX"}]
+ */
+ private List<SatelliteNetworkInfo> mPlmnAllowedList;
+ /**
+ * <p> Available option is :
+ * "PLMNBarred":[{"PLMN": "XXXXXX"}, {"PLMN”:"XXXXXX"}]
+ */
+ private List<String> mPlmnBarredList;
+
+ public SatelliteEntitlementResponse(String response) {
+ mEntitlementStatus = SATELLITE_ENTITLEMENT_STATUS_DISABLED;
+ mPlmnAllowedList = new ArrayList<>();
+ mPlmnBarredList = new ArrayList<>();
+ if (!TextUtils.isEmpty(response)) {
+ parsingResponse(response);
+ }
+ }
+
+ /**
+ * Get the entitlement status for the satellite service
+ * @return The satellite entitlement status
+ */
+ public int getEntitlementStatus() {
+ return mEntitlementStatus;
+ }
+
+ /**
+ * Get the PLMNAllowed from the response
+ * @return The PLMNs Allowed list. PLMN and Data Plan Type(optional).
+ */
+ public List<SatelliteNetworkInfo> getPlmnAllowed() {
+ return mPlmnAllowedList.stream().map((info) -> new SatelliteNetworkInfo(info.mPlmn,
+ info.mDataPlanType)).collect(Collectors.toList());
+ }
+
+ /**
+ * Get the PLMNBarredList from the response
+ * @return The PLMNs Barred List
+ */
+ public List<String> getPlmnBarredList() {
+ return mPlmnBarredList.stream().map(String::new).collect(Collectors.toList());
+ }
+
+ private void parsingResponse(String response) {
+ JSONObject jsonAuthResponse = null;
+ try {
+ jsonAuthResponse = new JSONObject(response);
+ if (!jsonAuthResponse.has(ServiceEntitlement.APP_SATELLITE_ENTITLEMENT)) {
+ loge("parsingResponse failed with no app");
+ return;
+ }
+ JSONObject jsonToken = jsonAuthResponse.getJSONObject(
+ ServiceEntitlement.APP_SATELLITE_ENTITLEMENT);
+ if (jsonToken.has(ENTITLEMENT_STATUS_KEY)) {
+ String entitlementStatus = jsonToken.getString(ENTITLEMENT_STATUS_KEY);
+ if (entitlementStatus == null) {
+ loge("parsingResponse EntitlementStatus is null");
+ return;
+ }
+ mEntitlementStatus = Integer.valueOf(entitlementStatus);
+ }
+ if (jsonToken.has(PLMN_ALLOWED_KEY)) {
+ JSONArray jsonArray = jsonToken.getJSONArray(PLMN_ALLOWED_KEY);
+ mPlmnAllowedList = new ArrayList<>();
+ for (int i = 0; i < jsonArray.length(); i++) {
+ String dataPlanType = jsonArray.getJSONObject(i).has(DATA_PLAN_TYPE_KEY)
+ ? jsonArray.getJSONObject(i).getString(DATA_PLAN_TYPE_KEY) : "";
+ String plmn = jsonArray.getJSONObject(i).getString(PLMN_KEY);
+ logd("parsingResponse: plmn=" + plmn + " dataplan=" + dataPlanType);
+ if (!TextUtils.isEmpty(plmn)) {
+ mPlmnAllowedList.add(new SatelliteNetworkInfo(plmn, dataPlanType));
+ }
+ }
+ }
+ if (jsonToken.has(PLMN_BARRED_KEY)) {
+ mPlmnBarredList = new ArrayList<>();
+ JSONArray jsonArray = jsonToken.getJSONArray(PLMN_BARRED_KEY);
+ for (int i = 0; i < jsonArray.length(); i++) {
+ String plmn = jsonArray.getJSONObject(i).getString(PLMN_KEY);
+ if (!TextUtils.isEmpty(plmn)) {
+ mPlmnBarredList.add(plmn);
+ }
+ }
+ }
+ } catch (JSONException e) {
+ loge("parsingResponse: failed JSONException", e);
+ } catch (NumberFormatException e) {
+ loge("parsingResponse: failed NumberFormatException", e);
+ }
+ }
+
+ private static void logd(String log) {
+ Log.d(TAG, log);
+ }
+
+ private static void loge(String log) {
+ Log.e(TAG, log);
+ }
+
+ private static void loge(String log, Exception e) {
+ Log.e(TAG, log, e);
+ }
+}
diff --git a/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
new file mode 100644
index 0000000..014e28e
--- /dev/null
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2024 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.satellite.entitlement;
+
+import android.annotation.IntDef;
+
+import com.android.internal.telephony.satellite.SatelliteNetworkInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * This class stores the result of the satellite entitlement query and passes them to
+ * SatelliteEntitlementController.
+ */
+public class SatelliteEntitlementResult {
+ /** SatMode allowed, but not yet provisioned and activated on the network. */
+ public static final int SATELLITE_ENTITLEMENT_STATUS_DISABLED = 0;
+ /** SatMode service allowed, provisioned and activated on the network. User can access the
+ * satellite service. */
+ public static final int SATELLITE_ENTITLEMENT_STATUS_ENABLED = 1;
+ /** SatMode cannot be offered for network or device. */
+ public static final int SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE = 2;
+ /** SatMode is being provisioned on the network. Not yet activated. */
+ public static final int SATELLITE_ENTITLEMENT_STATUS_PROVISIONING = 3;
+
+ @IntDef(prefix = {"SATELLITE_ENTITLEMENT_STATUS_"}, value = {
+ SATELLITE_ENTITLEMENT_STATUS_DISABLED,
+ SATELLITE_ENTITLEMENT_STATUS_ENABLED,
+ SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE,
+ SATELLITE_ENTITLEMENT_STATUS_PROVISIONING
+ })
+ public @interface SatelliteEntitlementStatus {}
+
+ private @SatelliteEntitlementStatus int mEntitlementStatus;
+ /**
+ * An SatelliteNetworkInfo list consisting of the PLMN and the DataPlanType in the PLMNAlowed
+ * item of the satellite configuration received from the entitlement server.
+ */
+ private List<SatelliteNetworkInfo> mAllowedSatelliteNetworkInfoList;
+ /**
+ * List consisting of the PLMN in the PLMNBarred item of the satellite configuration received
+ * from the entitlement server
+ */
+ private List<String> mBarredPlmnList;
+
+ /**
+ * Store the result of the satellite entitlement response.
+ *
+ * @param entitlementStatus The entitlement status.
+ * @param allowedSatelliteNetworkInfoList The allowedSatelliteNetworkInfoList
+ * @param barredPlmnList The barred plmn list
+ */
+ public SatelliteEntitlementResult(@SatelliteEntitlementStatus int entitlementStatus,
+ List<SatelliteNetworkInfo> allowedSatelliteNetworkInfoList,
+ List<String> barredPlmnList) {
+ mEntitlementStatus = entitlementStatus;
+ mAllowedSatelliteNetworkInfoList = allowedSatelliteNetworkInfoList;
+ mBarredPlmnList = barredPlmnList;
+ }
+
+ /**
+ * Get the entitlement status.
+ *
+ * @return The entitlement status.
+ */
+ public @SatelliteEntitlementStatus int getEntitlementStatus() {
+ return mEntitlementStatus;
+ }
+
+ /**
+ * Get the plmn allowed list
+ *
+ * @return The plmn allowed list.
+ */
+ public List<String> getAllowedPLMNList() {
+ return mAllowedSatelliteNetworkInfoList.stream().map(info -> info.mPlmn).collect(
+ Collectors.toList());
+ }
+
+ /**
+ * Get the plmn barred list
+ *
+ * @return The plmn barred list.
+ */
+ public List<String> getBarredPLMNList() {
+ return mBarredPlmnList.stream().map(String::new).collect(Collectors.toList());
+ }
+
+ /**
+ * Get the default SatelliteEntitlementResult. EntitlementStatus set to
+ * `SATELLITE_ENTITLEMENT_STATUS_DISABLED` and SatelliteNetworkInfo list set to empty.
+ *
+ * @return If there is no response, return default SatelliteEntitlementResult
+ */
+ public static SatelliteEntitlementResult getDefaultResult() {
+ return new SatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_DISABLED,
+ new ArrayList<>(), new ArrayList<>());
+ }
+}
diff --git a/src/com/android/phone/security/SafetySourceReceiver.java b/src/com/android/phone/security/SafetySourceReceiver.java
new file mode 100644
index 0000000..76f8e72
--- /dev/null
+++ b/src/com/android/phone/security/SafetySourceReceiver.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 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.security;
+
+import static android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES;
+import static android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.Flags;
+import com.android.phone.PhoneGlobals;
+import com.android.telephony.Rlog;
+
+public class SafetySourceReceiver extends BroadcastReceiver {
+ private static final String TAG = "TelephonySafetySourceReceiver";
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ // If none of the features that depend on this receiver are enabled, there's no reason
+ // to progress.
+ if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
+ || !Flags.enableModemCipherTransparencyUnsolEvents()) {
+ return;
+ }
+
+ String action = intent.getAction();
+ if (!ACTION_REFRESH_SAFETY_SOURCES.equals(action)) {
+ return;
+ }
+
+ String refreshBroadcastId =
+ intent.getStringExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID);
+ if (refreshBroadcastId == null) {
+ return;
+ }
+
+ if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
+ if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
+ refreshSafetySources(refreshBroadcastId);
+ }
+ } else {
+ refreshSafetySources(refreshBroadcastId);
+ }
+ }
+
+ private void refreshSafetySources(String refreshBroadcastId) {
+ Phone phone = getDefaultPhone();
+ // It's possible that phones have not been created yet. Safety center may send a refresh
+ // broadcast very early on.
+ if (phone != null) {
+ phone.refreshSafetySources(refreshBroadcastId);
+ }
+
+ }
+
+ @VisibleForTesting
+ public Phone getDefaultPhone() {
+ try {
+ return PhoneGlobals.getPhone();
+ } catch (IllegalStateException e) {
+ Rlog.i(TAG, "Unable to get phone. Skipping safety source refresh: " + e.getMessage());
+ }
+ return null;
+ }
+}
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index f6cd0d1..328087b 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -74,6 +74,7 @@
import android.telephony.TelephonyDisplayInfo;
import android.telephony.TelephonyManager;
import android.telephony.data.NetworkSlicingConfig;
+import android.telephony.euicc.EuiccManager;
import android.telephony.ims.ImsException;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
@@ -104,8 +105,6 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.euicc.EuiccConnector;
-import com.android.internal.telephony.flags.FeatureFlags;
-import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.phone.R;
@@ -207,6 +206,10 @@
Log.d(TAG, s);
}
+ private static void loge(String s) {
+ Log.e(TAG, s);
+ }
+
private static final int EVENT_QUERY_SMSC_DONE = 1005;
private static final int EVENT_UPDATE_SMSC_DONE = 1006;
private static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 1007;
@@ -261,9 +264,11 @@
private TextView mNrState;
private TextView mNrFrequency;
private TextView mNetworkSlicingConfig;
+ private TextView mEuiccInfo;
private EditText mSmsc;
private Switch mRadioPowerOnSwitch;
private Switch mSimulateOutOfServiceSwitch;
+ private Switch mMockSatellite;
private Button mDnsCheckToggleButton;
private Button mPingTestButton;
private Button mUpdateSmscButton;
@@ -291,6 +296,7 @@
private ImsManager mImsManager = null;
private Phone mPhone = null;
private ProvisioningManager mProvisioningManager = null;
+ private EuiccManager mEuiccManager;
private String mPingHostnameResultV4;
private String mPingHostnameResultV6;
@@ -298,15 +304,15 @@
private boolean mMwiValue = false;
private boolean mCfiValue = false;
+ private final PersistableBundle[] mCarrierSatelliteOriginalBundle = new PersistableBundle[2];
private List<CellInfo> mCellInfoResult = null;
private final boolean[] mSimulateOos = new boolean[2];
+ private String mEuiccInfoResult = "";
private int mPreferredNetworkTypeResult;
private int mCellInfoRefreshRateIndex;
private int mSelectedPhoneIndex;
- private FeatureFlags mFeatureFlags;
-
private final NetworkRequest mDefaultNetworkRequest = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
@@ -512,14 +518,13 @@
log("Started onCreate");
- mFeatureFlags = new FeatureFlagsImpl();
-
mQueuedWork = new ThreadPoolExecutor(1, 1, RUNNABLE_TIMEOUT_MS, TimeUnit.MICROSECONDS,
new LinkedBlockingDeque<Runnable>());
mConnectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
mPhone = getPhone(SubscriptionManager.getDefaultSubscriptionId());
mTelephonyManager = ((TelephonyManager) getSystemService(TELEPHONY_SERVICE))
.createForSubscriptionId(mPhone.getSubId());
+ mEuiccManager = getSystemService(EuiccManager.class);
mImsManager = new ImsManager(mPhone.getContext());
try {
@@ -567,6 +572,7 @@
mNrFrequency = (TextView) findViewById(R.id.nr_frequency);
mPhyChanConfig = (TextView) findViewById(R.id.phy_chan_config);
mNetworkSlicingConfig = (TextView) findViewById(R.id.network_slicing_config);
+ mEuiccInfo = (TextView) findViewById(R.id.euicc_info);
// hide 5G stats on devices that don't support 5G
if ((mTelephonyManager.getSupportedRadioAccessFamily()
@@ -639,6 +645,11 @@
mSimulateOutOfServiceSwitch.setVisibility(View.GONE);
}
+ mMockSatellite = (Switch) findViewById(R.id.mock_carrier_roaming_satellite);
+ if (!TelephonyUtils.IS_DEBUGGABLE) {
+ mMockSatellite.setVisibility(View.GONE);
+ }
+
mDownlinkKbps = (TextView) findViewById(R.id.dl_kbps);
mUplinkKbps = (TextView) findViewById(R.id.ul_kbps);
updateBandwidths(0, 0);
@@ -719,6 +730,7 @@
updateDnsCheckState();
updateNetworkType();
updateNrStats();
+ updateEuiccInfo();
updateCellInfo(mCellInfoResult);
updateSubscriptionIds();
@@ -749,8 +761,10 @@
mSelectPhoneIndex.setOnItemSelectedListener(mSelectPhoneIndexHandler);
mRadioPowerOnSwitch.setOnCheckedChangeListener(mRadioPowerOnChangeListener);
- mSimulateOutOfServiceSwitch.setOnCheckedChangeListener(mSimulateOosOnChangeListener);
mSimulateOutOfServiceSwitch.setChecked(mSimulateOos[mPhone.getPhoneId()]);
+ mSimulateOutOfServiceSwitch.setOnCheckedChangeListener(mSimulateOosOnChangeListener);
+ mMockSatellite.setChecked(mCarrierSatelliteOriginalBundle[mPhone.getPhoneId()] != null);
+ mMockSatellite.setOnCheckedChangeListener(mMockSatelliteListener);
mImsVolteProvisionedSwitch.setOnCheckedChangeListener(mImsVolteCheckedChangeListener);
mImsVtProvisionedSwitch.setOnCheckedChangeListener(mImsVtCheckedChangeListener);
mImsWfcProvisionedSwitch.setOnCheckedChangeListener(mImsWfcCheckedChangeListener);
@@ -862,12 +876,22 @@
@Override
protected void onDestroy() {
+ clearOverride();
super.onDestroy();
if (mQueuedWork != null) {
mQueuedWork.shutdown();
}
}
+ private void clearOverride() {
+ if (mSimulateOutOfServiceSwitch.isChecked()) {
+ mSimulateOosOnChangeListener.onCheckedChanged(mSimulateOutOfServiceSwitch, false);
+ }
+ if (mMockSatellite.isChecked()) {
+ mMockSatelliteListener.onCheckedChanged(mMockSatellite, false);
+ }
+ }
+
// returns array of string labels for each phone index. The array index is equal to the phone
// index.
private static String[] getPhoneIndexLabels(TelephonyManager tm) {
@@ -1300,7 +1324,7 @@
resultFuture.get(DEFAULT_TIMEOUT_MS, MILLISECONDS);
mNetworkSlicingConfig.setText(networkSlicingConfig.toString());
} catch (ExecutionException | InterruptedException | TimeoutException e) {
- Log.e(TAG, "Unable to get slicing config: " + e.toString());
+ loge("Unable to get slicing config: " + e);
mNetworkSlicingConfig.setText("Unable to get slicing config.");
}
@@ -1351,6 +1375,31 @@
mReceived.setText(rxPackets + " " + packets + ", " + rxBytes + " " + bytes);
}
+ private void updateEuiccInfo() {
+ final Runnable setEuiccInfo = new Runnable() {
+ public void run() {
+ mEuiccInfo.setText(mEuiccInfoResult);
+ }
+ };
+
+ mQueuedWork.execute(new Runnable() {
+ @Override
+ public void run() {
+ if (!mEuiccManager.isEnabled()) {
+ mEuiccInfoResult = "Not enabled";
+ }
+ try {
+ mEuiccInfoResult = " { Available memory in bytes:"
+ + mEuiccManager.getAvailableMemoryInBytes()
+ + " }";
+ } catch (Exception e) {
+ mEuiccInfoResult = e.getMessage();
+ }
+ mHandler.post(setEuiccInfo);
+ }
+ });
+ }
+
/**
* Ping a host name
*/
@@ -1573,11 +1622,7 @@
};
private boolean isRadioOn() {
- if (mFeatureFlags.radioInfoIsRadioOn()) {
- return mTelephonyManager.getRadioPowerState() == TelephonyManager.RADIO_POWER_ON;
- }
- //FIXME: Replace with a TelephonyManager call
- return mPhone.getServiceState().getState() != ServiceState.STATE_POWER_OFF;
+ return mTelephonyManager.getRadioPowerState() == TelephonyManager.RADIO_POWER_ON;
}
private void updateRadioPowerState() {
@@ -1726,6 +1771,69 @@
mPhone.getTelephonyTester().setServiceStateTestIntent(intent);
};
+ private final OnCheckedChangeListener mMockSatelliteListener =
+ (buttonView, isChecked) -> {
+ if (mPhone != null) {
+ CarrierConfigManager cm = mPhone.getContext()
+ .getSystemService(CarrierConfigManager.class);
+ if (cm == null) return;
+ if (isChecked) {
+ String operatorNumeric = mPhone.getOperatorNumeric();
+ TelephonyManager tm;
+ if (TextUtils.isEmpty(operatorNumeric) && (tm = mPhone.getContext()
+ .getSystemService(TelephonyManager.class)) != null) {
+ operatorNumeric = tm.getSimOperatorNumericForPhone(mPhone.getPhoneId());
+ }
+ if (TextUtils.isEmpty(operatorNumeric)) {
+ loge("mMockSatelliteListener: Can't mock because no operator for phone "
+ + mPhone.getPhoneId());
+ mMockSatellite.setChecked(false);
+ return;
+ }
+ PersistableBundle originalBundle = cm.getConfigForSubId(mPhone.getSubId(),
+ CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
+ CarrierConfigManager
+ .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE
+ );
+ PersistableBundle overrideBundle = new PersistableBundle();
+ overrideBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ overrideBundle.putBoolean(CarrierConfigManager
+ .KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false);
+ PersistableBundle capableProviderBundle = new PersistableBundle();
+ capableProviderBundle.putIntArray(mPhone.getOperatorNumeric(), new int[]{
+ // Currently satellite only supports below
+ NetworkRegistrationInfo.SERVICE_TYPE_SMS,
+ NetworkRegistrationInfo.SERVICE_TYPE_EMERGENCY
+ });
+ overrideBundle.putPersistableBundle(CarrierConfigManager
+ .KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
+ capableProviderBundle);
+ log("mMockSatelliteListener: new " + overrideBundle);
+ log("mMockSatelliteListener: old " + originalBundle);
+ cm.overrideConfig(mPhone.getSubId(), overrideBundle, false);
+ mCarrierSatelliteOriginalBundle[mPhone.getPhoneId()] = originalBundle;
+ } else {
+ try {
+ cm.overrideConfig(mPhone.getSubId(),
+ mCarrierSatelliteOriginalBundle[mPhone.getPhoneId()], false);
+ mCarrierSatelliteOriginalBundle[mPhone.getPhoneId()] = null;
+ log("mMockSatelliteListener: Successfully cleared mock for phone "
+ + mPhone.getPhoneId());
+ } catch (Exception e) {
+ loge("mMockSatelliteListener: Can't clear mock because invalid sub Id "
+ + mPhone.getSubId()
+ + ", insert SIM and use adb shell cmd phone cc clear-values");
+ // Keep show toggle ON if the view is not destroyed. If destroyed, must
+ // use cmd to reset, because upon creation the view doesn't remember the
+ // last toggle state while override mock is still in place.
+ mMockSatellite.setChecked(true);
+ }
+ }
+ }
+ };
+
private boolean isImsVolteProvisioned() {
return getImsConfigProvisionedState(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
diff --git a/src/com/android/phone/utils/CarrierAllowListInfo.java b/src/com/android/phone/utils/CarrierAllowListInfo.java
index 8e22cb9..3ab9733 100644
--- a/src/com/android/phone/utils/CarrierAllowListInfo.java
+++ b/src/com/android/phone/utils/CarrierAllowListInfo.java
@@ -23,7 +23,6 @@
import android.content.pm.Signature;
import android.telephony.Rlog;
import android.text.TextUtils;
-import android.util.Log;
import com.android.internal.telephony.uicc.IccUtils;
@@ -37,6 +36,7 @@
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -45,9 +45,9 @@
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";
+ private static final String MESSAGE_DIGEST_256_ALGORITHM = "SHA-256";
+ private static final String CALLER_SHA256_ID = "callerSHA256Ids";
+ private static final String CALLER_CARRIER_ID = "carrierIds";
public static final int INVALID_CARRIER_ID = -1;
private static final String CARRIER_RESTRICTION_OPERATOR_REGISTERED_FILE =
@@ -68,11 +68,12 @@
return mInstance;
}
- public int validateCallerAndGetCarrierId(String packageName) {
+ public Set<Integer> validateCallerAndGetCarrierIds(String packageName) {
CarrierInfo carrierInfo = parseJsonForCallerInfo(packageName);
boolean isValid = (carrierInfo != null) && validateCallerSignature(mContext, packageName,
carrierInfo.getSHAIdList());
- return (isValid) ? carrierInfo.getCallerCarrierId() : INVALID_CARRIER_ID;
+ return (isValid) ? carrierInfo.getCallerCarrierIdList() : Collections.singleton(
+ INVALID_CARRIER_ID);
}
private void loadJsonFile(Context context) {
@@ -94,13 +95,19 @@
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);
+ JSONArray callerJSONArray = callerJSON.getJSONArray(CALLER_SHA256_ID);
+ JSONArray carrierIdArray = callerJSON.getJSONArray(CALLER_CARRIER_ID);
+
+ Set<Integer> carrierIds = new HashSet<>();
+ for (int index = 0; index < carrierIdArray.length(); index++) {
+ carrierIds.add(carrierIdArray.getInt(index));
+ }
+
List<String> appSignatures = new ArrayList<>();
for (int index = 0; index < callerJSONArray.length(); index++) {
appSignatures.add((String) callerJSONArray.get(index));
}
- return new CarrierInfo(carrierId, appSignatures);
+ return new CarrierInfo(carrierIds, appSignatures);
}
} catch (JSONException ex) {
Rlog.e(LOG_TAG, "getCallerSignatureInfo: JSONException = " + ex);
@@ -134,7 +141,7 @@
/**
* API fetches all the related signatures of the given package from the packageManager
- * and validate all the signatures.
+ * and validate all the signatures using SHA-256.
*
* @param context context
* @param packageName package name of the caller to validate the signatures.
@@ -150,13 +157,13 @@
}
final PackageManager packageManager = context.getPackageManager();
try {
- MessageDigest sha1MDigest = MessageDigest.getInstance(MESSAGE_DIGEST_ALGORITHM);
+ MessageDigest sha256MDigest = MessageDigest.getInstance(MESSAGE_DIGEST_256_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)) {
+ final byte[] signatureSha256 = sha256MDigest.digest(signature.toByteArray());
+ final String hexSignatureSha256 = IccUtils.bytesToHexString(signatureSha256);
+ if (!allowListSignatures.contains(hexSignatureSha256)) {
return false;
}
}
@@ -183,16 +190,16 @@
}
private static class CarrierInfo {
- final private int mCallerCarrierId;
+ final private Set<Integer> mCallerCarrierIdList;
final private List<String> mSHAIdList;
- public CarrierInfo(int carrierId, List<String> SHAIds) {
- mCallerCarrierId = carrierId;
+ public CarrierInfo(Set<Integer> carrierIds, List<String> SHAIds) {
+ mCallerCarrierIdList = carrierIds;
mSHAIdList = SHAIds;
}
- public int getCallerCarrierId() {
- return mCallerCarrierId;
+ public Set<Integer> getCallerCarrierIdList() {
+ return mCallerCarrierIdList;
}
public List<String> getSHAIdList() {
@@ -203,10 +210,10 @@
@TestApi
public List<String> getShaIdList(String srcPkg, int carrierId) {
CarrierInfo carrierInfo = parseJsonForCallerInfo(srcPkg);
- if (carrierInfo != null && carrierInfo.getCallerCarrierId() == carrierId) {
+ if (carrierInfo != null && carrierInfo.getCallerCarrierIdList().contains(carrierId)) {
return carrierInfo.getSHAIdList();
}
- Rlog.e(LOG_TAG, "getShaIdList carrierId or shaIdList is empty");
+ Rlog.e(LOG_TAG, "getShaIdList: carrierId or shaIdList is empty");
return Collections.EMPTY_LIST;
}
}
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index adb07f9..48786dc 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -23,15 +23,19 @@
import android.telecom.DisconnectCause;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.telephony.ims.ImsReasonInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.CallFailCause;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.phone.ImsUtil;
import com.android.phone.PhoneGlobals;
-import com.android.phone.common.R;
+import com.android.phone.R;
public class DisconnectCauseUtil {
@@ -86,7 +90,7 @@
public static DisconnectCause toTelecomDisconnectCause(int telephonyDisconnectCause,
String reason, int phoneId) {
return toTelecomDisconnectCause(telephonyDisconnectCause, CallFailCause.NOT_VALID,
- reason, phoneId, null, new FlagsAdapterImpl());
+ reason, phoneId, null, new FlagsAdapterImpl(), false);
}
/**
@@ -103,7 +107,27 @@
int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason,
int phoneId, ImsReasonInfo imsReasonInfo, FlagsAdapter featureFlags) {
return toTelecomDisconnectCause(telephonyDisconnectCause, telephonyPreciseDisconnectCause,
- reason, phoneId, imsReasonInfo, getCarrierConfigBundle(phoneId), featureFlags);
+ reason, phoneId, imsReasonInfo, getCarrierConfigBundle(phoneId), featureFlags,
+ false);
+ }
+
+ /**
+ * Converts from a disconnect code in {@link android.telephony.DisconnectCause} into a more
+ * generic {@link android.telecom.DisconnectCause}.object, possibly populated with a localized
+ * message and tone for Slot.
+ * @param telephonyDisconnectCause The code for the reason for the disconnect.
+ * @param telephonyPreciseDisconnectCause The code for the precise reason for the disconnect.
+ * @param reason Description of the reason for the disconnect, not intended for the user to see.
+ * @param phoneId To support localized message based on phoneId
+ * @param imsReasonInfo
+ */
+ public static DisconnectCause toTelecomDisconnectCause(
+ int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason,
+ int phoneId, ImsReasonInfo imsReasonInfo, FlagsAdapter featureFlags,
+ boolean shouldTreatAsEmergency) {
+ return toTelecomDisconnectCause(telephonyDisconnectCause, telephonyPreciseDisconnectCause,
+ reason, phoneId, imsReasonInfo, getCarrierConfigBundle(phoneId), featureFlags,
+ shouldTreatAsEmergency);
}
/**
@@ -116,19 +140,23 @@
static DisconnectCause toTelecomDisconnectCause(
int telephonyDisconnectCause, int telephonyPreciseDisconnectCause, String reason,
int phoneId, ImsReasonInfo imsReasonInfo, PersistableBundle carrierConfig,
- FlagsAdapter featureFlags) {
+ FlagsAdapter featureFlags, boolean shouldTreatAsEmergency) {
Context context = PhoneGlobals.getInstance();
- return new DisconnectCause(
- toTelecomDisconnectCauseCode(telephonyDisconnectCause, carrierConfig),
- toTelecomDisconnectCauseLabel(context, telephonyDisconnectCause,
- telephonyPreciseDisconnectCause, carrierConfig, featureFlags),
- toTelecomDisconnectCauseDescription(context, telephonyDisconnectCause, phoneId),
- toTelecomDisconnectReason(context, telephonyDisconnectCause, reason, phoneId),
- toTelecomDisconnectCauseTone(telephonyDisconnectCause, carrierConfig, featureFlags),
- telephonyDisconnectCause,
- telephonyPreciseDisconnectCause,
- imsReasonInfo);
+ return new DisconnectCause.Builder(
+ toTelecomDisconnectCauseCode(telephonyDisconnectCause, carrierConfig))
+ .setLabel(toTelecomDisconnectCauseLabel(context, telephonyDisconnectCause,
+ telephonyPreciseDisconnectCause, carrierConfig, featureFlags))
+ .setDescription(toTelecomDisconnectCauseDescription(
+ context, telephonyDisconnectCause, phoneId, shouldTreatAsEmergency))
+ .setReason(toTelecomDisconnectReason(
+ context, telephonyDisconnectCause, reason, phoneId))
+ .setTone(toTelecomDisconnectCauseTone(
+ telephonyDisconnectCause, carrierConfig, featureFlags))
+ .setTelephonyDisconnectCause(telephonyDisconnectCause)
+ .setTelephonyPreciseDisconnectCause(telephonyPreciseDisconnectCause)
+ .setImsReasonInfo(imsReasonInfo)
+ .build();
}
/**
@@ -136,8 +164,8 @@
* {@link android.telecom.DisconnectCause} disconnect code.
* @return The disconnect code as defined in {@link android.telecom.DisconnectCause}.
*/
- private static int toTelecomDisconnectCauseCode(int telephonyDisconnectCause,
- PersistableBundle carrierConfig) {
+ private static @DisconnectCause.DisconnectCauseCode int toTelecomDisconnectCauseCode(
+ int telephonyDisconnectCause, PersistableBundle carrierConfig) {
// special case: some carriers determine what disconnect causes play the BUSY tone.
// hence, must adjust the disconnectCause CODE to match the tone.
@@ -430,7 +458,7 @@
resourceId = R.string.callFailed_wfc_service_not_available_in_this_location;
break;
case android.telephony.DisconnectCause.SATELLITE_ENABLED:
- resourceId = R.string.incall_error_satellite_enabled;
+ resourceId = getSatelliteErrorString();
break;
default:
break;
@@ -614,7 +642,7 @@
resourceId = R.string.clh_incall_error_out_of_service_txt;
break;
case android.telephony.DisconnectCause.SATELLITE_ENABLED:
- resourceId = R.string.clh_callFailed_satelliteEnabled_txt;
+ resourceId = getSatelliteErrorString();
break;
default:
resourceId = R.string.clh_card_title_call_ended_txt;
@@ -629,7 +657,8 @@
* Returns a description of the disconnect cause to be shown to the user.
*/
private static CharSequence toTelecomDisconnectCauseDescription(
- Context context, int telephonyDisconnectCause, int phoneId) {
+ Context context, int telephonyDisconnectCause, int phoneId,
+ boolean shouldTreatAsEmergency) {
if (context == null ) {
return "";
}
@@ -752,14 +781,31 @@
case android.telephony.DisconnectCause.OUT_OF_SERVICE:
// No network connection.
+ FeatureFlags mFeatureFlags = new FeatureFlagsImpl();
if (ImsUtil.shouldPromoteWfc(context, phoneId)) {
resourceId = R.string.incall_error_promote_wfc;
} else if (ImsUtil.isWfcModeWifiOnly(context, phoneId)) {
resourceId = R.string.incall_error_wfc_only_no_wireless_network;
} else if (ImsUtil.isWfcEnabled(context, phoneId)) {
- resourceId = R.string.incall_error_out_of_service_wfc;
+ if (!mFeatureFlags.showCallFailNotificationFor2gToggle()) {
+ resourceId = R.string.incall_error_out_of_service_wfc;
+ break;
+ }
+ if (is2gDisabled(phoneId) && !shouldTreatAsEmergency) {
+ resourceId = R.string.incall_error_out_of_service_wfc_2g_user;
+ } else {
+ resourceId = R.string.incall_error_out_of_service_wfc;
+ }
} else {
- resourceId = R.string.incall_error_out_of_service;
+ if (!mFeatureFlags.showCallFailNotificationFor2gToggle()) {
+ resourceId = R.string.incall_error_out_of_service;
+ break;
+ }
+ if (is2gDisabled(phoneId) && !shouldTreatAsEmergency) {
+ resourceId = R.string.incall_error_out_of_service_2g;
+ } else {
+ resourceId = R.string.incall_error_out_of_service;
+ }
}
break;
@@ -840,7 +886,7 @@
resourceId = R.string.callFailed_wfc_service_not_available_in_this_location;
break;
case android.telephony.DisconnectCause.SATELLITE_ENABLED:
- resourceId = R.string.incall_error_satellite_enabled;
+ resourceId = getSatelliteErrorString();
break;
default:
break;
@@ -884,6 +930,8 @@
return DisconnectCause.REASON_IMS_ACCESS_BLOCKED;
case android.telephony.DisconnectCause.OUTGOING_EMERGENCY_CALL_PLACED:
return DisconnectCause.REASON_EMERGENCY_CALL_PLACED;
+ case android.telephony.DisconnectCause.SATELLITE_ENABLED:
+ return reason;
}
// If no specific code-mapping found, then fall back to using the reason.
@@ -982,4 +1030,25 @@
return config;
}
+ /**
+ * Returns true if 2G is disabled.
+ */
+ protected static boolean is2gDisabled(int phoneId) {
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ if (phone == null) {
+ return false;
+ }
+ long bitmask2g = TelephonyManager.NETWORK_CLASS_BITMASK_2G;
+ long currentlyAllowedNetworkTypes = phone.getAllowedNetworkTypes(
+ TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
+ boolean is2gEnabled = (currentlyAllowedNetworkTypes & bitmask2g) != 0;
+ return !is2gEnabled;
+ }
+
+ private static Integer getSatelliteErrorString() {
+ if (SatelliteController.getInstance().isSatelliteEnabled()) {
+ return R.string.incall_error_satellite_enabled;
+ }
+ return R.string.incall_error_carrier_roaming_satellite_mode;
+ }
}
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index ea29b77..064c69b 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -64,6 +64,8 @@
import com.android.internal.telephony.ExponentialBackoff;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.SimultaneousCallingTracker;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.phone.PhoneGlobals;
import com.android.phone.PhoneUtils;
@@ -71,11 +73,16 @@
import com.android.telephony.Rlog;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
+import java.util.Set;
import java.util.function.Predicate;
+import java.util.stream.Collectors;
/**
* Owns all data we have registered with Telecom including handling dynamic addition and
@@ -122,6 +129,7 @@
final class AccountEntry implements PstnPhoneCapabilitiesNotifier.Listener {
private final Phone mPhone;
private PhoneAccount mAccount;
+ private SimultaneousCallingTracker mSCT;
private final PstnIncomingCallNotifier mIncomingCallNotifier;
private final PstnPhoneCapabilitiesNotifier mPhoneCapabilitiesNotifier;
private boolean mIsEmergency;
@@ -132,6 +140,7 @@
private MmTelFeature.MmTelCapabilities mMmTelCapabilities;
private ImsMmTelManager.CapabilityCallback mMmtelCapabilityCallback;
private RegistrationManager.RegistrationCallback mImsRegistrationCallback;
+ private SimultaneousCallingTracker.Listener mSimultaneousCallingTrackerListener;
private ImsMmTelManager mMmTelManager;
private final boolean mIsTestAccount;
private boolean mIsVideoCapable;
@@ -144,12 +153,18 @@
private boolean mIsManageImsConferenceCallSupported;
private boolean mIsUsingSimCallManager;
private boolean mIsShowPreciseFailedCause;
+ private Set<Integer> mSimultaneousCallSupportedSubIds;
AccountEntry(Phone phone, boolean isEmergency, boolean isTest) {
mPhone = phone;
mIsEmergency = isEmergency;
mIsTestAccount = isTest;
mIsAdhocConfCapable = mPhone.isImsRegistered();
+ if (Flags.simultaneousCallingIndications()) {
+ mSCT = SimultaneousCallingTracker.getInstance();
+ mSimultaneousCallSupportedSubIds =
+ mSCT.getSubIdsSupportingSimultaneousCalling(mPhone.getSubId());
+ }
mAccount = registerPstnPhoneAccount(isEmergency, isTest);
Log.i(this, "Registered phoneAccount: %s with handle: %s",
mAccount, mAccount.getAccountHandle());
@@ -202,6 +217,21 @@
}
};
registerImsRegistrationCallback();
+
+ if (Flags.simultaneousCallingIndications()) {
+ //Register SimultaneousCallingTracker listener:
+ mSimultaneousCallingTrackerListener = new SimultaneousCallingTracker.Listener() {
+ @Override
+ public void onSimultaneousCallingSupportChanged(Map<Integer,
+ Set<Integer>> simultaneousCallSubSupportMap) {
+ updateSimultaneousCallSubSupportMap(simultaneousCallSubSupportMap);
+ }
+ };
+ SimultaneousCallingTracker.getInstance()
+ .addListener(mSimultaneousCallingTrackerListener);
+ Log.d(LOG_TAG, "Finished registering mSimultaneousCallingTrackerListener for "
+ + "phoneId = " + mPhone.getPhoneId() + "; subId = " + mPhone.getSubId());
+ }
}
void teardown() {
@@ -216,6 +246,10 @@
mMmTelManager.unregisterImsRegistrationCallback(mImsRegistrationCallback);
}
}
+ if (Flags.simultaneousCallingIndications()) {
+ SimultaneousCallingTracker.getInstance()
+ .removeListener(mSimultaneousCallingTrackerListener);
+ }
}
private void registerMmTelCapabilityCallback() {
@@ -465,6 +499,15 @@
mIsUsingSimCallManager = isCarrierUsingSimCallManager();
mIsShowPreciseFailedCause = isCarrierShowPreciseFailedCause();
+ // Set CAPABILITY_EMERGENCY_CALLS_ONLY flag if either
+ // - Carrier config overrides subscription is not voice capable, or
+ // - Resource config overrides it be emergency_calls_only
+ // TODO(b/316183370:): merge the two cases when clearing up flag
+ if (Flags.dataOnlyServiceAllowEmergencyCallOnly()) {
+ if (!isSubscriptionVoiceCapableByCarrierConfig()) {
+ capabilities |= PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY;
+ }
+ }
if (isEmergency && mContext.getResources().getBoolean(
R.bool.config_emergency_account_emergency_calls_only)) {
capabilities |= PhoneAccount.CAPABILITY_EMERGENCY_CALLS_ONLY;
@@ -504,7 +547,7 @@
Log.i(this, "Adding Merged Account with group: " + Rlog.pii(LOG_TAG, groupId));
}
- PhoneAccount account = PhoneAccount.builder(phoneAccountHandle, label)
+ PhoneAccount.Builder accountBuilder = PhoneAccount.builder(phoneAccountHandle, label)
.setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, line1Number, null))
.setSubscriptionAddress(
Uri.fromParts(PhoneAccount.SCHEME_TEL, subNumber, null))
@@ -515,10 +558,19 @@
.setSupportedUriSchemes(Arrays.asList(
PhoneAccount.SCHEME_TEL, PhoneAccount.SCHEME_VOICEMAIL))
.setExtras(extras)
- .setGroupId(groupId)
- .build();
+ .setGroupId(groupId);
- return account;
+ if (Flags.simultaneousCallingIndications()) {
+ Set <PhoneAccountHandle> simultaneousCallingHandles =
+ mSimultaneousCallSupportedSubIds.stream()
+ .map(subscriptionId -> PhoneUtils.makePstnPhoneAccountHandleWithId(
+ String.valueOf(subscriptionId), userToRegister))
+ .collect(Collectors.toSet());
+ accountBuilder.setSimultaneousCallingRestriction(simultaneousCallingHandles);
+ }
+
+
+ return accountBuilder.build();
}
public PhoneAccountHandle getPhoneAccountHandle() {
@@ -804,6 +856,21 @@
}
/**
+ * @return true if the subscription is voice capable by the carrier config.
+ */
+ private boolean isSubscriptionVoiceCapableByCarrierConfig() {
+ PersistableBundle b =
+ PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ if (b == null) {
+ return true; // For any abnormal case, we assume subscription is voice capable
+ }
+ final int[] serviceCapabilities = b.getIntArray(
+ CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY);
+ return Arrays.stream(serviceCapabilities).anyMatch(
+ i -> i == SubscriptionManager.SERVICE_CAPABILITY_VOICE);
+ }
+
+ /**
* Receives callback from {@link PstnPhoneCapabilitiesNotifier} when the video capabilities
* have changed.
*
@@ -824,6 +891,30 @@
}
}
+ public void updateSimultaneousCallSubSupportMap(Map<Integer,
+ Set<Integer>> simultaneousCallSubSupportMap) {
+ if (!Flags.simultaneousCallingIndications()) { return; }
+ //Check if the simultaneous call support subIds for this account have changed:
+ Set<Integer> updatedSimultaneousCallSupportSubIds = new HashSet<>(3);
+ updatedSimultaneousCallSupportSubIds.addAll(
+ simultaneousCallSubSupportMap.get(mPhone.getSubId()));
+ if (!updatedSimultaneousCallSupportSubIds.equals(mSimultaneousCallSupportedSubIds)) {
+ //If necessary, update cache and re-register mAccount:
+ mSimultaneousCallSupportedSubIds = updatedSimultaneousCallSupportSubIds;
+ synchronized (mAccountsLock) {
+ if (!mAccounts.contains(this)) {
+ // Account has already been torn down, don't try to register it again.
+ // This handles the case where teardown has already happened, and we got a
+ // simultaneous calling support update that lost the race for the
+ // mAccountsLock. In such a scenario by the time we get here, the original
+ // phone account could have been torn down.
+ return;
+ }
+ mAccount = registerPstnPhoneAccount(mIsEmergency, mIsTestAccount);
+ }
+ }
+ }
+
public void updateAdhocConfCapability(boolean isAdhocConfCapable) {
synchronized (mAccountsLock) {
if (!mAccounts.contains(this)) {
@@ -1233,7 +1324,18 @@
*/
public static synchronized TelecomAccountRegistry getInstance(Context context) {
if (sInstance == null && context != null) {
- sInstance = new TelecomAccountRegistry(context);
+ if (Flags.enforceTelephonyFeatureMappingForPublicApis()) {
+ PackageManager pm = context.getPackageManager();
+ if (pm != null && pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
+ && pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING)) {
+ sInstance = new TelecomAccountRegistry(context);
+ } else {
+ Log.d(LOG_TAG, "Not initializing TelecomAccountRegistry: "
+ + "missing telephony/calling feature(s)");
+ }
+ } else {
+ sInstance = new TelecomAccountRegistry(context);
+ }
}
return sInstance;
}
@@ -1599,6 +1701,35 @@
new AccountEntry(PhoneFactory.getDefaultPhone(), true /* emergency */,
false /* isTest */));
}
+
+ // In some very rare cases, when setting the default voice sub in
+ // SubscriptionManagerService, the phone accounts here have not yet been built.
+ // So calling setUserSelectedOutgoingPhoneAccount in SubscriptionManagerService
+ // becomes a no-op. The workaround here is to reconcile and make sure the
+ // outgoing phone account is properly set in telecom.
+ int defaultVoiceSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
+ if (SubscriptionManager.isValidSubscriptionId(defaultVoiceSubId)) {
+ PhoneAccountHandle defaultVoiceAccountHandle =
+ getPhoneAccountHandleForSubId(defaultVoiceSubId);
+ if (defaultVoiceAccountHandle != null) {
+ PhoneAccountHandle currentAccount = mTelecomManager
+ .getUserSelectedOutgoingPhoneAccount();
+ // In some rare cases, the current phone account could be non-telephony
+ // phone account. We do not override in this case.
+ boolean wasPreviousAccountSameComponentOrUnset = currentAccount == null
+ || Objects.equals(defaultVoiceAccountHandle.getComponentName(),
+ currentAccount.getComponentName());
+
+ // Set the phone account again if it's out-of-sync.
+ if (!defaultVoiceAccountHandle.equals(currentAccount)
+ && wasPreviousAccountSameComponentOrUnset) {
+ Log.d(this, "setupAccounts: Re-setup phone account "
+ + "again for default voice sub " + defaultVoiceSubId);
+ mTelecomManager.setUserSelectedOutgoingPhoneAccount(
+ defaultVoiceAccountHandle);
+ }
+ }
+ }
}
// Add a fake account entry.
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index f96e6bd..5bfad6b 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -83,6 +83,7 @@
import com.android.internal.telephony.d2d.RtpTransport;
import com.android.internal.telephony.d2d.Timeouts;
import com.android.internal.telephony.d2d.TransportProtocol;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCall;
@@ -963,7 +964,7 @@
private Integer mEmergencyServiceCategory = null;
protected TelephonyConnection(com.android.internal.telephony.Connection originalConnection,
- String callId, @android.telecom.Call.Details.CallDirection int callDirection) {
+ String callId, int callDirection) {
setCallDirection(callDirection);
setTelecomCallId(callId);
if (originalConnection != null) {
@@ -1015,23 +1016,6 @@
mHandler.obtainMessage(MSG_HANGUP, android.telephony.DisconnectCause.LOCAL).sendToTarget();
}
- /**
- * Notifies this Connection of a request to disconnect a participant of the conference managed
- * by the connection.
- *
- * @param endpoint the {@link Uri} of the participant to disconnect.
- */
- @Override
- public void onDisconnectConferenceParticipant(Uri endpoint) {
- Log.v(this, "onDisconnectConferenceParticipant %s", endpoint);
-
- if (mOriginalConnection == null) {
- return;
- }
-
- mOriginalConnection.onDisconnectConferenceParticipant(endpoint);
- }
-
@Override
public void onSeparate() {
Log.v(this, "onSeparate");
@@ -1304,12 +1288,22 @@
originalConnection.sendRttModifyResponse(textStream);
}
+ private boolean answeringDropsFgCalls() {
+ if (Flags.callExtraForNonHoldSupportedCarriers()) {
+ Bundle extras = getExtras();
+ if (extras != null) {
+ return extras.getBoolean(Connection.EXTRA_ANSWERING_DROPS_FG_CALL);
+ }
+ }
+ return false;
+ }
+
public void performAnswer(int videoState) {
Log.v(this, "performAnswer");
if (isValidRingingCall() && getPhone() != null) {
try {
mTelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
- getPhoneAccountHandle());
+ getPhoneAccountHandle(), answeringDropsFgCalls());
getPhone().acceptCall(videoState);
} catch (CallStateException e) {
Log.e(this, e, "Failed to accept call.");
@@ -2567,7 +2561,8 @@
preciseDisconnectCause,
mOriginalConnection.getVendorDisconnectCause(),
getPhone().getPhoneId(), imsReasonInfo,
- new FlagsAdapterImpl()));
+ new FlagsAdapterImpl(),
+ shouldTreatAsEmergencyCall()));
close();
}
break;
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 0b0985b..a7e1fdc 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -33,11 +33,11 @@
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.ParcelUuid;
import android.os.PersistableBundle;
-import android.provider.DeviceConfig;
import android.telecom.Conference;
import android.telecom.Conferenceable;
import android.telecom.Connection;
@@ -54,7 +54,7 @@
import android.telephony.DataSpecificRegistrationInfo;
import android.telephony.DomainSelectionService;
import android.telephony.DomainSelectionService.SelectionAttributes;
-import android.telephony.EmergencyRegResult;
+import android.telephony.EmergencyRegistrationResult;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneNumberUtils;
import android.telephony.RadioAccessFamily;
@@ -89,6 +89,7 @@
import com.android.internal.telephony.emergency.EmergencyStateTracker;
import com.android.internal.telephony.emergency.RadioOnHelper;
import com.android.internal.telephony.emergency.RadioOnStateListener;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneConnection;
@@ -140,13 +141,18 @@
// 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 = 2000;
- private static final String KEY_DOMAIN_COMPARE_FEATURE_ENABLED_FLAG =
- "is_domain_selection_compare_feature_enabled";
+
+ // Timeout to wait for the termination of incoming call before continue with the emergency call.
+ private static final int DEFAULT_REJECT_INCOMING_CALL_TIMEOUT_MS = 10 * 1000; // 10 seconds.
// 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}");
+ private static final String DISCONNECT_REASON_SATELLITE_ENABLED = "SATELLITE_ENABLED";
+ private static final String DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE =
+ "CARRIER_ROAMING_SATELLITE_MODE";
+
private final TelephonyConnectionServiceProxy mTelephonyConnectionServiceProxy =
new TelephonyConnectionServiceProxy() {
@Override
@@ -230,7 +236,6 @@
private DomainSelectionResolver mDomainSelectionResolver;
private EmergencyCallDomainSelectionConnection mEmergencyCallDomainSelectionConnection;
private TelephonyConnection mEmergencyConnection;
- private String mEmergencyCallId = null;
private Executor mDomainSelectionMainExecutor;
private ImsManager mImsManager = null;
private DomainSelectionConnection mDomainSelectionConnection;
@@ -575,8 +580,7 @@
}
// 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());
+ mEmergencyStateTracker.onEmergencyCallDomainUpdated(origConn.getPhoneType(), c);
}
@Override
@@ -589,8 +593,8 @@
+ ", state=" + state);
if (c.getState() == Connection.STATE_ACTIVE) {
mEmergencyStateTracker.onEmergencyCallStateChanged(
- c.getOriginalConnection().getState(), c.getTelecomCallId());
- releaseEmergencyCallDomainSelection(false);
+ c.getOriginalConnection().getState(), c);
+ releaseEmergencyCallDomainSelection(false, true);
}
}
@@ -608,8 +612,8 @@
return;
}
Log.i(this, "onConnectionPropertiesChanged prop=" + connectionProperties);
- mEmergencyStateTracker.onEmergencyCallPropertiesChanged(connectionProperties,
- c.getTelecomCallId());
+ mEmergencyStateTracker.onEmergencyCallPropertiesChanged(
+ connectionProperties, c);
}
};
@@ -641,6 +645,13 @@
}
};
+ private void clearNormalCallDomainSelectionConnection() {
+ if (mDomainSelectionConnection != null) {
+ mDomainSelectionConnection.finishSelection();
+ mDomainSelectionConnection = null;
+ }
+ }
+
/**
* A listener for calls.
*/
@@ -653,17 +664,15 @@
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;
- }
+ clearNormalCallDomainSelectionConnection();
mNormalCallConnection = null;
}
break;
case Connection.STATE_DISCONNECTED: {
+ // Clear connection if the call state changes from
+ // DIALING -> DISCONNECTED without ACTIVE State.
+ clearNormalCallDomainSelectionConnection();
c.removeTelephonyConnectionListener(mNormalCallConnectionListener);
}
break;
@@ -705,6 +714,20 @@
}
}
+ private static class OnDisconnectListener extends
+ com.android.internal.telephony.Connection.ListenerBase {
+ private final CompletableFuture<Boolean> mFuture;
+
+ OnDisconnectListener(CompletableFuture<Boolean> future) {
+ mFuture = future;
+ }
+
+ @Override
+ public void onDisconnect(int cause) {
+ mFuture.complete(true);
+ }
+ };
+
private final DomainSelectionConnection.DomainSelectionConnectionCallback
mEmergencyDomainSelectionConnectionCallback =
new DomainSelectionConnection.DomainSelectionConnectionCallback() {
@@ -728,16 +751,32 @@
Phone phone = mEmergencyCallDomainSelectionConnection.getPhone();
mEmergencyConnection.removeTelephonyConnectionListener(
mEmergencyConnectionListener);
- releaseEmergencyCallDomainSelection(true);
- mEmergencyStateTracker.endCall(mEmergencyCallId);
- mEmergencyCallId = null;
+ releaseEmergencyCallDomainSelection(true, false);
+ mEmergencyStateTracker.endCall(c);
retryOutgoingOriginalConnection(c, phone, isPermanentFailure);
return;
}
}
if (mEmergencyConnection != null) {
- mEmergencyConnection.hangup(android.telephony.DisconnectCause.OUT_OF_NETWORK);
- mEmergencyConnection = null;
+ if (mEmergencyConnection.getOriginalConnection() != null) {
+ mEmergencyConnection.hangup(cause);
+ } else {
+ DomainSelectionConnection dsc = mEmergencyCallDomainSelectionConnection;
+ int disconnectCause = (cause == android.telephony.DisconnectCause.NOT_VALID)
+ ? dsc.getDisconnectCause() : cause;
+ mEmergencyConnection.setTelephonyConnectionDisconnected(
+ DisconnectCauseUtil.toTelecomDisconnectCause(disconnectCause,
+ dsc.getPreciseDisconnectCause(), dsc.getReasonMessage(),
+ dsc.getPhoneId(), dsc.getImsReasonInfo(),
+ new FlagsAdapterImpl()));
+ mEmergencyConnection.close();
+
+ TelephonyConnection c = mEmergencyConnection;
+ mEmergencyConnection.removeTelephonyConnectionListener(
+ mEmergencyConnectionListener);
+ releaseEmergencyCallDomainSelection(true, false);
+ mEmergencyStateTracker.endCall(c);
+ }
}
});
}
@@ -1102,6 +1141,7 @@
final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber,
/* Note: when not an emergency, handle can be null for unknown callers */
handle == null ? null : handle.getSchemeSpecificPart());
+ ImsPhone imsPhone = phone != null ? (ImsPhone) phone.getImsPhone() : null;
boolean isPhoneWifiCallingEnabled = phone != null && phone.isWifiCallingEnabled();
boolean needToTurnOnRadio = (isEmergencyNumber && (!isRadioOn() || isAirplaneModeOn))
@@ -1132,6 +1172,7 @@
}
int timeoutToOnTimeoutCallback = mDomainSelectionResolver.isDomainSelectionSupported()
? TIMEOUT_TO_DYNAMIC_ROUTING_MS : 0;
+ final Phone phoneForEmergency = phone;
mRadioOnHelper.triggerRadioOnAndListen(new RadioOnStateListener.Callback() {
@Override
public void onComplete(RadioOnStateListener listener, boolean isRadioReady) {
@@ -1156,7 +1197,12 @@
&& phone.getHalVersion(HAL_SERVICE_VOICE)
.less(RIL.RADIO_HAL_VERSION_1_4);
if (mDomainSelectionResolver.isDomainSelectionSupported()) {
- if (isEmergencyNumber) {
+ if (resultConnection != null
+ && resultConnection.getState() == Connection.STATE_DISCONNECTED) {
+ // Dialing is discarded.
+ return true;
+ }
+ if (isEmergencyNumber && phone == phoneForEmergency) {
// Since the domain selection service is enabled,
// dilaing normal routing emergency number only reaches here.
if (!isVoiceInService(phone, imsVoiceCapable)) {
@@ -1208,14 +1254,23 @@
}
if (!isEmergencyNumber) {
- if (mSatelliteController.isSatelliteEnabled()
- || isCallDisallowedDueToSatellite(phone)) {
- Log.d(this, "onCreateOutgoingConnection, cannot make call in satellite mode.");
+ if (mSatelliteController.isSatelliteEnabled()) {
+ Log.d(this, "onCreateOutgoingConnection, cannot make call in "
+ + "satellite mode.");
return Connection.createFailedConnection(
mDisconnectCauseFactory.toTelecomDisconnectCause(
android.telephony.DisconnectCause.SATELLITE_ENABLED,
- "Call failed because satellite modem is enabled."));
+ DISCONNECT_REASON_SATELLITE_ENABLED));
+ } else if (isCallDisallowedDueToSatellite(phone)
+ && (imsPhone == null || !imsPhone.canMakeWifiCall())) {
+ Log.d(this, "onCreateOutgoingConnection, cannot make call "
+ + "when device is connected to carrier roaming satellite network");
+ return Connection.createFailedConnection(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.SATELLITE_ENABLED,
+ DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE));
}
+
final Connection resultConnection = getTelephonyConnection(request, numberToDial,
false, handle, phone);
if (isAdhocConference) {
@@ -1249,27 +1304,9 @@
final Connection resultConnection = getTelephonyConnection(request, numberToDial,
true, handle, phone);
- CompletableFuture<Void> maybeHoldFuture = CompletableFuture.completedFuture(null);
- if (mTelephonyManagerProxy.isConcurrentCallsPossible()
- && shouldHoldForEmergencyCall(phone)) {
- // If the PhoneAccountHandle was adjusted on building the TelephonyConnection,
- // the relevant PhoneAccountHandle will be updated in resultConnection.
- PhoneAccountHandle phoneAccountHandle =
- resultConnection.getPhoneAccountHandle() == null
- ? request.getAccountHandle() : resultConnection.getPhoneAccountHandle();
- Conferenceable c = maybeHoldCallsOnOtherSubs(phoneAccountHandle);
- if (c != null) {
- maybeHoldFuture = delayDialForOtherSubHold(phone, c, (success) -> {
- Log.i(this, "onCreateOutgoingConn emergency-"
- + " delayDialForOtherSubHold success = " + success);
- if (!success) {
- // Terminates the existing call to make way for the emergency call.
- hangup(c, android.telephony.DisconnectCause
- .OUTGOING_EMERGENCY_CALL_PLACED);
- }
- });
- }
- }
+ CompletableFuture<Void> maybeHoldFuture =
+ checkAndHoldCallsOnOtherSubsForEmergencyCall(request,
+ resultConnection, phone);
Consumer<Boolean> ddsSwitchConsumer = (result) -> {
Log.i(this, "onCreateOutgoingConn emergency-"
+ " delayDialForDdsSwitch result = " + result);
@@ -1281,6 +1318,32 @@
}
}
+ private CompletableFuture<Void> checkAndHoldCallsOnOtherSubsForEmergencyCall(
+ ConnectionRequest request, Connection resultConnection, Phone phone) {
+ CompletableFuture<Void> maybeHoldFuture = CompletableFuture.completedFuture(null);
+ if (mTelephonyManagerProxy.isConcurrentCallsPossible()
+ && shouldHoldForEmergencyCall(phone)) {
+ // If the PhoneAccountHandle was adjusted on building the TelephonyConnection,
+ // the relevant PhoneAccountHandle will be updated in resultConnection.
+ PhoneAccountHandle phoneAccountHandle =
+ resultConnection.getPhoneAccountHandle() == null
+ ? request.getAccountHandle() : resultConnection.getPhoneAccountHandle();
+ Conferenceable c = maybeHoldCallsOnOtherSubs(phoneAccountHandle);
+ if (c != null) {
+ maybeHoldFuture = delayDialForOtherSubHold(phone, c, (success) -> {
+ Log.i(this, "checkAndHoldCallsOnOtherSubsForEmergencyCall"
+ + " delayDialForOtherSubHold success = " + success);
+ if (!success) {
+ // Terminates the existing call to make way for the emergency call.
+ hangup(c, android.telephony.DisconnectCause
+ .OUTGOING_EMERGENCY_CALL_PLACED);
+ }
+ });
+ }
+ }
+ return maybeHoldFuture;
+ }
+
private Connection placeOutgoingConnection(ConnectionRequest request,
Connection resultConnection, Phone phone) {
// If there was a failure, the resulting connection will not be a TelephonyConnection,
@@ -1342,6 +1405,11 @@
Log.i(this, "Call disconnected before the outgoing call was placed. Skipping call "
+ "placement.");
if (isEmergencyNumber) {
+ if (mDomainSelectionResolver.isDomainSelectionSupported()
+ && mDeviceState.isAirplaneModeOn(this)) {
+ mIsEmergencyCallPending = false;
+ return;
+ }
// If call is already canceled by the user, notify modem to exit emergency call
// mode by sending radio on with forEmergencyCall=false.
for (Phone curPhone : mPhoneFactoryProxy.getPhones()) {
@@ -2220,28 +2288,20 @@
}
} catch (CallStateException e) {
Log.e(this, e, "placeOutgoingConnection, phone.dial exception: " + e);
+ if (mDomainSelectionResolver.isDomainSelectionSupported()) {
+ // Notify EmergencyStateTracker and DomainSelector of the cancellation by exception
+ onLocalHangup(connection);
+ }
connection.unregisterForCallEvents();
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()) {
- Log.d(this, "dialed MMI code");
- int subId = phone.getSubId();
- Log.d(this, "subId: "+subId);
- telephonyDisconnectCause = android.telephony.DisconnectCause.DIALED_MMI;
- final Intent intent = new Intent(this, MMIDialogActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
- Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- if (SubscriptionManager.isValidSubscriptionId(subId)) {
- SubscriptionManager.putSubscriptionIdExtra(intent, subId);
- }
- startActivity(intent);
- }
Log.d(this, "placeOutgoingConnection, phone.dial returned null");
+
+ // On GSM phones, null connection means that we dialed an MMI code
+ int telephonyDisconnectCause = handleMmiCode(
+ phone, android.telephony.DisconnectCause.OUTGOING_FAILURE);
connection.setTelephonyConnectionDisconnected(
mDisconnectCauseFactory.toTelecomDisconnectCause(telephonyDisconnectCause,
"Connection is null", phone.getPhoneId()));
@@ -2261,6 +2321,25 @@
}
}
+ private int handleMmiCode(Phone phone, int telephonyDisconnectCause) {
+ int disconnectCause = telephonyDisconnectCause;
+ if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM
+ || phone.isUtEnabled()) {
+ Log.d(this, "dialed MMI code");
+ int subId = phone.getSubId();
+ Log.d(this, "subId: " + subId);
+ disconnectCause = android.telephony.DisconnectCause.DIALED_MMI;
+ final Intent intent = new Intent(this, MMIDialogActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
+ SubscriptionManager.putSubscriptionIdExtra(intent, subId);
+ }
+ startActivity(intent);
+ }
+ return disconnectCause;
+ }
+
private void handleOutgoingCallConnectionByCallDomainSelection(
int domain, Phone phone, String number, int videoState) {
Log.d(this, "Call Domain Selected : " + domain);
@@ -2270,14 +2349,6 @@
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);
@@ -2290,6 +2361,24 @@
.build(),
mNormalCallConnection::registerForCallEvents);
+ if (connection == null) {
+ Log.d(this, "placeOutgoingConnection, phone.dial returned null");
+
+ // On GSM phones, null connection means that we dialed an MMI code
+ int telephonyDisconnectCause = handleMmiCode(
+ phone, android.telephony.DisconnectCause.OUTGOING_FAILURE);
+ if (mNormalCallConnection.getState() != Connection.STATE_DISCONNECTED) {
+ mNormalCallConnection.setTelephonyConnectionDisconnected(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(
+ telephonyDisconnectCause,
+ "Connection is null",
+ phone.getPhoneId()));
+ mNormalCallConnection.close();
+ }
+ clearNormalCallDomainSelectionConnection();
+ return;
+ }
+
mNormalCallConnection.setOriginalConnection(connection);
mNormalCallConnection.addTelephonyConnectionListener(mNormalCallConnectionListener);
return;
@@ -2313,10 +2402,7 @@
e.getMessage(), phone.getPhoneId()));
mNormalCallConnection.close();
}
- if (mDomainSelectionConnection != null) {
- mDomainSelectionConnection.finishSelection();
- mDomainSelectionConnection = null;
- }
+ clearNormalCallDomainSelectionConnection();
mNormalCallConnection = null;
}
@@ -2336,6 +2422,7 @@
boolean isMmiCode = (dialPart.startsWith("*") || dialPart.startsWith("#"))
&& dialPart.endsWith("#");
boolean isSuppServiceCode = ImsPhoneMmiCode.isSuppServiceCodes(dialPart, phone);
+ boolean isPotentialUssdCode = isMmiCode && !isSuppServiceCode;
// 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.
@@ -2344,6 +2431,10 @@
return false;
}
+ /* For USSD codes, connection is closed and MMIDialogActivity is started.
+ To avoid connection close and return false. isPotentialUssdCode is handled after
+ all condition checks. */
+
// Check and select same domain as ongoing call on the same subscription (if exists)
int activeCallDomain = getActiveCallDomain(phone.getSubId());
if (activeCallDomain != NetworkRegistrationInfo.DOMAIN_UNKNOWN
@@ -2364,7 +2455,7 @@
SelectionAttributes selectionAttributes =
new SelectionAttributes.Builder(phone.getPhoneId(), phone.getSubId(),
SELECTOR_TYPE_CALLING)
- .setNumber(number)
+ .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, number, null))
.setEmergency(false)
.setVideoCall(VideoProfile.isVideo(videoState))
.build();
@@ -2379,6 +2470,15 @@
mNormalCallConnection = connection;
future.thenAcceptAsync((domain) -> handleOutgoingCallConnectionByCallDomainSelection(
domain, phone, number, videoState), mDomainSelectionMainExecutor);
+
+ if (isPotentialUssdCode) {
+ Log.v(LOG_TAG, "PotentialUssdCode. Closing connection with DisconnectCause.DIALED_MMI");
+ connection.setTelephonyConnectionDisconnected(
+ mDisconnectCauseFactory.toTelecomDisconnectCause(
+ android.telephony.DisconnectCause.DIALED_MMI,
+ "Dialing USSD", phone.getPhoneId()));
+ connection.close();
+ }
return true;
}
@@ -2395,6 +2495,32 @@
Log.i(this, "placeEmergencyConnection");
mIsEmergencyCallPending = true;
+ mEmergencyConnection = (TelephonyConnection) resultConnection;
+ }
+
+ CompletableFuture<Void> maybeHoldFuture =
+ checkAndHoldCallsOnOtherSubsForEmergencyCall(request, resultConnection, phone);
+ maybeHoldFuture.thenRun(() -> placeEmergencyConnectionInternal(resultConnection,
+ phone, request, numberToDial, isTestEmergencyNumber, needToTurnOnRadio));
+
+ // Non TelephonyConnection type instance means dialing failure.
+ return resultConnection;
+ }
+
+ @SuppressWarnings("FutureReturnValueIgnored")
+ private void placeEmergencyConnectionInternal(final Connection resultConnection,
+ final Phone phone, final ConnectionRequest request,
+ final String numberToDial, final boolean isTestEmergencyNumber,
+ final boolean needToTurnOnRadio) {
+
+ if (mEmergencyConnection == null) {
+ Log.i(this, "placeEmergencyConnectionInternal dialing canceled");
+ return;
+ }
+
+ if (resultConnection instanceof TelephonyConnection) {
+ Log.i(this, "placeEmergencyConnectionInternal");
+
((TelephonyConnection) resultConnection).addTelephonyConnectionListener(
mEmergencyConnectionListener);
@@ -2402,19 +2528,18 @@
mEmergencyStateTracker = EmergencyStateTracker.getInstance();
}
- mEmergencyCallId = resultConnection.getTelecomCallId();
CompletableFuture<Integer> future = mEmergencyStateTracker.startEmergencyCall(
- phone, mEmergencyCallId, isTestEmergencyNumber);
+ phone, resultConnection, isTestEmergencyNumber);
future.thenAccept((result) -> {
Log.d(this, "startEmergencyCall-complete result=" + result);
- if (mEmergencyCallId == null) {
+ if (mEmergencyConnection == 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());
+ numberToDial, isTestEmergencyNumber, request, needToTurnOnRadio,
+ mEmergencyStateTracker.getEmergencyRegistrationResult());
} else {
mEmergencyConnection = null;
String reason = "Couldn't setup emergency call";
@@ -2427,18 +2552,15 @@
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 boolean isTestEmergencyNumber,
final ConnectionRequest request, boolean needToTurnOnRadio,
- final EmergencyRegResult regResult) {
+ final EmergencyRegistrationResult regResult) {
Log.i(this, "createEmergencyConnection");
if (phone.getImsPhone() == null) {
@@ -2478,21 +2600,27 @@
DomainSelectionService.SelectionAttributes attr =
EmergencyCallDomainSelectionConnection.getSelectionAttributes(
phone.getPhoneId(), phone.getSubId(), needToTurnOnRadio,
- request.getTelecomCallId(), number, 0, null, regResult);
+ request.getTelecomCallId(), number, isTestEmergencyNumber,
+ 0, null, regResult);
CompletableFuture<Integer> future =
mEmergencyCallDomainSelectionConnection.createEmergencyConnection(
attr, mEmergencyDomainSelectionConnectionCallback);
future.thenAcceptAsync((result) -> {
Log.d(this, "createEmergencyConnection-complete result=" + result);
- if (mEmergencyCallId == null) {
+ if (mEmergencyConnection == 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;
+ CompletableFuture<Void> rejectFuture = checkAndRejectIncomingCall(phone, (ret) -> {
+ if (!ret) {
+ Log.i(this, "createEmergencyConnection reject incoming call failed");
+ }
+ });
+ rejectFuture.thenRun(() -> placeEmergencyConnectionOnSelectedDomain(request,
+ resultConnection, phone));
}, mDomainSelectionMainExecutor);
}
@@ -2503,22 +2631,40 @@
extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, NetworkRegistrationInfo.DOMAIN_CS);
mDomainSelectionMainExecutor.execute(
() -> {
- if (mEmergencyCallId == null) {
+ if (mEmergencyConnection == null) {
Log.i(this, "dialCsEmergencyCall dialing canceled");
return;
}
- placeOutgoingConnection(request, resultConnection, phone);
+ CompletableFuture<Void> future = checkAndRejectIncomingCall(phone, (ret) -> {
+ if (!ret) {
+ Log.i(this, "dialCsEmergencyCall reject incoming call failed");
+ }
+ });
+ future.thenRun(() -> placeEmergencyConnectionOnSelectedDomain(request,
+ resultConnection, phone));
});
}
- private void releaseEmergencyCallDomainSelection(boolean cancel) {
+ private void placeEmergencyConnectionOnSelectedDomain(ConnectionRequest request,
+ TelephonyConnection resultConnection, Phone phone) {
+ if (mEmergencyConnection == null) {
+ Log.i(this, "placeEmergencyConnectionOnSelectedDomain dialing canceled");
+ return;
+ }
+ placeOutgoingConnection(request, resultConnection, phone);
+ mIsEmergencyCallPending = false;
+ }
+
+ private void releaseEmergencyCallDomainSelection(boolean cancel, boolean isActive) {
if (mEmergencyCallDomainSelectionConnection != null) {
if (cancel) mEmergencyCallDomainSelectionConnection.cancelSelection();
else mEmergencyCallDomainSelectionConnection.finishSelection();
mEmergencyCallDomainSelectionConnection = null;
}
mIsEmergencyCallPending = false;
- mEmergencyConnection = null;
+ if (!isActive) {
+ mEmergencyConnection = null;
+ }
}
/**
@@ -2538,14 +2684,15 @@
int callFailCause = c.getOriginalConnection().getPreciseDisconnectCause();
Log.i(this, "maybeReselectDomain csCause=" + callFailCause + ", psCause=" + reasonInfo);
- if (TextUtils.equals(mEmergencyCallId, c.getTelecomCallId())) {
+ if (mEmergencyConnection == c) {
if (mEmergencyCallDomainSelectionConnection != null) {
- return maybeReselectDomainForEmergencyCall(c, callFailCause, reasonInfo);
+ return maybeReselectDomainForEmergencyCall(c, callFailCause, reasonInfo,
+ showPreciseCause, overrideCause);
}
Log.i(this, "maybeReselectDomain endCall()");
c.removeTelephonyConnectionListener(mEmergencyConnectionListener);
- mEmergencyStateTracker.endCall(c.getTelecomCallId());
- mEmergencyCallId = null;
+ releaseEmergencyCallDomainSelection(false, false);
+ mEmergencyStateTracker.endCall(c);
return false;
}
@@ -2557,10 +2704,7 @@
&& extraCode == ImsReasonInfo.EXTRA_CODE_CALL_RETRY_EMERGENCY)) {
// clear normal call domain selector
c.removeTelephonyConnectionListener(mNormalCallConnectionListener);
- if (mDomainSelectionConnection != null) {
- mDomainSelectionConnection.finishSelection();
- mDomainSelectionConnection = null;
- }
+ clearNormalCallDomainSelectionConnection();
mNormalCallConnection = null;
onEmergencyRedial(c, c.getPhone().getDefaultPhone());
@@ -2572,9 +2716,11 @@
}
private boolean maybeReselectDomainForEmergencyCall(final TelephonyConnection c,
- int callFailCause, ImsReasonInfo reasonInfo) {
+ int callFailCause, ImsReasonInfo reasonInfo,
+ boolean showPreciseCause, int overrideCause) {
Log.i(this, "maybeReselectDomainForEmergencyCall "
- + "csCause=" + callFailCause + ", psCause=" + reasonInfo);
+ + "csCause=" + callFailCause + ", psCause=" + reasonInfo
+ + ", showPreciseCause=" + showPreciseCause + ", overrideCause=" + overrideCause);
if (c.getOriginalConnection() != null
&& c.getOriginalConnection().getDisconnectCause()
@@ -2582,11 +2728,17 @@
&& c.getOriginalConnection().getDisconnectCause()
!= android.telephony.DisconnectCause.POWER_OFF) {
+ int disconnectCause = (overrideCause != android.telephony.DisconnectCause.NOT_VALID)
+ ? overrideCause : c.getOriginalConnection().getDisconnectCause();
+ mEmergencyCallDomainSelectionConnection.setDisconnectCause(disconnectCause,
+ showPreciseCause ? callFailCause : CallFailCause.NOT_VALID,
+ c.getOriginalConnection().getVendorDisconnectCause());
+
DomainSelectionService.SelectionAttributes attr =
EmergencyCallDomainSelectionConnection.getSelectionAttributes(
c.getPhone().getPhoneId(), c.getPhone().getSubId(), false,
c.getTelecomCallId(), c.getAddress().getSchemeSpecificPart(),
- callFailCause, reasonInfo, null);
+ false, callFailCause, reasonInfo, null);
CompletableFuture<Integer> future =
mEmergencyCallDomainSelectionConnection.reselectDomain(attr);
@@ -2595,7 +2747,7 @@
if (future != null) {
future.thenAcceptAsync((result) -> {
Log.d(this, "reselectDomain-complete");
- if (mEmergencyCallId == null) {
+ if (mEmergencyConnection == null) {
Log.i(this, "reselectDomain-complete dialing canceled");
return;
}
@@ -2607,9 +2759,8 @@
Log.i(this, "maybeReselectDomainForEmergencyCall endCall()");
c.removeTelephonyConnectionListener(mEmergencyConnectionListener);
- releaseEmergencyCallDomainSelection(true);
- mEmergencyStateTracker.endCall(c.getTelecomCallId());
- mEmergencyCallId = null;
+ releaseEmergencyCallDomainSelection(true, false);
+ mEmergencyStateTracker.endCall(c);
return false;
}
@@ -2670,6 +2821,25 @@
.findFirst().orElse(null);
}
+ /**
+ * Determines the phone with which emergency callback mode was set.
+ * @return The {@link Phone} with which emergency callback mode was set,
+ * or {@code null} if none was found.
+ */
+ @VisibleForTesting
+ public Phone getPhoneInEmergencyCallbackMode() {
+ if (!mDomainSelectionResolver.isDomainSelectionSupported()) {
+ // This is applicable for the AP domain selection service.
+ return null;
+ }
+ if (mEmergencyStateTracker == null) {
+ mEmergencyStateTracker = EmergencyStateTracker.getInstance();
+ }
+ return Stream.of(mPhoneFactoryProxy.getPhones())
+ .filter(p -> mEmergencyStateTracker.isInEcm(p))
+ .findFirst().orElse(null);
+ }
+
private boolean isVoiceInService(Phone phone, boolean imsVoiceCapable) {
// Dialing normal call is available.
if (phone.isWifiCallingEnabled()) {
@@ -2756,20 +2926,35 @@
}
c.removeTelephonyConnectionListener(mTelephonyConnectionListener);
- if (mDomainSelectionConnection != null) {
- mDomainSelectionConnection.finishSelection();
- mDomainSelectionConnection = null;
- }
+ clearNormalCallDomainSelectionConnection();
mNormalCallConnection = null;
Log.d(LOG_TAG, "Reselect call domain not triggered.");
return false;
}
- private void onEmergencyRedialOnDomain(TelephonyConnection connection,
+ private void onEmergencyRedialOnDomain(final TelephonyConnection connection,
final Phone phone, @NetworkRegistrationInfo.Domain int domain) {
Log.i(this, "onEmergencyRedialOnDomain phoneId=" + phone.getPhoneId()
+ ", domain=" + DomainSelectionService.getDomainName(domain));
+ final Bundle extras = new Bundle();
+ extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, domain);
+
+ CompletableFuture<Void> future = checkAndRejectIncomingCall(phone, (ret) -> {
+ if (!ret) {
+ Log.i(this, "onEmergencyRedialOnDomain reject incoming call failed");
+ }
+ });
+ future.thenRun(() -> onEmergencyRedialOnDomainInternal(connection, phone, extras));
+ }
+
+ private void onEmergencyRedialOnDomainInternal(TelephonyConnection connection,
+ Phone phone, Bundle extras) {
+ if (mEmergencyConnection == null) {
+ Log.i(this, "onEmergencyRedialOnDomainInternal dialing canceled");
+ return;
+ }
+
String number = connection.getAddress().getSchemeSpecificPart();
// Indicates undetectable emergency number with DialArgs
@@ -2778,12 +2963,9 @@
if (connection.getEmergencyServiceCategory() != null) {
isEmergency = true;
eccCategory = connection.getEmergencyServiceCategory();
- Log.i(this, "onEmergencyRedialOnDomain eccCategory=" + eccCategory);
+ Log.i(this, "onEmergencyRedialOnDomainInternal eccCategory=" + eccCategory);
}
- Bundle extras = new Bundle();
- extras.putInt(PhoneConstants.EXTRA_DIAL_DOMAIN, domain);
-
com.android.internal.telephony.Connection originalConnection =
connection.getOriginalConnection();
try {
@@ -2798,14 +2980,20 @@
connection::registerForCallEvents);
}
} catch (CallStateException e) {
- Log.e(this, e, "onEmergencyRedialOnDomain, exception: " + e);
+ Log.e(this, e, "onEmergencyRedialOnDomainInternal, exception: " + e);
+ onLocalHangup(connection);
+ connection.unregisterForCallEvents();
+ handleCallStateException(e, connection, phone);
+ return;
}
if (originalConnection == null) {
- Log.d(this, "onEmergencyRedialOnDomain, phone.dial returned null");
- connection.setDisconnected(
+ Log.d(this, "onEmergencyRedialOnDomainInternal, phone.dial returned null");
+ onLocalHangup(connection);
+ connection.setTelephonyConnectionDisconnected(
mDisconnectCauseFactory.toTelecomDisconnectCause(
android.telephony.DisconnectCause.ERROR_UNSPECIFIED,
"unknown error"));
+ connection.close();
} else {
connection.setOriginalConnection(originalConnection);
}
@@ -2826,12 +3014,12 @@
mEmergencyStateTracker = EmergencyStateTracker.getInstance();
}
- mEmergencyCallId = c.getTelecomCallId();
+ mEmergencyConnection = c;
CompletableFuture<Integer> future = mEmergencyStateTracker.startEmergencyCall(
- phone, mEmergencyCallId, isTestEmergencyNumber);
+ phone, c, isTestEmergencyNumber);
future.thenAccept((result) -> {
Log.d(this, "onEmergencyRedial-complete result=" + result);
- if (mEmergencyCallId == null) {
+ if (mEmergencyConnection == null) {
Log.i(this, "onEmergencyRedial-complete dialing canceled");
return;
}
@@ -2852,15 +3040,13 @@
mEmergencyCallDomainSelectionConnection =
(EmergencyCallDomainSelectionConnection) selectConnection;
- mEmergencyConnection = c;
-
DomainSelectionService.SelectionAttributes attr =
EmergencyCallDomainSelectionConnection.getSelectionAttributes(
phone.getPhoneId(),
phone.getSubId(), false,
c.getTelecomCallId(),
- c.getAddress().getSchemeSpecificPart(),
- 0, null, mEmergencyStateTracker.getEmergencyRegResult());
+ c.getAddress().getSchemeSpecificPart(), isTestEmergencyNumber,
+ 0, null, mEmergencyStateTracker.getEmergencyRegistrationResult());
CompletableFuture<Integer> domainFuture =
mEmergencyCallDomainSelectionConnection.createEmergencyConnection(
@@ -2872,6 +3058,7 @@
mIsEmergencyCallPending = false;
}, mDomainSelectionMainExecutor);
} else {
+ mEmergencyConnection = null;
c.setTelephonyConnectionDisconnected(
mDisconnectCauseFactory.toTelecomDisconnectCause(result, "unknown error"));
c.close();
@@ -2883,7 +3070,7 @@
private void recreateEmergencyConnection(final TelephonyConnection connection,
final Phone phone, final @NetworkRegistrationInfo.Domain int result) {
Log.d(this, "recreateEmergencyConnection result=" + result);
- if (mEmergencyCallId == null) {
+ if (mEmergencyConnection == null) {
Log.i(this, "recreateEmergencyConnection dialing canceled");
return;
}
@@ -2934,15 +3121,6 @@
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) {
@@ -2977,16 +3155,25 @@
}
protected void onLocalHangup(TelephonyConnection c) {
- if (TextUtils.equals(mEmergencyCallId, c.getTelecomCallId())) {
- Log.i(this, "onLocalHangup " + mEmergencyCallId);
+ if (mEmergencyConnection == c) {
+ Log.i(this, "onLocalHangup " + c.getTelecomCallId());
c.removeTelephonyConnectionListener(mEmergencyConnectionListener);
- releaseEmergencyCallDomainSelection(true);
- mEmergencyStateTracker.endCall(c.getTelecomCallId());
- mEmergencyCallId = null;
+ releaseEmergencyCallDomainSelection(true, false);
+ mEmergencyStateTracker.endCall(c);
}
}
@VisibleForTesting
+ public TelephonyConnection getEmergencyConnection() {
+ return mEmergencyConnection;
+ }
+
+ @VisibleForTesting
+ public void setEmergencyConnection(TelephonyConnection c) {
+ mEmergencyConnection = c;
+ }
+
+ @VisibleForTesting
public TelephonyConnection.TelephonyConnectionListener getEmergencyConnectionListener() {
return mEmergencyConnectionListener;
}
@@ -3156,6 +3343,15 @@
return normalRoutingPhone;
}
+ if (mDomainSelectionResolver.isDomainSelectionSupported()) {
+ Phone phoneInEcm = getPhoneInEmergencyCallbackMode();
+ if (phoneInEcm != null) {
+ Log.i(this, "getPhoneForAccount: in ECBM, using phoneId=%d/subId=%d",
+ phoneInEcm.getPhoneId(), phoneInEcm.getSubId());
+ return phoneInEcm;
+ }
+ }
+
// Default emergency call phone selection logic:
// This is an emergency call and the phone we originally planned to make this call
// with is not in service or was invalid, try to find one that is in service, using the
@@ -3354,6 +3550,52 @@
}
/**
+ * If needed, block until an incoming call is disconnected for outgoing emergency call,
+ * or timeout expires.
+ * @param phone The Phone to reject the incoming call
+ * @param completeConsumer The consumer to call once rejecting incoming call has been
+ * completed. {@code true} result if the operation commpletes successfully, or
+ * {@code false} if the operation timed out/failed.
+ */
+ private CompletableFuture<Void> checkAndRejectIncomingCall(Phone phone,
+ Consumer<Boolean> completeConsumer) {
+ if (phone == null) {
+ // Unexpected inputs
+ Log.i(this, "checkAndRejectIncomingCall phone is null");
+ completeConsumer.accept(false);
+ return CompletableFuture.completedFuture(null);
+ }
+
+ Call ringingCall = phone.getRingingCall();
+ if (ringingCall == null || !ringingCall.isRinging()) {
+ completeConsumer.accept(true);
+ return CompletableFuture.completedFuture(null);
+ }
+ Log.i(this, "checkAndRejectIncomingCall found a ringing call");
+
+ try {
+ ringingCall.hangup();
+ CompletableFuture<Boolean> future = new CompletableFuture<>();
+ com.android.internal.telephony.Connection cn = ringingCall.getLatestConnection();
+ cn.addListener(new OnDisconnectListener(future));
+ // 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_REJECT_INCOMING_CALL_TIMEOUT_MS);
+ // Ensure that the Consumer is completed on the main thread.
+ return future.acceptEitherAsync(timeout, completeConsumer,
+ phone.getContext().getMainExecutor()).exceptionally((ex) -> {
+ Log.w(this, "checkAndRejectIncomingCall - exceptionally= " + ex);
+ return null;
+ });
+ } catch (Exception e) {
+ Log.w(this, "checkAndRejectIncomingCall - exception= " + e.getMessage());
+ completeConsumer.accept(false);
+ return CompletableFuture.completedFuture(null);
+ }
+ }
+
+ /**
* 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
* address, and one of them is the default voice Phone, consider the default voice phone
@@ -3598,6 +3840,11 @@
@VisibleForTesting
public boolean isAvailableForEmergencyCalls(Phone phone,
@EmergencyNumber.EmergencyCallRouting int routing) {
+ if (isCallDisallowedDueToSatellite(phone)) {
+ // Phone is connected to satellite due to which it is not preferred for emergency call.
+ return false;
+ }
+
if (phone.getImsRegistrationTech() == ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM) {
// When a Phone is registered to Cross-SIM calling, there must always be a Phone on the
// other sub which is registered to cellular, so that must be selected.
@@ -3906,10 +4153,34 @@
return origAccountHandle;
}
+ /*
+ * Returns true if both existing connections on-device and the incoming connection support HOLD,
+ * false otherwise. Assumes that a TelephonyConference supports HOLD.
+ */
+ private boolean allCallsSupportHold(@NonNull TelephonyConnection incomingConnection) {
+ if (Flags.callExtraForNonHoldSupportedCarriers()) {
+ if (getAllConnections().stream()
+ .filter(c ->
+ // Exclude multiendpoint calls as they're not on this device.
+ (c.getConnectionProperties() & Connection.PROPERTY_IS_EXTERNAL_CALL)
+ == 0
+ && (c.getConnectionCapabilities()
+ & Connection.CAPABILITY_SUPPORT_HOLD) != 0).count() == 0) {
+ return false;
+ }
+ if ((incomingConnection.getConnectionCapabilities()
+ & Connection.CAPABILITY_SUPPORT_HOLD) == 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
- * For the passed in incoming {@link TelephonyConnection}, for non- dual active voice devices,
+ * 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.
+ * subscription (ie phone account handle) than the one passed in. For dual active voice devices,
+ * still sets the EXTRA if either subscription has connections that don't support hold.
* @param connection The connection.
* @param phoneAccountHandle The {@link PhoneAccountHandle} the incoming call originated on;
* this is passed in because
@@ -3919,10 +4190,11 @@
*/
public void maybeIndicateAnsweringWillDisconnect(@NonNull TelephonyConnection connection,
@NonNull PhoneAccountHandle phoneAccountHandle) {
- if (mTelephonyManagerProxy.isConcurrentCallsPossible()) {
- return;
- }
if (isCallPresentOnOtherSub(phoneAccountHandle)) {
+ if (mTelephonyManagerProxy.isConcurrentCallsPossible()
+ && allCallsSupportHold(connection)) {
+ return;
+ }
Log.i(this, "maybeIndicateAnsweringWillDisconnect; answering call %s will cause a call "
+ "on another subscription to drop.", connection.getTelecomCallId());
Bundle extras = new Bundle();
@@ -3947,13 +4219,16 @@
/**
* Where there are ongoing calls on another subscription other than the one specified,
- * 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.
+ * 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.
* @param incomingHandle The incoming {@link PhoneAccountHandle}.
+ * @param answeringDropsFgCall Whether for dual-SIM dual active devices, answering the incoming
+ * call should drop the second call.
*/
- public void maybeDisconnectCallsOnOtherSubs(@NonNull PhoneAccountHandle incomingHandle) {
+ public void maybeDisconnectCallsOnOtherSubs(
+ @NonNull PhoneAccountHandle incomingHandle, boolean answeringDropsFgCall) {
Log.i(this, "maybeDisconnectCallsOnOtherSubs: check for calls not on %s", incomingHandle);
- maybeDisconnectCallsOnOtherSubs(getAllConnections(), incomingHandle,
+ maybeDisconnectCallsOnOtherSubs(getAllConnections(), incomingHandle, answeringDropsFgCall,
mTelephonyManagerProxy);
}
@@ -3963,13 +4238,16 @@
* the core functionality.
* @param connections the calls to check.
* @param incomingHandle the incoming handle.
+ * @param answeringDropsFgCall Whether for dual-SIM dual active devices, answering the incoming
+ * call should drop the second call.
* @param telephonyManagerProxy the proxy to the {@link TelephonyManager} instance.
*/
@VisibleForTesting
public static void maybeDisconnectCallsOnOtherSubs(@NonNull Collection<Connection> connections,
@NonNull PhoneAccountHandle incomingHandle,
+ boolean answeringDropsFgCall,
TelephonyManagerProxy telephonyManagerProxy) {
- if (telephonyManagerProxy.isConcurrentCallsPossible()) {
+ if (telephonyManagerProxy.isConcurrentCallsPossible() && !answeringDropsFgCall) {
return;
}
connections.stream()
@@ -4217,6 +4495,11 @@
private void handleEmergencyCallStartedForSatelliteSOSMessageRecommender(
@NonNull TelephonyConnection connection, @NonNull Phone phone) {
+ if (!phone.getContext().getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_SATELLITE)) {
+ return;
+ }
+
if (mSatelliteSOSMessageRecommender == null) {
mSatelliteSOSMessageRecommender = new SatelliteSOSMessageRecommender(phone.getContext(),
phone.getContext().getMainLooper());
@@ -4240,19 +4523,16 @@
return false;
}
- ServiceState serviceState = phone.getServiceState();
- if (!serviceState.isUsingNonTerrestrialNetwork()) {
+ if (!mSatelliteController.isInSatelliteModeForCarrierRoaming(phone)) {
// Device is not connected to satellite
return false;
}
- for (NetworkRegistrationInfo nri : serviceState.getNetworkRegistrationInfoList()) {
- if (nri.isNonTerrestrialNetwork()
- && nri.getAvailableServices().contains(
- NetworkRegistrationInfo.SERVICE_TYPE_VOICE)) {
- // Call is supported while using satellite
- return false;
- }
+ List<Integer> capabilities =
+ mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(phone);
+ if (capabilities.contains(NetworkRegistrationInfo.SERVICE_TYPE_VOICE)) {
+ // Call is supported while using satellite
+ return false;
}
// Call is disallowed while using satellite
diff --git a/src/com/android/services/telephony/domainselection/CarrierConfigHelper.java b/src/com/android/services/telephony/domainselection/CarrierConfigHelper.java
deleted file mode 100644
index d39a6b7..0000000
--- a/src/com/android/services/telephony/domainselection/CarrierConfigHelper.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.AccessNetworkConstants.AccessNetworkType.NGRAN;
-import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PersistableBundle;
-import android.os.SystemProperties;
-import android.preference.PreferenceManager;
-import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.util.ArrayMap;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.phone.R;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/** Helper class to cache carrier configurations. */
-public class CarrierConfigHelper extends Handler {
- private static final String TAG = "CarrierConfigHelper";
- private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1);
-
- @VisibleForTesting
- public static final String KEY_VONR_EMERGENCY_SUPPORT = "vonr_emergency_support";
-
- private final Context mContext;
- private final CarrierConfigManager mConfigManager;
- private final TelephonyManager mTelephonyManager;
- private final ArrayMap<Integer, Boolean> mVoNrSupported = new ArrayMap<>();
-
- private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
- (slotIndex, subId, carrierId, specificCarrierId) -> onCarrierConfigurationChanged(
- slotIndex, subId, carrierId);
-
- // For test purpose only
- private final SharedPreferences mSharedPreferences;
-
- private List<Integer> mIgnoreNrWhenSimRemoved = null;
-
- /**
- * Creates an instance.
- *
- * @param context The Context this is associated with.
- * @param looper The Looper to run the CarrierConfigHelper.
- */
- public CarrierConfigHelper(@NonNull Context context, @NonNull Looper looper) {
- this(context, looper, null);
- }
-
- /**
- * Creates an instance.
- *
- * @param context The Context this is associated with.
- * @param looper The Looper to run the CarrierConfigHelper.
- * @param sharedPreferences The SharedPreferences instance.
- */
- @VisibleForTesting
- public CarrierConfigHelper(@NonNull Context context, @NonNull Looper looper,
- @Nullable SharedPreferences sharedPreferences) {
- super(looper);
-
- mContext = context;
- mTelephonyManager = context.getSystemService(TelephonyManager.class);
- mConfigManager = context.getSystemService(CarrierConfigManager.class);
- mConfigManager.registerCarrierConfigChangeListener(this::post,
- mCarrierConfigChangeListener);
- mSharedPreferences = sharedPreferences;
-
- readFromSharedPreference();
- readResourceConfiguration();
- }
-
- /**
- * Returns whether VoNR emergency was supported with the last valid subscription.
- *
- * @param slotIndex The SIM slot index.
- * @return true if VoNR emergency was supported with the last valid subscription.
- * Otherwise, false.
- */
- public boolean isVoNrEmergencySupported(int slotIndex) {
- return mVoNrSupported.get(Integer.valueOf(slotIndex));
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch(msg.what) {
- default:
- super.handleMessage(msg);
- break;
- }
- }
-
- private void readFromSharedPreference() {
- mVoNrSupported.clear();
- int modemCount = mTelephonyManager.getActiveModemCount();
- SharedPreferences sp = (mSharedPreferences != null) ? mSharedPreferences
- : PreferenceManager.getDefaultSharedPreferences(mContext);
- for (int i = 0; i < modemCount; i++) {
- Boolean savedConfig = Boolean.valueOf(
- sp.getBoolean(KEY_VONR_EMERGENCY_SUPPORT + i, false));
- mVoNrSupported.put(Integer.valueOf(i), savedConfig);
- Log.i(TAG, "readFromSharedPreference slot=" + i + ", " + savedConfig);
- }
- }
-
- private void onCarrierConfigurationChanged(int slotIndex, int subId, int carrierId) {
- Log.i(TAG, "onCarrierConfigurationChanged slotIndex=" + slotIndex
- + ", subId=" + subId + ", carrierId=" + carrierId);
-
- if (slotIndex < 0
- || !SubscriptionManager.isValidSubscriptionId(subId)
- || mTelephonyManager.getSimState(slotIndex) != TelephonyManager.SIM_STATE_READY) {
- return;
- }
-
- PersistableBundle b = mConfigManager.getConfigForSubId(subId,
- KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY);
- if (b.isEmpty()) {
- Log.e(TAG, "onCarrierConfigurationChanged empty result");
- return;
- }
-
- if (!CarrierConfigManager.isConfigForIdentifiedCarrier(b)) {
- Log.i(TAG, "onCarrierConfigurationChanged not carrier specific configuration");
- return;
- }
-
- int[] imsRatsConfig = b.getIntArray(
- KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY);
- if (imsRatsConfig == null) imsRatsConfig = new int[0];
- boolean carrierConfig = false;
- for (int i = 0; i < imsRatsConfig.length; i++) {
- if (imsRatsConfig[i] == NGRAN) {
- carrierConfig = true;
- break;
- }
- }
- if (mIgnoreNrWhenSimRemoved.contains(carrierId)) carrierConfig = false;
-
- Boolean savedConfig = mVoNrSupported.get(Integer.valueOf(slotIndex));
- if (carrierConfig == savedConfig) {
- return;
- }
-
- mVoNrSupported.put(Integer.valueOf(slotIndex), Boolean.valueOf(carrierConfig));
-
- SharedPreferences sp = (mSharedPreferences != null) ? mSharedPreferences
- : PreferenceManager.getDefaultSharedPreferences(mContext);
- SharedPreferences.Editor editor = sp.edit();
- editor.putBoolean(KEY_VONR_EMERGENCY_SUPPORT + slotIndex, carrierConfig);
- editor.apply();
-
- Log.i(TAG, "onCarrierConfigurationChanged preference updated slotIndex=" + slotIndex
- + ", supported=" + carrierConfig);
- }
-
- private void readResourceConfiguration() {
- try {
- mIgnoreNrWhenSimRemoved = Arrays.stream(mContext.getResources().getIntArray(
- R.array.config_carriers_ignore_ngran_preference_when_sim_removed))
- .boxed().collect(Collectors.toList());
- } catch (Resources.NotFoundException nfe) {
- Log.e(TAG, "readResourceConfiguration exception=" + nfe);
- } catch (NullPointerException npe) {
- Log.e(TAG, "readResourceConfiguration exception=" + npe);
- }
- if (mIgnoreNrWhenSimRemoved == null) {
- mIgnoreNrWhenSimRemoved = new ArrayList<Integer>();
- }
- Log.i(TAG, "readResourceConfiguration ignoreNrWhenSimRemoved=" + mIgnoreNrWhenSimRemoved);
- }
-
- /** Destroys the instance. */
- public void destroy() {
- if (DBG) Log.d(TAG, "destroy");
- mConfigManager.unregisterCarrierConfigChangeListener(mCarrierConfigChangeListener);
- }
-}
diff --git a/src/com/android/services/telephony/domainselection/CrossSimRedialingController.java b/src/com/android/services/telephony/domainselection/CrossSimRedialingController.java
index 44904f4..d368d46 100644
--- a/src/com/android/services/telephony/domainselection/CrossSimRedialingController.java
+++ b/src/com/android/services/telephony/domainselection/CrossSimRedialingController.java
@@ -29,9 +29,12 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.os.SystemProperties;
+import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.CarrierConfigManager;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneNumberUtils;
+import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.emergency.EmergencyNumber;
@@ -144,7 +147,7 @@
* @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 inService Indicates 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
*/
@@ -228,12 +231,26 @@
}
/**
+ * Returns whether there is another slot with which normal service is available.
+ *
+ * @return {@code true} if there is another slot with which normal service is available.
+ * {@code false} otherwise.
+ */
+ public boolean isThereOtherSlotInService() {
+ return isThereOtherSlot(true);
+ }
+
+ /**
* Returns whether there is another slot emergency capable.
*
* @return {@code true} if there is another slot emergency capable,
* {@code false} otherwise.
*/
public boolean isThereOtherSlot() {
+ return isThereOtherSlot(false);
+ }
+
+ private boolean isThereOtherSlot(boolean networkRegisteredOnly) {
logi("isThereOtherSlot modemCount=" + mModemCount);
if (mModemCount < 2) return false;
@@ -254,7 +271,13 @@
int subId = SubscriptionManager.getSubscriptionId(i);
if (mEmergencyNumberHelper.isEmergencyNumber(subId, mNumber)) {
logi("isThereOtherSlot index=" + i + "(" + subId + "), found");
- return true;
+ if (networkRegisteredOnly) {
+ if (isNetworkRegistered(subId)) {
+ return true;
+ }
+ } else {
+ return true;
+ }
} else {
logi("isThereOtherSlot index=" + i + "(" + subId + "), not emergency number");
}
@@ -263,6 +286,31 @@
return false;
}
+ private boolean isNetworkRegistered(int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) return false;
+
+ TelephonyManager tm = mTelephonyManager.createForSubscriptionId(subId);
+ ServiceState ss = tm.getServiceState();
+ if (ss != null) {
+ NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (nri != null && nri.isNetworkRegistered()) {
+ // PS is IN_SERVICE state.
+ return true;
+ }
+ nri = ss.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_CS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (nri != null && nri.isNetworkRegistered()) {
+ // CS is IN_SERVICE state.
+ return true;
+ }
+ }
+ logi("isNetworkRegistered subId=" + subId + " not network registered");
+ return false;
+ }
+
/**
* Caches the configuration.
*/
diff --git a/src/com/android/services/telephony/domainselection/DataConnectionStateHelper.java b/src/com/android/services/telephony/domainselection/DataConnectionStateHelper.java
new file mode 100644
index 0000000..8fbf7e3
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/DataConnectionStateHelper.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2024 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.SubscriptionManager.EXTRA_SLOT_INDEX;
+import static android.telephony.SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+import static android.telephony.TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED;
+import static android.telephony.TelephonyManager.EXTRA_PHONE_IN_ECM_STATE;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemProperties;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PreciseDataConnectionState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
+import android.util.ArrayMap;
+import android.util.Log;
+
+/** Helper class to cache emergency data connection state. */
+public class DataConnectionStateHelper extends Handler {
+ private static final String TAG = "DataConnectionStateHelper";
+ private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1);
+
+ /**
+ * TelephonyCallback used to monitor ePDN state.
+ */
+ private static final class DataConnectionStateListener extends TelephonyCallback
+ implements TelephonyCallback.PreciseDataConnectionStateListener {
+
+ private final Handler mHandler;
+ private final TelephonyManager mTelephonyManager;
+ private final DataConnectionStateHelper mOwner;
+ private final int mSubId;
+ private final int mSlotIndex;
+ private int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ private int mState = TelephonyManager.DATA_UNKNOWN;
+
+ DataConnectionStateListener(Handler handler, TelephonyManager tm,
+ DataConnectionStateHelper owner, int subId, int slotIndex) {
+ mHandler = handler;
+ mTelephonyManager = tm;
+ mOwner = owner;
+ mSubId = subId;
+ mSlotIndex = slotIndex;
+ }
+
+ @Override
+ public void onPreciseDataConnectionStateChanged(
+ @NonNull PreciseDataConnectionState dataConnectionState) {
+ ApnSetting apnSetting = dataConnectionState.getApnSetting();
+ if ((apnSetting == null)
+ || ((apnSetting.getApnTypeBitmask() & ApnSetting.TYPE_EMERGENCY) == 0)) {
+ return;
+ }
+ mTransportType = dataConnectionState.getTransportType();
+ mState = dataConnectionState.getState();
+ mOwner.notifyDataConnectionStateChange(mSlotIndex, mState);
+ Log.i(TAG, "onPreciseDataConnectionStateChanged ePDN state=" + mState
+ + ", transport=" + mTransportType + ", subId=" + mSubId);
+ }
+
+ public void registerTelephonyCallback() {
+ Log.i(TAG, "registerTelephonyCallback subId=" + mSubId);
+ TelephonyManager tm = mTelephonyManager.createForSubscriptionId(mSubId);
+ tm.registerTelephonyCallback(mHandler::post, this);
+ }
+
+ public void unregisterTelephonyCallback() {
+ Log.i(TAG, "unregisterTelephonyCallback subId=" + mSubId);
+ mTelephonyManager.unregisterTelephonyCallback(this);
+ }
+
+ public int getSubId() {
+ return mSubId;
+ }
+
+ public int getTransportType() {
+ return mTransportType;
+ }
+
+ public int getState() {
+ return mState;
+ }
+ }
+
+ private final Context mContext;
+ private final TelephonyManager mTelephonyManager;
+ private final CarrierConfigManager mConfigManager;
+
+ private final ArrayMap<Integer, DataConnectionStateListener>
+ mDataConnectionStateListeners = new ArrayMap<>();
+
+ private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
+ (slotIndex, subId, carrierId, specificCarrierId) -> onCarrierConfigChanged(
+ slotIndex, subId, carrierId);
+
+ private EmergencyCallDomainSelector mSelector;
+
+ /**
+ * Creates an instance.
+ *
+ * @param context The Context this is associated with.
+ * @param looper The Looper to run the DataConnectionStateHelper.
+ */
+ public DataConnectionStateHelper(@NonNull Context context, @NonNull Looper looper) {
+ super(looper);
+
+ mContext = context;
+ mTelephonyManager = context.getSystemService(TelephonyManager.class);
+ mConfigManager = context.getSystemService(CarrierConfigManager.class);
+ mConfigManager.registerCarrierConfigChangeListener(this::post,
+ mCarrierConfigChangeListener);
+ }
+
+ /**
+ * Returns whether it is in emergency callback mode.
+ *
+ * @param slotIndex The logical SIM slot index.
+ * @return true if it is in emergency callback mode.
+ */
+ public boolean isInEmergencyCallbackMode(int slotIndex) {
+ Intent intent = mContext.registerReceiver(null,
+ new IntentFilter(ACTION_EMERGENCY_CALLBACK_MODE_CHANGED));
+ if (intent != null
+ && ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(intent.getAction())) {
+ boolean inEcm = intent.getBooleanExtra(EXTRA_PHONE_IN_ECM_STATE, false);
+ int index = intent.getIntExtra(EXTRA_SLOT_INDEX, INVALID_SIM_SLOT_INDEX);
+ Log.i(TAG, "isInEmergencyCallbackMode inEcm=" + inEcm + ", slotIndex=" + index);
+ return inEcm && (slotIndex == index);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the transport type of emergency data connection.
+ *
+ * @param slotIndex The logical SIM slot index.
+ * @return the transport type of emergency data connection.
+ */
+ public int getTransportType(int slotIndex) {
+ DataConnectionStateListener listener =
+ mDataConnectionStateListeners.get(Integer.valueOf(slotIndex));
+ if (listener == null) return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ Log.i(TAG, "getTransportType " + listener.getTransportType());
+ return listener.getTransportType();
+ }
+
+ /**
+ * Returns the data connection state.
+ *
+ * @param slotIndex The logical SIM slot index.
+ * @return the data connection state.
+ */
+ public int getDataConnectionState(int slotIndex) {
+ DataConnectionStateListener listener =
+ mDataConnectionStateListeners.get(Integer.valueOf(slotIndex));
+ if (listener == null) return TelephonyManager.DATA_UNKNOWN;
+ Log.i(TAG, "getDataConnectionState " + listener.getState());
+ return listener.getState();
+ }
+
+ /**
+ * Sets the EmergencyCallDomainSelector instance.
+ *
+ * @param selector The instance of {@link EmergencyCallDomainSelector}.
+ */
+ public void setEmergencyCallDomainSelector(EmergencyCallDomainSelector selector) {
+ mSelector = selector;
+ }
+
+ private void notifyDataConnectionStateChange(int slotIndex, int state) {
+ EmergencyCallDomainSelector selector = mSelector;
+ if (selector != null) {
+ Log.i(TAG, "notifyDataConnectionStateChange slot=" + slotIndex + ", state=" + state);
+ selector.notifyDataConnectionStateChange(slotIndex, state);
+ }
+ }
+
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ default:
+ super.handleMessage(msg);
+ break;
+ }
+ }
+
+ private void onCarrierConfigChanged(int slotIndex, int subId, int carrierId) {
+ Log.i(TAG, "onCarrierConfigChanged slotIndex=" + slotIndex
+ + ", subId=" + subId + ", carrierId=" + carrierId);
+
+ if (slotIndex < 0) {
+ return;
+ }
+
+ DataConnectionStateListener listener =
+ mDataConnectionStateListeners.get(Integer.valueOf(slotIndex));
+
+ // Remove stale listener.
+ if (listener != null && listener.getSubId() != subId) {
+ listener.unregisterTelephonyCallback();
+ mDataConnectionStateListeners.remove(Integer.valueOf(slotIndex));
+ listener = null;
+ }
+
+ if (listener == null
+ && SubscriptionManager.isValidSubscriptionId(subId)) {
+ listener = new DataConnectionStateListener(this, mTelephonyManager,
+ this, subId, slotIndex);
+ listener.registerTelephonyCallback();
+ mDataConnectionStateListeners.put(Integer.valueOf(slotIndex), listener);
+ }
+ }
+
+ /** Destroys the instance. */
+ public void destroy() {
+ if (DBG) Log.d(TAG, "destroy");
+ mConfigManager.unregisterCarrierConfigChangeListener(mCarrierConfigChangeListener);
+ mDataConnectionStateListeners.forEach((k, v) -> v.unregisterTelephonyCallback());
+ }
+}
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
index 3d6a4d1..18c03ac 100644
--- a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -42,9 +42,11 @@
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_IMS_REASONINFO_CODE_TO_RETRY_EMERGENCY_INT_ARRAY;
import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_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.KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_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;
@@ -53,7 +55,13 @@
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 static android.telephony.PreciseDisconnectCause.NO_VALID_SIM;
import static android.telephony.PreciseDisconnectCause.SERVICE_OPTION_NOT_AVAILABLE;
+import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
+import static android.telephony.TelephonyManager.DATA_CONNECTED;
+import static android.telephony.TelephonyManager.DATA_DISCONNECTED;
+import static android.telephony.TelephonyManager.DATA_DISCONNECTING;
+import static android.telephony.TelephonyManager.DATA_UNKNOWN;
import android.annotation.NonNull;
import android.content.Context;
@@ -76,15 +84,15 @@
import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.DomainSelectionService.SelectionAttributes;
-import android.telephony.EmergencyRegResult;
+import android.telephony.EmergencyRegistrationResult;
import android.telephony.NetworkRegistrationInfo;
-import android.telephony.PhoneNumberUtils;
+import android.telephony.SubscriptionInfo;
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.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
import android.text.TextUtils;
import android.util.LocalLog;
@@ -94,10 +102,9 @@
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;
+import java.util.stream.Collectors;
/**
* Selects the domain for emergency calling.
@@ -108,18 +115,34 @@
private static final boolean DBG = (SystemProperties.getInt("ro.debuggable", 0) == 1);
private static final int LOG_SIZE = 50;
+ /**
+ * Timeout before we requests network scan without waiting for the disconnection
+ * of ePDN.
+ */
+ private static final int DEFAULT_DATA_DISCONNECTION_TIMEOUT_MS = 2 * 1000; // 2 seconds
+
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;
@VisibleForTesting
public static final int MSG_MAX_CELLULAR_TIMEOUT = 14;
+ @VisibleForTesting
+ public static final int MSG_WAIT_DISCONNECTION_TIMEOUT = 15;
private static final int NOT_SUPPORTED = -1;
+ private static List<Integer> sDefaultRetryReasonCodes = List.of(
+ ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED,
+ ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR,
+ ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED,
+ ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL);
+
private static final LocalLog sLocalLog = new LocalLog(LOG_SIZE);
private static List<String> sSimReadyAllowList;
+ private static List<String> sPreferSlotWithNormalServiceList;
+ private static List<String> sPreferCsAfterCsfbFailure;
/**
* Network callback used to determine whether Wi-Fi is connected or not.
@@ -159,9 +182,9 @@
private @TransportType int mLastTransportType = TRANSPORT_TYPE_INVALID;
private @DomainSelectionService.EmergencyScanType int mScanType;
private @RadioAccessNetworkType List<Integer> mLastPreferredNetworks;
- private boolean mIsTestEmergencyNumber;
private CancellationSignal mCancelSignal;
+ private EmergencyRegistrationResult mLastRegResult;
// Members for carrier configuration
private @RadioAccessNetworkType int[] mImsRatsConfig;
@@ -182,13 +205,16 @@
private boolean mRequiresImsRegistration;
private boolean mRequiresVoLteEnabled;
private boolean mLtePreferredAfterNrFailure;
+ private boolean mScanLimitedOnlyAfterVolteFailure;
+ private List<Integer> mRetryReasonCodes;
// Members for states
private boolean mIsMonitoringConnectivity;
private boolean mWiFiAvailable;
private boolean mWasCsfbAfterPsFailure;
private boolean mTryCsWhenPsFails;
- private boolean mTryEpsFallback;
+ private boolean mTryEsFallback;
+ private boolean mIsWaitingForDataDisconnection;
private int mModemCount;
/** Indicates whether this instance is deactivated. */
@@ -210,14 +236,14 @@
private final PowerManager.WakeLock mPartialWakeLock;
private final CrossSimRedialingController mCrossSimRedialingController;
- private final CarrierConfigHelper mCarrierConfigHelper;
+ private final DataConnectionStateHelper mEpdnHelper;
/** Constructor. */
public EmergencyCallDomainSelector(Context context, int slotId, int subId,
@NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
@NonNull DestroyListener destroyListener,
@NonNull CrossSimRedialingController csrController,
- @NonNull CarrierConfigHelper carrierConfigHelper) {
+ @NonNull DataConnectionStateHelper epdnHelper) {
super(context, slotId, subId, looper, imsStateTracker, destroyListener, TAG);
mImsStateTracker.addBarringInfoListener(this);
@@ -227,7 +253,8 @@
mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
mCrossSimRedialingController = csrController;
- mCarrierConfigHelper = carrierConfigHelper;
+ mEpdnHelper = epdnHelper;
+ epdnHelper.setEmergencyCallDomainSelector(this);
acquireWakeLock();
}
@@ -245,13 +272,17 @@
break;
case MSG_NETWORK_SCAN_RESULT:
- handleScanResult((EmergencyRegResult) msg.obj);
+ handleScanResult((EmergencyRegistrationResult) msg.obj);
break;
case MSG_MAX_CELLULAR_TIMEOUT:
handleMaxCellularTimeout();
break;
+ case MSG_WAIT_DISCONNECTION_TIMEOUT:
+ requestScanDelayed();
+ break;
+
default:
super.handleMessage(msg);
break;
@@ -263,7 +294,7 @@
*
* @param result The scan result.
*/
- private void handleScanResult(EmergencyRegResult result) {
+ private void handleScanResult(EmergencyRegistrationResult result) {
logi("handleScanResult result=" + result);
if (mLastTransportType == TRANSPORT_TYPE_WLAN) {
@@ -282,7 +313,7 @@
&& (mScanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE)) {
mScanType = DomainSelectionService.SCAN_TYPE_LIMITED_SERVICE;
mWwanSelectorCallback.onRequestEmergencyNetworkScan(
- mLastPreferredNetworks, mScanType, mCancelSignal,
+ mLastPreferredNetworks, mScanType, false, mCancelSignal,
(regResult) -> {
logi("requestScan-onComplete");
sendMessage(obtainMessage(MSG_NETWORK_SCAN_RESULT, regResult));
@@ -294,9 +325,11 @@
return;
}
+ mLastRegResult = result;
removeMessages(MSG_NETWORK_SCAN_TIMEOUT);
onWwanNetworkTypeSelected(getAccessNetworkType(result));
mCancelSignal = null;
+ maybeModifyScanType(mLastNetworkType);
}
/**
@@ -305,7 +338,7 @@
* @param result The result of network scan.
* @return The selected network type.
*/
- private @RadioAccessNetworkType int getAccessNetworkType(EmergencyRegResult result) {
+ private @RadioAccessNetworkType int getAccessNetworkType(EmergencyRegistrationResult result) {
int accessNetworkType = result.getAccessNetwork();
if (accessNetworkType != EUTRAN) return accessNetworkType;
@@ -323,12 +356,6 @@
}
@Override
- public void cancelSelection() {
- logi("cancelSelection");
- finishSelection();
- }
-
- @Override
public void reselectDomain(SelectionAttributes attr) {
logi("reselectDomain attr=" + attr);
mSelectionAttributes = attr;
@@ -338,12 +365,11 @@
private void reselectDomain() {
logi("reselectDomain tryCsWhenPsFails=" + mTryCsWhenPsFails);
- int cause = mSelectionAttributes.getCsDisconnectCause();
+ int cause = getDisconnectCause();
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) {
+ if ((cause == EMERGENCY_TEMP_FAILURE && mCrossSimRedialingController.isThereOtherSlot())
+ || cause == EMERGENCY_PERM_FAILURE) {
logi("reselectDomain should redial on the other subscription");
terminateSelectionForCrossSimRedialing(cause == EMERGENCY_PERM_FAILURE);
return;
@@ -355,8 +381,8 @@
return;
}
- if (mIsTestEmergencyNumber) {
- selectDomainForTestEmergencyNumber();
+ if (maybeTerminateSelection(cause)) {
+ logi("reselectDomain terminate selection");
return;
}
@@ -374,7 +400,7 @@
if (mWasCsfbAfterPsFailure) {
mWasCsfbAfterPsFailure = false;
- if (cause == SERVICE_OPTION_NOT_AVAILABLE) {
+ if (preferCsAfterCsfbFailure(cause)) {
// b/299875872, combined attach but EXTENDED_SERVICE_REQUEST failed.
// Try CS preferred scan instead of PS preferred scan.
mLastNetworkType = EUTRAN;
@@ -393,23 +419,94 @@
}
}
+ if (mLastTransportType == TRANSPORT_TYPE_WWAN) {
+ if (mLastNetworkType == NGRAN && (!mTryEsFallback) && mLtePreferredAfterNrFailure) {
+ int state = mEpdnHelper.getDataConnectionState(getSlotId());
+ if (state != DATA_DISCONNECTED && state != DATA_UNKNOWN) {
+ mIsWaitingForDataDisconnection = true;
+ // If deactivation of ePDN has been started, then wait for the disconnection
+ // with the timeout of 2 seconds and then request network scan.
+ // If deactivation of ePDN hasn't been started yet, then wait for the start
+ // of the deactivation with the timeout of 2 seconds.
+ // The timer shall be restarted in notifyDataConnectionStateChange()
+ // when starting the deactivation.
+ sendEmptyMessageDelayed(MSG_WAIT_DISCONNECTION_TIMEOUT,
+ DEFAULT_DATA_DISCONNECTION_TIMEOUT_MS);
+ mDomainSelected = false;
+ return;
+ }
+ }
+ }
+
if (mLastTransportType == TRANSPORT_TYPE_WLAN) {
// Dialing over Wi-Fi failed. Try scanning cellular networks.
onWwanSelected(this::reselectDomainInternal);
return;
}
+ if (mLastNetworkType == EUTRAN && mLastRegResult != null
+ && mSelectionAttributes.getPsDisconnectCause() != null) {
+ int regState = mLastRegResult.getRegState();
+ int reasonCode = mSelectionAttributes.getPsDisconnectCause().getCode();
+ if (reasonCode == ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED
+ && regState != REGISTRATION_STATE_HOME
+ && regState != REGISTRATION_STATE_ROAMING) {
+ // b/326292100, ePDN setup failed in limited state, request PS preferred scan.
+ mLastNetworkType = UNKNOWN;
+ }
+ }
+
requestScan(true);
mDomainSelected = false;
}
+ private boolean preferCsAfterCsfbFailure(int cause) {
+ if (cause != SERVICE_OPTION_NOT_AVAILABLE) return false;
+ if (sPreferCsAfterCsfbFailure == null || mLastRegResult == null
+ || TextUtils.isEmpty(mLastRegResult.getCountryIso())) {
+ // Enabled by default if country is not identified.
+ return true;
+ }
+
+ return sPreferCsAfterCsfbFailure.contains(mLastRegResult.getCountryIso());
+ }
+
+ private int getDisconnectCause() {
+ int cause = mSelectionAttributes.getCsDisconnectCause();
+
+ ImsReasonInfo reasonInfo = mSelectionAttributes.getPsDisconnectCause();
+ if (reasonInfo != null) {
+ switch (reasonInfo.getCode()) {
+ case ImsReasonInfo.CODE_EMERGENCY_TEMP_FAILURE:
+ cause = EMERGENCY_TEMP_FAILURE;
+ break;
+ case ImsReasonInfo.CODE_EMERGENCY_PERM_FAILURE:
+ cause = EMERGENCY_PERM_FAILURE;
+ break;
+ default:
+ break;
+ }
+ }
+ return cause;
+ }
+
private void reselectDomainInternal() {
post(() -> {
+ if (mDestroyed) return;
requestScan(true, false, true);
mDomainSelected = false;
});
}
+ private void requestScanDelayed() {
+ logi("requestScanDelayed waiting=" + mIsWaitingForDataDisconnection);
+ if (!mDestroyed && mIsWaitingForDataDisconnection) {
+ requestScan(true);
+ removeMessages(MSG_WAIT_DISCONNECTION_TIMEOUT);
+ }
+ mIsWaitingForDataDisconnection = false;
+ }
+
@Override
public void finishSelection() {
logi("finishSelection");
@@ -434,7 +531,7 @@
logi("selectDomain attr=" + attr);
mTransportSelectorCallback = cb;
mSelectionAttributes = attr;
- mIsTestEmergencyNumber = isTestEmergencyNumber(attr.getNumber());
+ mLastRegResult = mSelectionAttributes.getEmergencyRegistrationResult();
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
mModemCount = tm.getActiveModemCount();
@@ -490,7 +587,27 @@
*/
private void updateCarrierConfiguration() {
CarrierConfigManager configMgr = mContext.getSystemService(CarrierConfigManager.class);
- PersistableBundle b = configMgr.getConfigForSubId(getSubId());
+ PersistableBundle b = configMgr.getConfigForSubId(getSubId(),
+ KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ KEY_EMERGENCY_OVER_IMS_ROAMING_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ KEY_EMERGENCY_OVER_CS_ROAMING_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY,
+ KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY,
+ KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY,
+ KEY_PREFER_IMS_EMERGENCY_WHEN_VOICE_CALLS_ON_CS_BOOL,
+ KEY_EMERGENCY_VOWIFI_REQUIRES_CONDITION_INT,
+ KEY_EMERGENCY_SCAN_TIMER_SEC_INT,
+ KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT,
+ KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT,
+ KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL,
+ KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT,
+ KEY_EMERGENCY_CALL_SETUP_TIMER_ON_CURRENT_NETWORK_SEC_INT,
+ KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL,
+ KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL,
+ KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL,
+ KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_BOOL,
+ KEY_IMS_REASONINFO_CODE_TO_RETRY_EMERGENCY_INT_ARRAY,
+ KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY);
if (b == null) {
b = CarrierConfigManager.getDefaultConfig();
}
@@ -499,7 +616,6 @@
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);
- maybeModifyImsRats();
mCsRatsConfig =
b.getIntArray(KEY_EMERGENCY_OVER_CS_SUPPORTED_ACCESS_NETWORK_TYPES_INT_ARRAY);
@@ -521,7 +637,11 @@
mRequiresVoLteEnabled = b.getBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL);
mLtePreferredAfterNrFailure = b.getBoolean(
KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL);
+ mScanLimitedOnlyAfterVolteFailure = b.getBoolean(
+ KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_BOOL);
String[] numbers = b.getStringArray(KEY_EMERGENCY_CDMA_PREFERRED_NUMBERS_STRING_ARRAY);
+ int[] imsReasonCodes =
+ b.getIntArray(KEY_IMS_REASONINFO_CODE_TO_RETRY_EMERGENCY_INT_ARRAY);
if (mImsRatsConfig == null) mImsRatsConfig = new int[0];
if (mCsRatsConfig == null) mCsRatsConfig = new int[0];
@@ -530,6 +650,10 @@
if (mDomainPreference == null) mDomainPreference = new int[0];
if (mDomainPreferenceRoam == null) mDomainPreferenceRoam = new int[0];
if (numbers == null) numbers = new String[0];
+ if (imsReasonCodes == null) imsReasonCodes = new int[0];
+
+ mRetryReasonCodes = Arrays.stream(imsReasonCodes).boxed().collect(Collectors.toList());
+ mRetryReasonCodes.addAll(sDefaultRetryReasonCodes);
logi("updateCarrierConfiguration "
+ "imsRats=" + arrayToString(mImsRatsConfig,
@@ -556,6 +680,8 @@
+ ", requiresImsReg=" + mRequiresImsRegistration
+ ", requiresVoLteEnabled=" + mRequiresVoLteEnabled
+ ", ltePreferredAfterNr=" + mLtePreferredAfterNrFailure
+ + ", scanLimitedOnly=" + mScanLimitedOnlyAfterVolteFailure
+ + ", retryReasonCodes=" + mRetryReasonCodes
+ ", cdmaPreferredNumbers=" + arrayToString(numbers));
mCdmaPreferredNumbers = Arrays.asList(numbers);
@@ -569,40 +695,55 @@
}
}
- /** Adds NGRAN if SIM is absent or locked and the last valid subscription supported NGRAN. */
- private void maybeModifyImsRats() {
- if (mCarrierConfigHelper.isVoNrEmergencySupported(getSlotId())
- && !isSimReady() && mImsRatsConfig.length < 2) {
- // Default configuration includes only EUTRAN.
- mImsRatsConfig = new int[] { EUTRAN, NGRAN };
- mImsRoamRatsConfig = new int[] { EUTRAN, NGRAN };
- }
- }
-
/**
* Caches the resource configuration.
*/
private void readResourceConfiguration() {
- if (sSimReadyAllowList != null) return;
+ if (sSimReadyAllowList == null) {
+ sSimReadyAllowList = readResourceConfiguration(
+ R.array.config_countries_require_sim_for_emergency);
+ }
+ logi("readResourceConfiguration simReadyCountries=" + sSimReadyAllowList);
+
+ if (sPreferSlotWithNormalServiceList == null) {
+ sPreferSlotWithNormalServiceList = readResourceConfiguration(
+ R.array.config_countries_prefer_normal_service_capable_subscription);
+ }
+ logi("readResourceConfiguration preferNormalServiceCountries="
+ + sPreferSlotWithNormalServiceList);
+
+ if (sPreferCsAfterCsfbFailure == null) {
+ sPreferCsAfterCsfbFailure = readResourceConfiguration(
+ R.array.config_countries_prefer_cs_preferred_scan_after_csfb_failure);
+ }
+ logi("readResourceConfiguration preferCsAfterCsfbFailure="
+ + sPreferCsAfterCsfbFailure);
+ }
+
+ private List<String> readResourceConfiguration(int id) {
+ logi("readResourceConfiguration id=" + id);
+
+ List<String> resource = null;
try {
- sSimReadyAllowList = Arrays.asList(mContext.getResources().getStringArray(
- R.array.config_countries_require_sim_for_emergency));
+ resource = Arrays.asList(mContext.getResources().getStringArray(id));
} catch (Resources.NotFoundException nfe) {
loge("readResourceConfiguration exception=" + nfe);
} catch (NullPointerException npe) {
loge("readResourceConfiguration exception=" + npe);
} finally {
- if (sSimReadyAllowList == null) {
- sSimReadyAllowList = new ArrayList<String>();
+ if (resource == null) {
+ resource = new ArrayList<String>();
}
}
- logi("readResourceConfiguration simReadyCountries=" + sSimReadyAllowList);
+ return resource;
}
/** For test purpose only */
@VisibleForTesting
public void clearResourceConfiguration() {
sSimReadyAllowList = null;
+ sPreferSlotWithNormalServiceList = null;
+ sPreferCsAfterCsfbFailure = null;
}
private void selectDomain() {
@@ -624,13 +765,14 @@
// Reset mDomainSelectionRequested to avoid redundant execution of selectDomain().
mDomainSelectionRequested = false;
- if (!allowEmergencyCalls(mSelectionAttributes.getEmergencyRegResult())) {
+ if (!allowEmergencyCalls(mSelectionAttributes.getEmergencyRegistrationResult())) {
// Detected the country and found that emergency calls are not allowed with this slot.
terminateSelectionPermanentlyForSlot();
return;
}
- if (isWifiPreferred()) {
+ if (isWifiPreferred()
+ || isInEmergencyCallbackModeOnWlan()) {
onWlanSelected();
return;
}
@@ -643,8 +785,12 @@
}
private void selectDomainFromInitialState() {
- if (mIsTestEmergencyNumber) {
- selectDomainForTestEmergencyNumber();
+ if (mDestroyed) return;
+
+ if (isInEmergencyCallbackModeOnPsWwan()) {
+ logi("selectDomain PS cellular connected in ECBM");
+ mPsNetworkType = EUTRAN;
+ onWwanNetworkTypeSelected(mPsNetworkType);
return;
}
@@ -652,13 +798,28 @@
boolean psInService = isPsInService();
if (!csInService && !psInService) {
- mPsNetworkType = getSelectablePsNetworkType(false);
- logi("selectDomain limited service ps=" + accessNetworkTypeToString(mPsNetworkType));
- if (mPsNetworkType == UNKNOWN) {
- requestScan(true);
- } else {
- onWwanNetworkTypeSelected(mPsNetworkType);
+ if (maybeRedialOnTheOtherSlotInNormalService()) {
+ return;
}
+ mCsNetworkType = getSelectableCsNetworkType();
+ mPsNetworkType = getSelectablePsNetworkType(false);
+ logi("selectDomain limited service ps=" + accessNetworkTypeToString(mPsNetworkType)
+ + ", cs=" + accessNetworkTypeToString(mCsNetworkType));
+ if (!isInRoaming()
+ && (mPreferredNetworkScanType
+ == CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE)) {
+ requestScan(true);
+ return;
+ }
+ // If NGRAN, request scan to trigger emergency registration.
+ if (mPsNetworkType == EUTRAN) {
+ onWwanNetworkTypeSelected(mPsNetworkType);
+ } else if (mCsNetworkType != UNKNOWN) {
+ onWwanNetworkTypeSelected(mCsNetworkType);
+ } else {
+ requestScan(true);
+ }
+ maybeModifyScanType(mLastNetworkType);
return;
}
@@ -675,7 +836,8 @@
logi("selectDomain CS={" + csInService + ", " + accessNetworkTypeToString(mCsNetworkType)
+ "}, PS={" + psInService + ", " + accessNetworkTypeToString(mPsNetworkType) + "}");
if (csAvailable && psAvailable) {
- if (mPreferImsWhenCallsOnCs || isImsRegisteredWithVoiceCapability()) {
+ if (mSelectionAttributes.isExitedFromAirplaneMode()
+ || mPreferImsWhenCallsOnCs || isImsRegisteredWithVoiceCapability()) {
mTryCsWhenPsFails = true;
onWwanNetworkTypeSelected(mPsNetworkType);
} else if (isDeactivatedSim()) {
@@ -685,8 +847,9 @@
onWwanNetworkTypeSelected(mCsNetworkType);
}
} else if (psAvailable) {
- mTryEpsFallback = (mPsNetworkType == NGRAN) && isEpsFallbackAvailable();
- if (!mRequiresImsRegistration || isImsRegisteredWithVoiceCapability()) {
+ mTryEsFallback = (mPsNetworkType == NGRAN) && isEsFallbackAvailable();
+ if (mSelectionAttributes.isExitedFromAirplaneMode()
+ || !mRequiresImsRegistration || isImsRegisteredWithVoiceCapability()) {
onWwanNetworkTypeSelected(mPsNetworkType);
} else if (isDeactivatedSim()) {
// Deactivated SIM but PS is in service and supports emergency calls.
@@ -694,22 +857,24 @@
} else {
// Carrier configuration requires IMS registration for emergency services over PS,
// but not registered. Try CS emergency call.
- mTryEpsFallback = false;
+ mTryEsFallback = false;
requestScan(true, true);
}
} else if (csAvailable) {
onWwanNetworkTypeSelected(mCsNetworkType);
} else {
// PS is in service but not supports emergency calls.
- if (mRequiresImsRegistration && !isImsRegisteredWithVoiceCapability()) {
+ if (!mSelectionAttributes.isExitedFromAirplaneMode()
+ && 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();
+ mTryEsFallback = isEsFallbackAvailable();
requestScan(true);
}
}
+ maybeModifyScanType(mLastNetworkType);
}
/**
@@ -744,20 +909,21 @@
mCancelSignal = new CancellationSignal();
// In case dialing over Wi-Fi has failed, do not the change the domain preference.
- if (!wifiFailed) {
- mLastPreferredNetworks = getNextPreferredNetworks(csPreferred, mTryEpsFallback);
+ if (!wifiFailed || mLastPreferredNetworks == null) {
+ mLastPreferredNetworks = getNextPreferredNetworks(csPreferred, mTryEsFallback);
}
- mTryEpsFallback = false;
+ mTryEsFallback = false;
if (isInRoaming()
- && (mPreferredNetworkScanType == DomainSelectionService.SCAN_TYPE_FULL_SERVICE)) {
+ && (mPreferredNetworkScanType
+ == CarrierConfigManager.ImsEmergency.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,
+ mLastPreferredNetworks, mScanType, false, mCancelSignal,
(result) -> {
logi("requestScan-onComplete");
sendMessage(obtainMessage(MSG_NETWORK_SCAN_RESULT, result));
@@ -782,12 +948,12 @@
* 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.
+ * @param tryEsFallback Indicates whether scan requested for ES fallback.
* @return The list of preferred network types.
*/
@VisibleForTesting
public @RadioAccessNetworkType List<Integer> getNextPreferredNetworks(boolean csPreferred,
- boolean tryEpsFallback) {
+ boolean tryEsFallback) {
if (mRequiresVoLteEnabled && !isAdvancedCallingSettingEnabled()) {
// Emergency call over IMS is not supported.
logi("getNextPreferredNetworks VoLte setting is not enabled.");
@@ -800,10 +966,10 @@
int psPriority = domains.indexOf(DOMAIN_PS_3GPP);
int csPriority = domains.indexOf(DOMAIN_CS);
logi("getNextPreferredNetworks psPriority=" + psPriority + ", csPriority=" + csPriority
- + ", csPreferred=" + csPreferred + ", epsFallback=" + tryEpsFallback
+ + ", csPreferred=" + csPreferred + ", esFallback=" + tryEsFallback
+ ", lastNetworkType=" + accessNetworkTypeToString(mLastNetworkType));
- if (!csPreferred && (mLastNetworkType == UNKNOWN || tryEpsFallback)) {
+ if (!csPreferred && (mLastNetworkType == UNKNOWN || tryEsFallback)) {
// Generate the list per the domain preference.
if (psPriority == NOT_SUPPORTED && csPriority == NOT_SUPPORTED) {
@@ -827,17 +993,20 @@
}
// Make NGRAN have the lowest priority
- if (tryEpsFallback && preferredNetworks.contains(NGRAN)) {
+ if (tryEsFallback && 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,
+ preferredNetworks = generatePreferredNetworks(getImsNetworkTypeConfiguration(),
getCsNetworkTypeConfiguration());
+ // Make NGRAN have the lowest priority
+ if (preferredNetworks.contains(NGRAN)) {
+ preferredNetworks.remove(Integer.valueOf(NGRAN));
+ preferredNetworks.add(NGRAN);
+ }
} else if (csPriority > NOT_SUPPORTED) {
// PS tried, generate the list with CS preferred.
preferredNetworks = generatePreferredNetworks(getCsNetworkTypeConfiguration(),
@@ -943,7 +1112,8 @@
* @return {@code true} if CS is in service.
*/
private boolean isCsInService() {
- EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ EmergencyRegistrationResult regResult =
+ mSelectionAttributes.getEmergencyRegistrationResult();
if (regResult == null) return false;
int regState = regResult.getRegState();
@@ -963,7 +1133,12 @@
* @return The network type of the CS network.
*/
private @RadioAccessNetworkType int getSelectableCsNetworkType() {
- EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ List<Integer> domains = getDomainPreference();
+ if (domains.indexOf(DOMAIN_CS) == NOT_SUPPORTED) {
+ return UNKNOWN;
+ }
+ EmergencyRegistrationResult regResult =
+ mSelectionAttributes.getEmergencyRegistrationResult();
logi("getSelectableCsNetworkType regResult=" + regResult);
if (regResult == null) return UNKNOWN;
@@ -988,7 +1163,8 @@
* @return {@code true} if PS is in service.
*/
private boolean isPsInService() {
- EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ EmergencyRegistrationResult regResult =
+ mSelectionAttributes.getEmergencyRegistrationResult();
if (regResult == null) return false;
int regState = regResult.getRegState();
@@ -1009,7 +1185,12 @@
* @return The network type if the network supports emergency services over PS network.
*/
private @RadioAccessNetworkType int getSelectablePsNetworkType(boolean inService) {
- EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ List<Integer> domains = getDomainPreference();
+ if (domains.indexOf(DOMAIN_PS_3GPP) == NOT_SUPPORTED) {
+ return UNKNOWN;
+ }
+ EmergencyRegistrationResult regResult =
+ mSelectionAttributes.getEmergencyRegistrationResult();
logi("getSelectablePsNetworkType regResult=" + regResult);
if (regResult == null) return UNKNOWN;
if (mRequiresVoLteEnabled && !isAdvancedCallingSettingEnabled()) {
@@ -1038,8 +1219,9 @@
return UNKNOWN;
}
- private boolean isEpsFallbackAvailable() {
- EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ private boolean isEsFallbackAvailable() {
+ EmergencyRegistrationResult regResult =
+ mSelectionAttributes.getEmergencyRegistrationResult();
if (regResult == null) return false;
List<Integer> ratList = getImsNetworkTypeConfiguration();
@@ -1175,7 +1357,8 @@
}
if (!mCdmaPreferredNumbers.isEmpty()) {
- if (mCdmaPreferredNumbers.contains(mSelectionAttributes.getNumber())) {
+ String number = mSelectionAttributes.getAddress().getSchemeSpecificPart();
+ if (mCdmaPreferredNumbers.contains(number)) {
// The number will be dialed over CDMA.
ratList.clear();
ratList.add(new Integer(CDMA2000));
@@ -1206,12 +1389,11 @@
tm = tm.createForSubscriptionId(getSubId());
String netIso = tm.getNetworkCountryIso();
- EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ EmergencyRegistrationResult regResult = mLastRegResult;
if (regResult != null) {
if (regResult.getRegState() == REGISTRATION_STATE_HOME) return false;
- if (regResult.getRegState() == REGISTRATION_STATE_ROAMING) return true;
- String iso = regResult.getIso();
+ String iso = regResult.getCountryIso();
if (!TextUtils.isEmpty(iso)) netIso = iso;
}
@@ -1360,48 +1542,86 @@
}
}
- private boolean allowEmergencyCalls(EmergencyRegResult regResult) {
- if (mModemCount < 2) return true;
+ private boolean allowEmergencyCalls(EmergencyRegistrationResult regResult) {
if (regResult == null) {
loge("allowEmergencyCalls null regResult");
return true;
}
- String iso = regResult.getIso();
+ String iso = regResult.getCountryIso();
if (sSimReadyAllowList.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()) {
+ if (isSimReady()) {
+ SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class);
+ SubscriptionInfo subInfo = sm.getActiveSubscriptionInfo(getSubId());
+ if (subInfo != null
+ && subInfo.getProfileClass() == PROFILE_CLASS_PROVISIONING) {
+ // b/334773484, bootstrap profile
+ logi("allowEmergencyCalls bootstrap profile, iso=" + iso);
return false;
}
- logi("allowEmergencyCalls there is no other slot available");
+ } else {
+ logi("allowEmergencyCalls SIM state not ready, iso=" + iso);
+ return false;
}
}
return true;
}
+ private boolean maybeRedialOnTheOtherSlotInNormalService() {
+ EmergencyRegistrationResult regResult =
+ mSelectionAttributes.getEmergencyRegistrationResult();
+ if (regResult == null) return false;
+
+ String iso = regResult.getCountryIso();
+ if (sPreferSlotWithNormalServiceList.contains(iso)
+ && mCrossSimRedialingController.isThereOtherSlotInService()) {
+ terminateSelectionForCrossSimRedialing(false);
+ return true;
+ }
+ return false;
+ }
+
private void terminateSelectionPermanentlyForSlot() {
logi("terminateSelectionPermanentlyForSlot");
- terminateSelection(true);
+ mCrossSimRedialingController.notifyCallFailure(EMERGENCY_PERM_FAILURE);
+ if (mCrossSimRedialingController.isThereOtherSlot()) {
+ terminateSelection(DisconnectCause.EMERGENCY_PERM_FAILURE);
+ } else {
+ terminateSelection(DisconnectCause.ICC_ERROR);
+ }
}
private void terminateSelectionForCrossSimRedialing(boolean permanent) {
logi("terminateSelectionForCrossSimRedialing perm=" + permanent);
- terminateSelection(permanent);
+ terminateSelection(permanent ? DisconnectCause.EMERGENCY_PERM_FAILURE
+ : DisconnectCause.EMERGENCY_TEMP_FAILURE);
}
- private void terminateSelection(boolean permanent) {
- mTransportSelectorCallback.onSelectionTerminated(permanent
- ? DisconnectCause.EMERGENCY_PERM_FAILURE
- : DisconnectCause.EMERGENCY_TEMP_FAILURE);
+ private void terminateSelection(int cause) {
+ mTransportSelectorCallback.onSelectionTerminated(cause);
+ }
- if (mIsScanRequested && mCancelSignal != null) {
- mCancelSignal.cancel();
- mCancelSignal = null;
+ private boolean maybeTerminateSelection(int cause) {
+ switch (cause) {
+ case NO_VALID_SIM:
+ // The disconnect cause saved in DomainSelectionConnection shall be used.
+ terminateSelection(DisconnectCause.NOT_VALID);
+ return true;
+ default:
+ break;
}
+
+ // If CS call fails, retry always. Otherwise, check the reason code.
+ ImsReasonInfo reasonInfo = mSelectionAttributes.getPsDisconnectCause();
+ if (mRetryReasonCodes != null && reasonInfo != null) {
+ if (!mRetryReasonCodes.contains(reasonInfo.getCode())) {
+ // The disconnect cause saved in DomainSelectionConnection shall be used.
+ terminateSelection(DisconnectCause.NOT_VALID);
+ return true;
+ }
+ }
+ return false;
}
/** Starts the cross stack timer. */
@@ -1411,7 +1631,8 @@
if (mModemCount == 1) return;
- EmergencyRegResult regResult = mSelectionAttributes.getEmergencyRegResult();
+ EmergencyRegistrationResult regResult =
+ mSelectionAttributes.getEmergencyRegistrationResult();
if (regResult != null) {
int regState = regResult.getRegState();
@@ -1423,8 +1644,9 @@
inRoaming = (regState == REGISTRATION_STATE_ROAMING) || isInRoaming();
}
+ String number = mSelectionAttributes.getAddress().getSchemeSpecificPart();
mCrossSimRedialingController.startTimer(mContext, this, mSelectionAttributes.getCallId(),
- mSelectionAttributes.getNumber(), inService, inRoaming, mModemCount);
+ number, inService, inRoaming, mModemCount);
}
/** Notifies that the cross stack redilaing timer has been expired. */
@@ -1436,9 +1658,34 @@
// When reselecting domain, terminateSelection will be called.
return;
}
+ mIsWaitingForDataDisconnection = false;
+ removeMessages(MSG_WAIT_DISCONNECTION_TIMEOUT);
terminateSelectionForCrossSimRedialing(false);
}
+ /** Notifies the ePDN connection state changes. */
+ public void notifyDataConnectionStateChange(int slotId, int state) {
+ if (slotId == getSlotId() && mIsWaitingForDataDisconnection) {
+ if (state == DATA_DISCONNECTED || state == DATA_UNKNOWN) {
+ requestScanDelayed();
+ } else if (state == DATA_DISCONNECTING) {
+ logi("notifyDataConnectionStateChange deactivation starting, restart timer");
+ removeMessages(MSG_WAIT_DISCONNECTION_TIMEOUT);
+ sendEmptyMessageDelayed(MSG_WAIT_DISCONNECTION_TIMEOUT,
+ DEFAULT_DATA_DISCONNECTION_TIMEOUT_MS);
+ }
+ }
+ }
+
+ private void maybeModifyScanType(int selectedNetworkType) {
+ if ((mPreferredNetworkScanType
+ != CarrierConfigManager.ImsEmergency.SCAN_TYPE_FULL_SERVICE)
+ && mScanLimitedOnlyAfterVolteFailure
+ && (selectedNetworkType == EUTRAN)) {
+ mScanType = DomainSelectionService.SCAN_TYPE_LIMITED_SERVICE;
+ }
+ }
+
private static String arrayToString(int[] intArray, IntFunction<String> func) {
int length = intArray.length;
StringBuilder sb = new StringBuilder("{");
@@ -1509,6 +1756,7 @@
public void destroy() {
if (DBG) logd("destroy");
+ mEpdnHelper.setEmergencyCallDomainSelector(null);
mCrossSimRedialingController.stopTimer();
releaseWakeLock();
@@ -1540,35 +1788,16 @@
}
}
- private void selectDomainForTestEmergencyNumber() {
- logi("selectDomainForTestEmergencyNumber");
- if (isImsRegisteredWithVoiceCapability()) {
- onWwanNetworkTypeSelected(EUTRAN);
- } else {
- onWwanNetworkTypeSelected(UTRAN);
- }
+ private boolean isInEmergencyCallbackModeOnWlan() {
+ return mEpdnHelper.isInEmergencyCallbackMode(getSlotId())
+ && mEpdnHelper.getTransportType(getSlotId()) == TRANSPORT_TYPE_WLAN
+ && mEpdnHelper.getDataConnectionState(getSlotId()) == DATA_CONNECTED;
}
- 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;
+ private boolean isInEmergencyCallbackModeOnPsWwan() {
+ return mEpdnHelper.isInEmergencyCallbackMode(getSlotId())
+ && mEpdnHelper.getTransportType(getSlotId()) == TRANSPORT_TYPE_WWAN
+ && mEpdnHelper.getDataConnectionState(getSlotId()) == DATA_CONNECTED;
}
@Override
diff --git a/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelector.java
index aef193b..7f28b04 100644
--- a/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelector.java
@@ -18,12 +18,17 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.os.CancellationSignal;
import android.os.Looper;
+import android.os.Message;
import android.os.PersistableBundle;
import android.telephony.AccessNetworkConstants;
+import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.BarringInfo;
import android.telephony.CarrierConfigManager;
import android.telephony.DataSpecificRegistrationInfo;
+import android.telephony.DomainSelectionService;
+import android.telephony.EmergencyRegistrationResult;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
@@ -31,11 +36,14 @@
import com.android.internal.annotations.VisibleForTesting;
+import java.util.List;
+
/**
* Implements an emergency SMS domain selector for sending an emergency SMS.
*/
public class EmergencySmsDomainSelector extends SmsDomainSelector implements
ImsStateTracker.BarringInfoListener, ImsStateTracker.ServiceStateListener {
+ protected static final int EVENT_EMERGENCY_NETWORK_SCAN_RESULT = 201;
/**
* Stores the configuration value of
* {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL}.
@@ -46,6 +54,8 @@
private boolean mServiceStateReceived;
private BarringInfo mBarringInfo;
private boolean mBarringInfoReceived;
+ private boolean mEmergencyNetworkScanInProgress;
+ private CancellationSignal mEmergencyNetworkScanSignal;
public EmergencySmsDomainSelector(Context context, int slotId, int subId,
@NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
@@ -68,6 +78,18 @@
}
@Override
+ public void handleMessage(@NonNull Message msg) {
+ switch (msg.what) {
+ case EVENT_EMERGENCY_NETWORK_SCAN_RESULT:
+ handleEmergencyNetworkScanResult((EmergencyRegistrationResult) msg.obj);
+ break;
+ default:
+ super.handleMessage(msg);
+ break;
+ }
+ }
+
+ @Override
public void finishSelection() {
super.finishSelection();
mServiceStateReceived = false;
@@ -75,6 +97,12 @@
mBarringInfoReceived = false;
mBarringInfo = null;
mEmergencySmsOverImsSupportedByConfig = null;
+
+ mEmergencyNetworkScanInProgress = false;
+ if (mEmergencyNetworkScanSignal != null) {
+ mEmergencyNetworkScanSignal.cancel();
+ mEmergencyNetworkScanSignal = null;
+ }
}
@Override
@@ -111,7 +139,7 @@
* when {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL} is set
* to true.
*/
- if (isEmergencySmsOverImsSupportedIfLteLimitedOrInService()) {
+ if (isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService()) {
/**
* Emergency SMS should be supported via emergency PDN.
* If this condition is false, then need to fallback to CS network
@@ -139,60 +167,132 @@
return;
}
+ if (mEmergencyNetworkScanInProgress) {
+ logi("Emergency network scan is in progress.");
+ return;
+ }
+
logi("selectDomain: " + mImsStateTracker.imsStateToString());
if (isSmsOverImsAvailable()) {
- boolean isEmergencySmsOverImsSupportedIfLteLimitedOrInService =
- isEmergencySmsOverImsSupportedIfLteLimitedOrInService();
+ boolean isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService =
+ isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService();
if (mImsStateTracker.isImsRegisteredOverWlan()) {
/**
* When {@link CarrierConfigManager#KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL}
- * is set to true, the emergency SMS supports on the LTE network using the
+ * is set to true, the emergency SMS supports on the LTE/NR network using the
* emergency PDN. As of now, since the emergency SMS doesn't use the emergency PDN
* over WLAN, the domain selector reports the domain as WLAN only if
- * {@code isEmergencySmsOverImsSupportedIfLteLimitedOrInService} is set to false
+ * {@code isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService} is set to false
* and IMS is registered over WLAN.
* Otherwise, the domain selector reports the domain as WWAN.
*/
- if (!isEmergencySmsOverImsSupportedIfLteLimitedOrInService) {
+ if (!isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService) {
notifyWlanSelected(false);
return;
}
logi("DomainSelected: WLAN >> WWAN");
}
- notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_PS,
- isEmergencySmsOverImsSupportedIfLteLimitedOrInService);
+
+ /**
+ * The request of emergency network scan triggers the modem to request the emergency
+ * service fallback because NR network doesn't support the emergency service.
+ */
+ if (isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService
+ && isNrEmergencyServiceFallbackRequired()) {
+ requestEmergencyNetworkScan(List.of(AccessNetworkType.EUTRAN));
+ } else {
+ notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_PS,
+ isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService);
+ }
} else {
notifyWwanSelected(NetworkRegistrationInfo.DOMAIN_CS, false);
}
}
+ private void requestEmergencyNetworkScan(List<Integer> preferredNetworks) {
+ mEmergencyNetworkScanInProgress = true;
+
+ if (mWwanSelectorCallback == null) {
+ mTransportSelectorCallback.onWwanSelected((callback) -> {
+ mWwanSelectorCallback = callback;
+ requestEmergencyNetworkScanInternal(preferredNetworks);
+ });
+ } else {
+ requestEmergencyNetworkScanInternal(preferredNetworks);
+ }
+ }
+
+ private void requestEmergencyNetworkScanInternal(List<Integer> preferredNetworks) {
+ logi("requestEmergencyNetworkScan: preferredNetworks=" + preferredNetworks);
+ mEmergencyNetworkScanSignal = new CancellationSignal();
+ mWwanSelectorCallback.onRequestEmergencyNetworkScan(
+ preferredNetworks,
+ DomainSelectionService.SCAN_TYPE_FULL_SERVICE, false,
+ mEmergencyNetworkScanSignal,
+ (regResult) -> {
+ logi("requestEmergencyNetworkScan-onComplete");
+ obtainMessage(EVENT_EMERGENCY_NETWORK_SCAN_RESULT, regResult).sendToTarget();
+ });
+ }
+
+ /**
+ * Handles the emergency network scan result.
+ *
+ * This triggers the emergency service fallback to modem when the emergency service is not
+ * supported but the emergency service fallback is supported in the current network.
+ *
+ * @param regResult The emergency registration result that is triggered
+ * by the emergency network scan.
+ */
+ private void handleEmergencyNetworkScanResult(EmergencyRegistrationResult regResult) {
+ logi("handleEmergencyNetworkScanResult: " + regResult);
+
+ mEmergencyNetworkScanInProgress = false;
+ mEmergencyNetworkScanSignal = null;
+
+ int accessNetworkType = regResult.getAccessNetwork();
+ int domain = NetworkRegistrationInfo.DOMAIN_CS;
+
+ if (accessNetworkType == AccessNetworkType.NGRAN) {
+ domain = NetworkRegistrationInfo.DOMAIN_PS;
+ } else if (accessNetworkType == AccessNetworkType.EUTRAN) {
+ if (regResult.getDomain() == NetworkRegistrationInfo.DOMAIN_CS) {
+ logi("PS emergency service is not supported in LTE network.");
+ } else {
+ domain = NetworkRegistrationInfo.DOMAIN_PS;
+ }
+ }
+
+ notifyWwanSelected(domain, (domain == NetworkRegistrationInfo.DOMAIN_PS));
+ }
+
/**
* Checks if the emergency SMS messages over IMS is available according to the carrier
* configuration and the current network states.
*/
private boolean isImsEmergencySmsAvailable() {
- boolean isEmergencySmsOverImsSupportedIfLteLimitedOrInService =
- isEmergencySmsOverImsSupportedIfLteLimitedOrInService();
+ boolean isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService =
+ isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService();
boolean networkAvailable = isNetworkAvailableForImsEmergencySms();
logi("isImsEmergencySmsAvailable: "
- + "emergencySmsOverIms=" + isEmergencySmsOverImsSupportedIfLteLimitedOrInService
+ + "emergencySmsOverIms=" + isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService
+ ", mmTelFeatureAvailable=" + mImsStateTracker.isMmTelFeatureAvailable()
+ ", networkAvailable=" + networkAvailable);
- return isEmergencySmsOverImsSupportedIfLteLimitedOrInService
+ return isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService
&& 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.
+ * Checks if sending emergency SMS messages over IMS is supported when in the network(LTE/NR)
+ * normal/limited(Emergency only) service mode from the carrier configuration.
*/
- private boolean isEmergencySmsOverImsSupportedIfLteLimitedOrInService() {
+ private boolean isEmergencySmsOverImsSupportedIfNetworkLimitedOrInService() {
if (mEmergencySmsOverImsSupportedByConfig == null) {
CarrierConfigManager ccm = mContext.getSystemService(CarrierConfigManager.class);
@@ -257,7 +357,8 @@
*/
private boolean isNetworkAvailableForImsEmergencySms() {
return isLteEmergencyAvailableInService()
- || isLteEmergencyAvailableInLimitedService();
+ || isLteEmergencyAvailableInLimitedService()
+ || isNrEmergencyAvailable();
}
/**
@@ -280,6 +381,22 @@
}
/**
+ * Checks if the emergency service fallback is supported by the network.
+ *
+ * @return {@code true} if the emergency service fallback is supported by the network,
+ * {@code false} otherwise.
+ */
+ private boolean isEmergencyServiceFallbackSupported(@NonNull NetworkRegistrationInfo regInfo) {
+ final DataSpecificRegistrationInfo dsRegInfo = regInfo.getDataSpecificInfo();
+ if (dsRegInfo != null) {
+ final VopsSupportInfo vopsSupportInfo = dsRegInfo.getVopsSupportInfo();
+ return vopsSupportInfo != null
+ && vopsSupportInfo.isEmergencyServiceFallbackSupported();
+ }
+ return false;
+ }
+
+ /**
* Checks if the emergency service is allowed (not barred) by the network.
*
* This checks if SystemInformationBlockType2 includes the ac-BarringInfo and
@@ -297,4 +414,45 @@
mBarringInfo.getBarringServiceInfo(BarringInfo.BARRING_SERVICE_TYPE_EMERGENCY);
return !bsi.isBarred();
}
+
+ /**
+ * Checks if the emergency service fallback is available in the NR network
+ * because the emergency service is not supported.
+ */
+ private boolean isNrEmergencyServiceFallbackRequired() {
+ 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_NR
+ && regInfo.isRegistered()) {
+ return !isEmergencyServiceSupported(regInfo)
+ && isEmergencyServiceFallbackSupported(regInfo);
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the emergency service is available in the NR network.
+ */
+ private boolean isNrEmergencyAvailable() {
+ 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_NR
+ && regInfo.isRegistered()) {
+ return isEmergencyServiceSupported(regInfo)
+ || isEmergencyServiceFallbackSupported(regInfo);
+ }
+ return false;
+ }
}
diff --git a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
index f85dabe..31a1cc2 100644
--- a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
@@ -34,6 +34,8 @@
import android.telephony.TransportSelectorCallback;
import android.telephony.ims.ImsReasonInfo;
+import com.android.internal.annotations.VisibleForTesting;
+
/**
* Implements domain selector for outgoing non-emergency calls.
*/
@@ -42,8 +44,15 @@
private static final String LOG_TAG = "NCDS";
- private boolean mStopDomainSelection = true;
- private ServiceState mServiceState;
+ @VisibleForTesting
+ protected enum SelectorState {
+ ACTIVE,
+ INACTIVE,
+ DESTROYED
+ };
+
+ protected SelectorState mSelectorState = SelectorState.INACTIVE;
+ protected ServiceState mServiceState;
private boolean mImsRegStateReceived;
private boolean mMmTelCapabilitiesReceived;
private boolean mReselectDomain;
@@ -66,9 +75,10 @@
public void selectDomain(SelectionAttributes attributes, TransportSelectorCallback callback) {
mSelectionAttributes = attributes;
mTransportSelectorCallback = callback;
- mStopDomainSelection = false;
+ mSelectorState = SelectorState.ACTIVE;
if (callback == null) {
+ mSelectorState = SelectorState.INACTIVE;
loge("Invalid params: TransportSelectorCallback is null");
return;
}
@@ -79,7 +89,7 @@
return;
}
- int subId = attributes.getSubId();
+ int subId = attributes.getSubscriptionId();
boolean validSubscriptionId = SubscriptionManager.isValidSubscriptionId(subId);
if (attributes.getSelectorType() != SELECTOR_TYPE_CALLING || attributes.isEmergency()
|| !validSubscriptionId) {
@@ -95,6 +105,7 @@
logd("NormalCallDomainSelection triggered. Sub-id:" + subId);
post(() -> selectDomain());
} else {
+ mSelectorState = SelectorState.INACTIVE;
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.
@@ -111,27 +122,44 @@
@Override
public synchronized void finishSelection() {
logd("finishSelection");
- mStopDomainSelection = true;
- mImsStateTracker.removeServiceStateListener(this);
- mImsStateTracker.removeImsStateListener(this);
- mSelectionAttributes = null;
- mTransportSelectorCallback = null;
+ if (mSelectorState == SelectorState.ACTIVE) {
+ // This is cancel selection case.
+ cancelSelection();
+ return;
+ }
+
+ if (mSelectorState != SelectorState.DESTROYED) {
+ mImsStateTracker.removeServiceStateListener(this);
+ mImsStateTracker.removeImsStateListener(this);
+ mSelectionAttributes = null;
+ mTransportSelectorCallback = null;
+ destroy();
+ }
}
@Override
public void destroy() {
- finishSelection();
- super.destroy();
+ logd("destroy");
+ switch (mSelectorState) {
+ case INACTIVE:
+ mSelectorState = SelectorState.DESTROYED;
+ super.destroy();
+ break;
+
+ case ACTIVE:
+ loge("destroy is called when selector state is in ACTIVE state");
+ cancelSelection();
+ break;
+
+ case DESTROYED:
+ super.destroy();
+ break;
+ }
}
- /**
- * 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;
+ mSelectorState = SelectorState.INACTIVE;
mReselectDomain = false;
if (mTransportSelectorCallback != null) {
mTransportSelectorCallback.onSelectionTerminated(DisconnectCause.OUTGOING_CANCELED);
@@ -170,7 +198,7 @@
private void notifyPsSelected() {
logd("notifyPsSelected");
- mStopDomainSelection = true;
+ mSelectorState = SelectorState.INACTIVE;
if (mImsStateTracker.isImsRegisteredOverWlan()) {
logd("WLAN selected");
mTransportSelectorCallback.onWlanSelected(false);
@@ -198,7 +226,7 @@
private void notifyCsSelected() {
logd("notifyCsSelected");
- mStopDomainSelection = true;
+ mSelectorState = SelectorState.INACTIVE;
if (mWwanSelectorCallback == null) {
mTransportSelectorCallback.onWwanSelected((callback) -> {
mWwanSelectorCallback = callback;
@@ -220,7 +248,7 @@
}
private void notifySelectionTerminated(@DisconnectCauses int cause) {
- mStopDomainSelection = true;
+ mSelectorState = SelectorState.INACTIVE;
if (mTransportSelectorCallback != null) {
mTransportSelectorCallback.onSelectionTerminated(cause);
finishSelection();
@@ -238,7 +266,7 @@
PersistableBundle config = null;
if (configManager != null) {
- config = configManager.getConfigForSubId(mSelectionAttributes.getSubId(),
+ config = configManager.getConfigForSubId(mSelectionAttributes.getSubscriptionId(),
new String[] {CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL});
}
@@ -266,7 +294,7 @@
PersistableBundle config = null;
if (configManager != null) {
- config = configManager.getConfigForSubId(mSelectionAttributes.getSubId(),
+ config = configManager.getConfigForSubId(mSelectionAttributes.getSubscriptionId(),
new String[] {CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL});
}
@@ -284,7 +312,7 @@
}
private synchronized void selectDomain() {
- if (mStopDomainSelection || mSelectionAttributes == null
+ if (mSelectorState != SelectorState.ACTIVE || mSelectionAttributes == null
|| mTransportSelectorCallback == null) {
logd("Domain Selection is stopped.");
return;
@@ -382,7 +410,8 @@
// Handle voice call.
if (mImsStateTracker.isImsVoiceCapable()) {
logd("IMS is voice capable");
- if (PhoneNumberUtils.isWpsCallNumber(mSelectionAttributes.getNumber())) {
+ String number = mSelectionAttributes.getAddress().getSchemeSpecificPart();
+ if (PhoneNumberUtils.isWpsCallNumber(number)) {
handleWpsCall();
} else {
notifyPsSelected();
@@ -398,4 +427,9 @@
}
}
}
+
+ @VisibleForTesting
+ public SelectorState getSelectorState() {
+ return mSelectorState;
+ }
}
diff --git a/src/com/android/services/telephony/domainselection/SmsDomainSelector.java b/src/com/android/services/telephony/domainselection/SmsDomainSelector.java
index 95b04e2..4e41e43 100644
--- a/src/com/android/services/telephony/domainselection/SmsDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/SmsDomainSelector.java
@@ -71,12 +71,6 @@
}
@Override
- public void cancelSelection() {
- logi("cancelSelection");
- finishSelection();
- }
-
- @Override
public void reselectDomain(@NonNull SelectionAttributes attr) {
if (isDomainSelectionRequested()) {
// The domain selection is already requested,
diff --git a/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java b/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java
index 66894f7..7e1a2e6 100644
--- a/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java
+++ b/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java
@@ -18,7 +18,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
@@ -74,7 +73,7 @@
@NonNull ImsStateTracker imsStateTracker,
@NonNull DomainSelectorBase.DestroyListener listener,
@NonNull CrossSimRedialingController crossSimRedialingController,
- @NonNull CarrierConfigHelper carrierConfigHelper);
+ @NonNull DataConnectionStateHelper dataConnectionStateHelper);
}
private static final class DefaultDomainSelectorFactory implements DomainSelectorFactory {
@@ -84,7 +83,7 @@
@NonNull ImsStateTracker imsStateTracker,
@NonNull DomainSelectorBase.DestroyListener listener,
@NonNull CrossSimRedialingController crossSimRedialingController,
- @NonNull CarrierConfigHelper carrierConfigHelper) {
+ @NonNull DataConnectionStateHelper dataConnectionStateHelper) {
DomainSelectorBase selector = null;
logi("create-DomainSelector: slotId=" + slotId + ", subId=" + subId
@@ -96,7 +95,7 @@
if (isEmergency) {
selector = new EmergencyCallDomainSelector(context, slotId, subId, looper,
imsStateTracker, listener, crossSimRedialingController,
- carrierConfigHelper);
+ dataConnectionStateHelper);
} else {
selector = new NormalCallDomainSelector(context, slotId, subId, looper,
imsStateTracker, listener);
@@ -192,7 +191,7 @@
// Persistent Logging
private static final LocalLog sEventLog = new LocalLog(20);
- private final Context mContext;
+ private Context mContext;
// Map of slotId -> ImsStateTracker
private final SparseArray<ImsStateTracker> mImsStateTrackers = new SparseArray<>(2);
private final List<DomainSelectorContainer> mDomainSelectorContainers = new ArrayList<>();
@@ -200,23 +199,30 @@
private final DomainSelectorFactory mDomainSelectorFactory;
private Handler mServiceHandler;
private CrossSimRedialingController mCrossSimRedialingController;
- private CarrierConfigHelper mCarrierConfigHelper;
+ private DataConnectionStateHelper mDataConnectionStateHelper;
- public TelephonyDomainSelectionService(Context context) {
- this(context, ImsStateTracker::new, new DefaultDomainSelectorFactory(), null);
+ /** Default constructor. */
+ public TelephonyDomainSelectionService() {
+ this(ImsStateTracker::new, new DefaultDomainSelectorFactory(), null);
}
@VisibleForTesting
- public TelephonyDomainSelectionService(Context context,
+ protected TelephonyDomainSelectionService(
@NonNull ImsStateTrackerFactory imsStateTrackerFactory,
@NonNull DomainSelectorFactory domainSelectorFactory,
- @Nullable CarrierConfigHelper carrierConfigHelper) {
- mContext = context;
+ @Nullable DataConnectionStateHelper dataConnectionStateHelper) {
mImsStateTrackerFactory = imsStateTrackerFactory;
mDomainSelectorFactory = domainSelectorFactory;
+ mDataConnectionStateHelper = dataConnectionStateHelper;
+ }
+
+ @Override
+ public void onCreate() {
+ logd("onCreate");
+ mContext = getApplicationContext();
// Create a worker thread for this domain selection service.
- getExecutor();
+ getCreateExecutor();
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
int activeModemCount = (tm != null) ? tm.getActiveModemCount() : 1;
@@ -231,9 +237,10 @@
loge("Adding OnSubscriptionChangedListener failed");
}
- mCrossSimRedialingController = new CrossSimRedialingController(context, getLooper());
- mCarrierConfigHelper = (carrierConfigHelper != null)
- ? carrierConfigHelper : new CarrierConfigHelper(context, getLooper());
+ mCrossSimRedialingController = new CrossSimRedialingController(mContext, getLooper());
+ if (mDataConnectionStateHelper == null) {
+ mDataConnectionStateHelper = new DataConnectionStateHelper(mContext, getLooper());
+ }
logi("TelephonyDomainSelectionService created");
}
@@ -277,9 +284,9 @@
mCrossSimRedialingController = null;
}
- if (mCarrierConfigHelper != null) {
- mCarrierConfigHelper.destroy();
- mCarrierConfigHelper = null;
+ if (mDataConnectionStateHelper != null) {
+ mDataConnectionStateHelper.destroy();
+ mDataConnectionStateHelper = null;
}
if (mServiceHandler != null) {
@@ -297,14 +304,14 @@
@Override
public void onDomainSelection(@NonNull SelectionAttributes attr,
@NonNull TransportSelectorCallback callback) {
- final int slotId = attr.getSlotId();
- final int subId = attr.getSubId();
+ final int slotId = attr.getSlotIndex();
+ final int subId = attr.getSubscriptionId();
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, mCarrierConfigHelper);
+ mCrossSimRedialingController, mDataConnectionStateHelper);
if (selector != null) {
// Ensures that ImsStateTracker is started before selecting the domain if not started
@@ -313,15 +320,21 @@
addDomainSelector(slotId, selectorType, isEmergency, selector);
} else {
loge("No proper domain selector: " + selectorTypeToString(selectorType));
- callback.onSelectionTerminated(DisconnectCause.ERROR_UNSPECIFIED);
+ // Executed through the service handler to ensure that the callbacks are not called
+ // directly in this execution flow.
+ mServiceHandler.post(() ->
+ 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);
+ // Executed through the service handler to ensure that the callbacks are not called
+ // directly in this execution flow.
+ mServiceHandler.post(() -> {
+ // Notify the caller that the domain selector is created.
+ callback.onCreated(selector);
+ // Performs the domain selection.
+ selector.selectDomain(attr, callback);
+ });
}
/**
@@ -359,8 +372,15 @@
/**
* Returns an Executor used to execute methods called remotely by the framework.
*/
- @SuppressLint("OnNameExpected")
@Override
+ public @NonNull Executor getCreateExecutor() {
+ return getExecutor();
+ }
+
+ /**
+ * Returns an Executor used to execute methods called remotely by the framework.
+ */
+ @VisibleForTesting
public @NonNull Executor getExecutor() {
if (mServiceHandler == null) {
HandlerThread handlerThread = new HandlerThread(TAG);
@@ -480,7 +500,6 @@
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);
}
}
diff --git a/src/com/android/services/telephony/rcs/TelephonyRcsService.java b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
index f6ba40b..63753c2 100644
--- a/src/com/android/services/telephony/rcs/TelephonyRcsService.java
+++ b/src/com/android/services/telephony/rcs/TelephonyRcsService.java
@@ -33,6 +33,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.PhoneConfigurationManager;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.RcsStats;
import com.android.internal.util.IndentingPrintWriter;
import com.android.phone.ImsStateCallbackController;
@@ -63,7 +64,8 @@
/**
* @return an instance of {@link UceControllerManager} associated with the slot specified.
*/
- UceControllerManager createUceControllerManager(Context context, int slotId, int subId);
+ UceControllerManager createUceControllerManager(Context context, int slotId, int subId,
+ FeatureFlags featureFlags);
/**
* @return an instance of {@link SipTransportController} for the slot and subscription
@@ -80,8 +82,8 @@
@Override
public UceControllerManager createUceControllerManager(Context context, int slotId,
- int subId) {
- return new UceControllerManager(context, slotId, subId);
+ int subId, FeatureFlags featureFlags) {
+ return new UceControllerManager(context, slotId, subId, featureFlags);
}
@Override
@@ -112,6 +114,7 @@
private final Context mContext;
private final Object mLock = new Object();
+ private final FeatureFlags mFeatureFlags;
private int mNumSlots;
// Maps slot ID -> RcsFeatureController.
@@ -160,23 +163,26 @@
return true;
});
- public TelephonyRcsService(Context context, int numSlots) {
+ public TelephonyRcsService(Context context, int numSlots, FeatureFlags featureFlags) {
mContext = context;
mNumSlots = numSlots;
mFeatureControllers = new SparseArray<>(numSlots);
mSlotToAssociatedSubIds = new SparseArray<>(numSlots);
mRcsUceEnabled = sResourceProxy.getDeviceUceEnabled(mContext);
+ mFeatureFlags = featureFlags;
RcsStats.getInstance().registerUceCallback();
}
@VisibleForTesting
- public TelephonyRcsService(Context context, int numSlots, ResourceProxy resourceProxy) {
+ public TelephonyRcsService(Context context, int numSlots, ResourceProxy resourceProxy,
+ FeatureFlags featureFlags) {
mContext = context;
mNumSlots = numSlots;
mFeatureControllers = new SparseArray<>(numSlots);
mSlotToAssociatedSubIds = new SparseArray<>(numSlots);
sResourceProxy = resourceProxy;
mRcsUceEnabled = sResourceProxy.getDeviceUceEnabled(mContext);
+ mFeatureFlags = featureFlags;
RcsStats.getInstance().registerUceCallback();
}
@@ -310,8 +316,8 @@
private void updateSupportedFeatures(RcsFeatureController c, int slotId, int subId) {
if (isDeviceUceEnabled() && doesSubscriptionSupportPresence(subId)) {
if (c.getFeature(UceControllerManager.class) == null) {
- c.addFeature(mFeatureFactory.createUceControllerManager(mContext, slotId, subId),
- UceControllerManager.class);
+ c.addFeature(mFeatureFactory.createUceControllerManager(
+ mContext, slotId, subId, mFeatureFlags), UceControllerManager.class);
}
} else {
if (c.getFeature(UceControllerManager.class) != null) {
diff --git a/src/com/android/services/telephony/rcs/UceControllerManager.java b/src/com/android/services/telephony/rcs/UceControllerManager.java
index 02ae048..b7e12a3 100644
--- a/src/com/android/services/telephony/rcs/UceControllerManager.java
+++ b/src/com/android/services/telephony/rcs/UceControllerManager.java
@@ -32,6 +32,7 @@
import com.android.ims.RcsFeatureManager;
import com.android.ims.rcs.uce.UceController;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
import java.io.PrintWriter;
import java.util.List;
@@ -53,15 +54,17 @@
private final int mSlotId;
private final Context mContext;
private final ExecutorService mExecutorService;
+ private final FeatureFlags mFeatureFlags;
private volatile @Nullable UceController mUceController;
private volatile @Nullable RcsFeatureManager mRcsFeatureManager;
- public UceControllerManager(Context context, int slotId, int subId) {
+ public UceControllerManager(Context context, int slotId, int subId, FeatureFlags featureFlags) {
Log.d(LOG_TAG, "create: slotId=" + slotId + ", subId=" + subId);
mSlotId = slotId;
mContext = context;
mExecutorService = Executors.newSingleThreadExecutor();
+ mFeatureFlags = featureFlags;
initUceController(subId);
}
@@ -70,11 +73,12 @@
*/
@VisibleForTesting
public UceControllerManager(Context context, int slotId, ExecutorService executor,
- UceController uceController) {
+ UceController uceController, FeatureFlags featureFlags) {
mSlotId = slotId;
mContext = context;
mExecutorService = executor;
mUceController = uceController;
+ mFeatureFlags = featureFlags;
}
@Override
@@ -440,7 +444,7 @@
if (mUceController == null) {
// Create new UceController only when the subscription ID is valid.
if (SubscriptionManager.isValidSubscriptionId(newSubId)) {
- mUceController = new UceController(mContext, newSubId);
+ mUceController = new UceController(mContext, newSubId, mFeatureFlags);
}
} else if (mUceController.getSubId() != newSubId) {
// The subscription ID is updated. Remove the old UceController instance.
@@ -448,7 +452,7 @@
mUceController = null;
// Create new UceController only when the subscription ID is valid.
if (SubscriptionManager.isValidSubscriptionId(newSubId)) {
- mUceController = new UceController(mContext, newSubId);
+ mUceController = new UceController(mContext, newSubId, mFeatureFlags);
}
}
}
diff --git a/testapps/GbaTestApp/res/values-eu/strings.xml b/testapps/GbaTestApp/res/values-eu/strings.xml
index 6774d99..c192a56 100644
--- a/testapps/GbaTestApp/res/values-eu/strings.xml
+++ b/testapps/GbaTestApp/res/values-eu/strings.xml
@@ -20,10 +20,10 @@
<string name="request_naf_url" msgid="4487793541217737042">"Sareko aplikazioaren funtzioaren (NAF) URLa"</string>
<string name="request_force_bootstrapping" msgid="206043602616214325">"Bootstrapping-a erabiltzera behartu nahi duzu?"</string>
<string name="request_org" msgid="8416693445448308975">"Erakundearen kodea"</string>
- <string name="request_security_protocol" msgid="1444164827561010482">"UA segurtasun-protokoloaren IDa"</string>
+ <string name="request_security_protocol" msgid="1444164827561010482">"UA segurtasun-protokoloaren identifikatzailea"</string>
<string name="request_tls_cipher_suite" msgid="6659854717595308404">"TLS Cipher Suite ID"</string>
<string name="response_success" msgid="2469204471244527663">"Burutu da GBA autentifikazioa?"</string>
- <string name="response_fail_reason" msgid="3401426967253202496">"Hutsegitearen arrazoiaren IDa"</string>
+ <string name="response_fail_reason" msgid="3401426967253202496">"Hutsegitearen arrazoiaren identifikatzailea"</string>
<string name="response_key" msgid="8839847772051686309">"GBA-ko gakoa (CK + IK)"</string>
<string name="response_btid" msgid="2550216722679350756">"Bootstrapping Transaction Identifier (B-TID)"</string>
<string name="sample_naf" msgid="255371174145881001">"3GPP-bootstrapping@naf1.operator.com"</string>
diff --git a/testapps/GbaTestApp/res/values-mr/strings.xml b/testapps/GbaTestApp/res/values-mr/strings.xml
index 75aaf5f..f8e8992 100644
--- a/testapps/GbaTestApp/res/values-mr/strings.xml
+++ b/testapps/GbaTestApp/res/values-mr/strings.xml
@@ -3,9 +3,9 @@
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_carrier" msgid="1470455313066422804">"वाहक कॉंफिगरेशन"</string>
- <string name="label_service" msgid="2668963955237345578">"सेवा कॉंफिगरेशन"</string>
- <string name="label_test" msgid="8425079572898571918">"चाचणी कॉंफिगरेशन"</string>
+ <string name="label_carrier" msgid="1470455313066422804">"वाहकाचे कॉन्फिगरेशन"</string>
+ <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="label_test_result" msgid="892984695972956196">"चाचणी परिणाम"</string>
diff --git a/testapps/TestRcsApp/TestApp/AndroidManifest.xml b/testapps/TestRcsApp/TestApp/AndroidManifest.xml
index 35a0822..3ec9b69 100644
--- a/testapps/TestRcsApp/TestApp/AndroidManifest.xml
+++ b/testapps/TestRcsApp/TestApp/AndroidManifest.xml
@@ -56,6 +56,7 @@
<activity android:name=".ContactListActivity" />
<activity android:name=".ProvisioningActivity" />
<activity android:name=".FileUploadActivity" />
+ <activity android:name=".carrierLock.CarrieLockModeListActivity" />
<provider
android:name=".util.ChatProvider"
@@ -117,6 +118,10 @@
</intent-filter>
</service>
+ <provider
+ android:name=".carrierLock.CarrierLockProvider"
+ android:authorities="com.sample.lockProvider"
+ android:exported="true" />
</application>
</manifest>
diff --git a/testapps/TestRcsApp/TestApp/lint-baseline.xml b/testapps/TestRcsApp/TestApp/lint-baseline.xml
index 8971388..872a626 100644
--- a/testapps/TestRcsApp/TestApp/lint-baseline.xml
+++ b/testapps/TestRcsApp/TestApp/lint-baseline.xml
@@ -1,26 +1,444 @@
<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01">
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#bootstrapAuthenticationRequest`"
- errorLine1=" telephonyManager.bootstrapAuthenticationRequest(mUiccType,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Class requires API level 31 (current min is 30): `android.telephony.ims.stub.DelegateConnectionMessageCallback`"
+ errorLine1=" new DelegateConnectionMessageCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
- line="130"
- column="30"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="87"
+ column="17"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.gba.UaSecurityProtocolIdentifier.Builder#build`"
- errorLine1=" UaSecurityProtocolIdentifier spId = builder.build();"
- errorLine2=" ~~~~~">
+ message="Class requires API level 31 (current min is 30): `android.telephony.ims.stub.DelegateConnectionStateCallback`"
+ errorLine1=" new DelegateConnectionStateCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="117"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.FeatureTagState#getFeatureTag`"
+ errorLine1=' stringBuilder.append(featureTagState.getFeatureTag()).append(" ").append('
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="148"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.FeatureTagState#getState`"
+ errorLine1=" featureTagState.getState());"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="149"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.DelegateRegistrationState#getRegisteredFeatureTags`"
+ errorLine1=" Set<String> registeredFt = registrationState.getRegisteredFeatureTags();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="151"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ImsManager#getSipDelegateManager`"
+ errorLine1=" mSipDelegateManager = imsManager.getSipDelegateManager(mDefaultSmsSubId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="220"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#createSipDelegate`"
+ errorLine1=" mSipDelegateManager.createSipDelegate(new DelegateRequest(featureTags),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="231"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `new android.telephony.ims.DelegateRequest`"
+ errorLine1=" mSipDelegateManager.createSipDelegate(new DelegateRequest(featureTags),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="231"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#destroySipDelegate`"
+ errorLine1=" mSipDelegateManager.destroySipDelegate(mSipDelegateConnection,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="247"
+ column="37"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#destroySipDelegate`"
+ errorLine1=" mSipDelegateManager.destroySipDelegate(mSipDelegateConnection,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="322"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getVersion`"
+ errorLine1=' + "mVersion=" + config.getVersion()'
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="332"
+ column="40"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getTransportType`"
+ errorLine1=' + ", \n\tmTransportType=" + config.getTransportType()'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="333"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getLocalAddress`"
+ errorLine1=' + ", \n\tmLocalIpAddr=" + config.getLocalAddress()'
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="334"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServerAddress`"
+ errorLine1=' + ", \n\tmSipServerAddr=" + config.getSipServerAddress()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="335"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#isSipCompactFormEnabled`"
+ errorLine1=' + ", \n\tmIsSipCompactFormEnabled=" + config.isSipCompactFormEnabled()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="336"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#isSipKeepaliveEnabled`"
+ errorLine1=' + ", \n\tmIsSipKeepaliveEnabled=" + config.isSipKeepaliveEnabled()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="337"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getMaxUdpPayloadSizeBytes`"
+ errorLine1=' + ", \n\tmMaxUdpPayloadSize=" + config.getMaxUdpPayloadSizeBytes()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="338"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicUserIdentifier`"
+ errorLine1=' + ", \n\tmPublicUserIdentifier=" + config.getPublicUserIdentifier()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="339"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPrivateUserIdentifier`"
+ errorLine1=' + ", \n\tmPrivateUserIdentifier=" + config.getPrivateUserIdentifier()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="340"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getHomeDomain`"
+ errorLine1=' + ", \n\tmHomeDomain=" + config.getHomeDomain()'
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="341"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getImei`"
+ errorLine1=' + ", \n\tmImei=" + config.getImei()'
+ errorLine2=" ~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="342"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicGruuUri`"
+ errorLine1=' + ", \n\tmGruu=" + config.getPublicGruuUri()'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="343"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAuthenticationHeader`"
+ errorLine1=' + ", \n\tmSipAuthHeader=" + config.getSipAuthenticationHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="344"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAuthenticationNonce`"
+ errorLine1=' + ", \n\tmSipAuthNonce=" + config.getSipAuthenticationNonce()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="345"
+ column="51"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServiceRouteHeader`"
+ errorLine1=' + ", \n\tmServiceRouteHeader=" + config.getSipServiceRouteHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="346"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPathHeader`"
+ errorLine1=' + ", \n\tmPathHeader=" + config.getSipPathHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="347"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipUserAgentHeader`"
+ errorLine1=' + ", \n\tmUserAgentHeader=" + config.getSipUserAgentHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="348"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipContactUserParameter`"
+ errorLine1=' + ", \n\tmContactUserParam=" + config.getSipContactUserParameter()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="349"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPaniHeader`"
+ errorLine1=' + ", \n\tmPaniHeader=" + config.getSipPaniHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="350"
+ column="49"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPlaniHeader`"
+ errorLine1=' + ", \n\tmPlaniHeader=" + config.getSipPlaniHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="351"
+ column="50"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipCniHeader`"
+ errorLine1=' + ", \n\tmCniHeader=" + config.getSipCniHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="352"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAssociatedUriHeader`"
+ errorLine1=' + ", \n\tmAssociatedUriHeader=" + config.getSipAssociatedUriHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="353"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getIpSecConfiguration`"
+ errorLine1=' + ", \n\tmIpSecConfiguration=" + config.getIpSecConfiguration()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="354"
+ column="57"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getNatSocketAddress`"
+ errorLine1=" + ", \n\tmNatConfiguration=" + config.getNatSocketAddress() + '}';"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ line="355"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager.RcsProvisioningCallback`"
+ errorLine1=" new RcsProvisioningCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
+ line="89"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#setRcsClientConfiguration`"
+ errorLine1=" mProvisioningManager.setRcsClientConfiguration(getDefaultClientConfiguration());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
+ line="220"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback`"
+ errorLine1=" mProvisioningManager.registerRcsProvisioningCallback(getMainExecutor(), mCallback);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
+ line="221"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `new android.telephony.ims.RcsClientConfiguration`"
+ errorLine1=" return new RcsClientConfiguration("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
+ line="231"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback`"
+ errorLine1=" mProvisioningManager.unregisterRcsProvisioningCallback(mCallback);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
+ line="348"
+ column="34"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `new android.telephony.gba.UaSecurityProtocolIdentifier.Builder`"
+ errorLine1=" new UaSecurityProtocolIdentifier.Builder();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
- line="129"
- column="57"/>
+ line="120"
+ column="21"/>
</issue>
<issue
@@ -58,134 +476,68 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.DelegateRegistrationState#getRegisteredFeatureTags`"
- errorLine1=" Set<String> registeredFt = registrationState.getRegisteredFeatureTags();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.gba.UaSecurityProtocolIdentifier.Builder#build`"
+ errorLine1=" UaSecurityProtocolIdentifier spId = builder.build();"
+ errorLine2=" ~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="151"
- column="66"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
+ line="129"
+ column="57"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.FeatureTagState#getFeatureTag`"
- errorLine1=' stringBuilder.append(featureTagState.getFeatureTag()).append(" ").append('
- errorLine2=" ~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#bootstrapAuthenticationRequest`"
+ errorLine1=" telephonyManager.bootstrapAuthenticationRequest(mUiccType,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="148"
- column="62"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
+ line="130"
+ column="30"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.FeatureTagState#getState`"
- errorLine1=" featureTagState.getState());"
- errorLine2=" ~~~~~~~~">
+ message="Cast to `BootstrapAuthenticationCallback` requires API level 31 (current min is 30)"
+ errorLine1=" new BootstrapAuthenticationCallback() {"
+ errorLine2=" ^">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="149"
- column="49"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
+ line="135"
+ column="21"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ImsManager#getSipDelegateManager`"
- errorLine1=" mSipDelegateManager = imsManager.getSipDelegateManager(mDefaultSmsSubId);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyManager.BootstrapAuthenticationCallback`"
+ errorLine1=" new BootstrapAuthenticationCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="220"
- column="46"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
+ line="135"
+ column="25"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable`"
- errorLine1=" boolean capable = mProvisioningManager.isRcsVolteSingleRegistrationCapable();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Class requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager.RcsProvisioningCallback`"
+ errorLine1=" new RcsProvisioningCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
- line="204"
- column="60"/>
+ line="80"
+ column="17"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable`"
- errorLine1=" mProvisioningManager.isRcsVolteSingleRegistrationCapable();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `new android.telephony.ims.RcsClientConfiguration`"
+ errorLine1=" return new RcsClientConfiguration("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
- line="166"
- column="34"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback`"
- errorLine1=" mProvisioningManager.registerRcsProvisioningCallback(mExecutorService,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
- line="181"
- column="42"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback`"
- errorLine1=" mProvisioningManager.registerRcsProvisioningCallback(getMainExecutor(), mCallback);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
- line="221"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#setRcsClientConfiguration`"
- errorLine1=" mProvisioningManager.setRcsClientConfiguration(getDefaultClientConfiguration());"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
- line="180"
- column="42"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#setRcsClientConfiguration`"
- errorLine1=" mProvisioningManager.setRcsClientConfiguration(getDefaultClientConfiguration());"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
- line="220"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback`"
- errorLine1=" mProvisioningManager.unregisterRcsProvisioningCallback(mCallback);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
- line="195"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback`"
- errorLine1=" mProvisioningManager.unregisterRcsProvisioningCallback(mCallback);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
- line="348"
- column="34"/>
+ line="106"
+ column="16"/>
</issue>
<issue
@@ -201,122 +553,122 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getContactUri`"
- errorLine1=" b.append(t.getContactUri());"
- errorLine2=" ~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable`"
+ errorLine1=" mProvisioningManager.isRcsVolteSingleRegistrationCapable();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="220"
- column="28"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
+ line="166"
+ column="34"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getServiceCapabilities`"
- errorLine1=" t.getServiceCapabilities();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#setRcsClientConfiguration`"
+ errorLine1=" mProvisioningManager.setRcsClientConfiguration(getDefaultClientConfiguration());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="227"
- column="31"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
+ line="180"
+ column="42"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getServiceCapabilities`"
- errorLine1=" if (t.getServiceCapabilities() != null) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback`"
+ errorLine1=" mProvisioningManager.registerRcsProvisioningCallback(mExecutorService,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="225"
- column="23"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
+ line="181"
+ column="42"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getServiceId`"
- errorLine1=" b.append(t.getServiceId());"
- errorLine2=" ~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback`"
+ errorLine1=" mProvisioningManager.unregisterRcsProvisioningCallback(mCallback);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="222"
- column="28"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
+ line="195"
+ column="38"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getServiceVersion`"
- errorLine1=" b.append(t.getServiceVersion());"
- errorLine2=" ~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable`"
+ errorLine1=" boolean capable = mProvisioningManager.isRcsVolteSingleRegistrationCapable();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="224"
- column="28"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
+ line="204"
+ column="60"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#getSupportedDuplexModes`"
- errorLine1=" b.append(servCaps.getSupportedDuplexModes());"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="233"
- column="39"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#getUnsupportedDuplexModes`"
- errorLine1=" b.append(servCaps.getUnsupportedDuplexModes());"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="235"
- column="39"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#isAudioCapable`"
- errorLine1=" b.append(servCaps.isAudioCapable());"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="229"
- column="39"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#isVideoCapable`"
- errorLine1=" b.append(servCaps.isVideoCapable());"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="231"
- column="39"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactUceCapability#getCapabilityMechanism`"
- errorLine1=" if (c.getCapabilityMechanism() == RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="216"
- column="15"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactUceCapability#getCapabilityTuples`"
- errorLine1=" for (RcsContactPresenceTuple t : c.getCapabilityTuples()) {"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsUceAdapter#requestCapabilities`"
+ errorLine1=" mImsRcsManager.getUceAdapter().requestCapabilities(contactList, getMainExecutor(),"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="218"
+ line="95"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Cast to `CapabilitiesCallback` requires API level 31 (current min is 30)"
+ errorLine1=" new RcsUceAdapter.CapabilitiesCallback() {"
+ errorLine2=" ^">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="96"
+ column="25"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 31 (current min is 30): `android.telephony.ims.RcsUceAdapter.CapabilitiesCallback`"
+ errorLine1=" new RcsUceAdapter.CapabilitiesCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="96"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsUceAdapter#requestAvailability`"
+ errorLine1=" mImsRcsManager.getUceAdapter().requestAvailability(contactList.get(0),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="135"
+ column="48"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Cast to `CapabilitiesCallback` requires API level 31 (current min is 30)"
+ errorLine1=" getMainExecutor(), new RcsUceAdapter.CapabilitiesCallback() {"
+ errorLine2=" ^">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="136"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 31 (current min is 30): `android.telephony.ims.RcsUceAdapter.CapabilitiesCallback`"
+ errorLine1=" getMainExecutor(), new RcsUceAdapter.CapabilitiesCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="136"
column="48"/>
</issue>
@@ -355,475 +707,123 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsUceAdapter#requestAvailability`"
- errorLine1=" mImsRcsManager.getUceAdapter().requestAvailability(contactList.get(0),"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactUceCapability#getCapabilityMechanism`"
+ errorLine1=" if (c.getCapabilityMechanism() == RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="216"
+ column="15"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactUceCapability#getCapabilityTuples`"
+ errorLine1=" for (RcsContactPresenceTuple t : c.getCapabilityTuples()) {"
errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="135"
+ line="218"
column="48"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsUceAdapter#requestCapabilities`"
- errorLine1=" mImsRcsManager.getUceAdapter().requestCapabilities(contactList, getMainExecutor(),"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getContactUri`"
+ errorLine1=" b.append(t.getContactUri());"
+ errorLine2=" ~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="95"
- column="48"/>
+ line="220"
+ column="28"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getHomeDomain`"
- errorLine1=' + ", \n\tmHomeDomain=" + config.getHomeDomain()'
- errorLine2=" ~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getServiceId`"
+ errorLine1=" b.append(t.getServiceId());"
+ errorLine2=" ~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="341"
- column="49"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="222"
+ column="28"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getImei`"
- errorLine1=' + ", \n\tmImei=" + config.getImei()'
- errorLine2=" ~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getServiceVersion`"
+ errorLine1=" b.append(t.getServiceVersion());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="342"
- column="43"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="224"
+ column="28"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getIpSecConfiguration`"
- errorLine1=' + ", \n\tmIpSecConfiguration=" + config.getIpSecConfiguration()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getServiceCapabilities`"
+ errorLine1=" if (t.getServiceCapabilities() != null) {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="354"
- column="57"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="225"
+ column="23"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getLocalAddress`"
- errorLine1=' + ", \n\tmLocalIpAddr=" + config.getLocalAddress()'
- errorLine2=" ~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple#getServiceCapabilities`"
+ errorLine1=" t.getServiceCapabilities();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="334"
- column="50"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="227"
+ column="31"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getMaxUdpPayloadSizeBytes`"
- errorLine1=' + ", \n\tmMaxUdpPayloadSize=" + config.getMaxUdpPayloadSizeBytes()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#isAudioCapable`"
+ errorLine1=" b.append(servCaps.isAudioCapable());"
+ errorLine2=" ~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="338"
- column="56"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
+ line="229"
+ column="39"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getNatSocketAddress`"
- errorLine1=" + ", \n\tmNatConfiguration=" + config.getNatSocketAddress() + '}';"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#isVideoCapable`"
+ errorLine1=" b.append(servCaps.isVideoCapable());"
+ errorLine2=" ~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="355"
- column="55"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPrivateUserIdentifier`"
- errorLine1=' + ", \n\tmPrivateUserIdentifier=" + config.getPrivateUserIdentifier()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="340"
- column="60"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicGruuUri`"
- errorLine1=' + ", \n\tmGruu=" + config.getPublicGruuUri()'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="343"
- column="43"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicUserIdentifier`"
- errorLine1=' + ", \n\tmPublicUserIdentifier=" + config.getPublicUserIdentifier()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="339"
- column="59"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAssociatedUriHeader`"
- errorLine1=' + ", \n\tmAssociatedUriHeader=" + config.getSipAssociatedUriHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="353"
- column="58"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAuthenticationHeader`"
- errorLine1=' + ", \n\tmSipAuthHeader=" + config.getSipAuthenticationHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="344"
- column="52"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAuthenticationNonce`"
- errorLine1=' + ", \n\tmSipAuthNonce=" + config.getSipAuthenticationNonce()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="345"
- column="51"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipCniHeader`"
- errorLine1=' + ", \n\tmCniHeader=" + config.getSipCniHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="352"
- column="48"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipContactUserParameter`"
- errorLine1=' + ", \n\tmContactUserParam=" + config.getSipContactUserParameter()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="349"
- column="55"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPaniHeader`"
- errorLine1=' + ", \n\tmPaniHeader=" + config.getSipPaniHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="350"
- column="49"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPathHeader`"
- errorLine1=' + ", \n\tmPathHeader=" + config.getSipPathHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="347"
- column="49"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPlaniHeader`"
- errorLine1=' + ", \n\tmPlaniHeader=" + config.getSipPlaniHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="351"
- column="50"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServerAddress`"
- errorLine1=' + ", \n\tmSipServerAddr=" + config.getSipServerAddress()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="335"
- column="52"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServiceRouteHeader`"
- errorLine1=' + ", \n\tmServiceRouteHeader=" + config.getSipServiceRouteHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="346"
- column="57"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipUserAgentHeader`"
- errorLine1=' + ", \n\tmUserAgentHeader=" + config.getSipUserAgentHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="348"
- column="54"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getTransportType`"
- errorLine1=' + ", \n\tmTransportType=" + config.getTransportType()'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="333"
- column="52"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getVersion`"
- errorLine1=' + "mVersion=" + config.getVersion()'
- errorLine2=" ~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="332"
- column="40"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#isSipCompactFormEnabled`"
- errorLine1=' + ", \n\tmIsSipCompactFormEnabled=" + config.isSipCompactFormEnabled()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="336"
- column="62"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#isSipKeepaliveEnabled`"
- errorLine1=' + ", \n\tmIsSipKeepaliveEnabled=" + config.isSipKeepaliveEnabled()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="337"
- column="60"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#createSipDelegate`"
- errorLine1=" mSipDelegateManager.createSipDelegate(new DelegateRequest(featureTags),"
- errorLine2=" ~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
+ file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
line="231"
- column="41"/>
+ column="39"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#destroySipDelegate`"
- errorLine1=" mSipDelegateManager.destroySipDelegate(mSipDelegateConnection,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="247"
- column="37"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#destroySipDelegate`"
- errorLine1=" mSipDelegateManager.destroySipDelegate(mSipDelegateConnection,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="322"
- column="33"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.gba.UaSecurityProtocolIdentifier.Builder`"
- errorLine1=" new UaSecurityProtocolIdentifier.Builder();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
- line="120"
- column="21"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.ims.DelegateRequest`"
- errorLine1=" mSipDelegateManager.createSipDelegate(new DelegateRequest(featureTags),"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="231"
- column="59"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.ims.RcsClientConfiguration`"
- errorLine1=" return new RcsClientConfiguration("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
- line="231"
- column="16"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.ims.RcsClientConfiguration`"
- errorLine1=" return new RcsClientConfiguration("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
- line="106"
- column="16"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Cast to `BootstrapAuthenticationCallback` requires API level 31 (current min is 30)"
- errorLine1=" new BootstrapAuthenticationCallback() {"
- errorLine2=" ^">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
- line="135"
- column="21"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Cast to `CapabilitiesCallback` requires API level 31 (current min is 30)"
- errorLine1=" getMainExecutor(), new RcsUceAdapter.CapabilitiesCallback() {"
- errorLine2=" ^">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#getSupportedDuplexModes`"
+ errorLine1=" b.append(servCaps.getSupportedDuplexModes());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="136"
- column="44"/>
+ line="233"
+ column="39"/>
</issue>
<issue
id="NewApi"
- message="Cast to `CapabilitiesCallback` requires API level 31 (current min is 30)"
- errorLine1=" new RcsUceAdapter.CapabilitiesCallback() {"
- errorLine2=" ^">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#getUnsupportedDuplexModes`"
+ errorLine1=" b.append(servCaps.getUnsupportedDuplexModes());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="96"
- column="25"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyManager.BootstrapAuthenticationCallback`"
- errorLine1=" new BootstrapAuthenticationCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/GbaActivity.java"
- line="135"
- column="25"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager.RcsProvisioningCallback`"
- errorLine1=" new RcsProvisioningCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/FileUploadActivity.java"
- line="89"
- column="17"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager.RcsProvisioningCallback`"
- errorLine1=" new RcsProvisioningCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/ProvisioningActivity.java"
- line="80"
- column="17"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.ims.RcsUceAdapter.CapabilitiesCallback`"
- errorLine1=" getMainExecutor(), new RcsUceAdapter.CapabilitiesCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="136"
- column="48"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.ims.RcsUceAdapter.CapabilitiesCallback`"
- errorLine1=" new RcsUceAdapter.CapabilitiesCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/UceActivity.java"
- line="96"
- column="29"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.ims.stub.DelegateConnectionMessageCallback`"
- errorLine1=" new DelegateConnectionMessageCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="87"
- column="17"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.ims.stub.DelegateConnectionStateCallback`"
- errorLine1=" new DelegateConnectionStateCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/DelegateActivity.java"
- line="117"
- column="17"/>
+ line="235"
+ column="39"/>
</issue>
</issues>
\ No newline at end of file
diff --git a/testapps/TestRcsApp/TestApp/res/layout/CarrierLockListLayout.xml b/testapps/TestRcsApp/TestApp/res/layout/CarrierLockListLayout.xml
new file mode 100644
index 0000000..f07c65c
--- /dev/null
+++ b/testapps/TestRcsApp/TestApp/res/layout/CarrierLockListLayout.xml
@@ -0,0 +1,77 @@
+<!--
+ ~ 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.
+ -->
+
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context=".MainActivity">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/noLockMode"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/no_LockMode"
+ android:textAlignment="center"
+ android:textAllCaps="false" />
+
+ <Button
+ android:id="@+id/lockToVZW"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/no_LockTo_VZW"
+ android:textAlignment="center"
+ android:textAllCaps="false" />
+
+ <Button
+ android:id="@+id/lockToATT"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/no_LockTo_ATT"
+ android:textAlignment="center"
+ android:textAllCaps="false" />
+
+ <Button
+ android:id="@+id/lockToTMO"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/no_LockTo_TMO"
+ android:textAlignment="center"
+ android:textAllCaps="false" />
+
+ <Button
+ android:id="@+id/lockToKOODOS"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/no_LockTo_KOODOS"
+ android:textAlignment="center"
+ android:textAllCaps="false" />
+
+ <Button
+ android:id="@+id/lockToTELUS"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/no_LockTo_TELUS"
+ android:textAlignment="center"
+ android:textAllCaps="false" />
+ </LinearLayout>
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/testapps/TestRcsApp/TestApp/res/layout/activity_main.xml b/testapps/TestRcsApp/TestApp/res/layout/activity_main.xml
index 939feb0..ebf5508 100644
--- a/testapps/TestRcsApp/TestApp/res/layout/activity_main.xml
+++ b/testapps/TestRcsApp/TestApp/res/layout/activity_main.xml
@@ -74,6 +74,14 @@
android:textAlignment="center"
android:textAllCaps="false" />
+ <Button
+ android:id="@+id/setCarrierLockMode"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/setCarrierLockMode"
+ android:textAlignment="center"
+ android:textAllCaps="false"/>
+
<TextView
android:id="@+id/version_info"
android:layout_width="match_parent"
diff --git a/testapps/TestRcsApp/TestApp/res/values/donottranslate_strings.xml b/testapps/TestRcsApp/TestApp/res/values/donottranslate_strings.xml
index f52b70d..b017139 100644
--- a/testapps/TestRcsApp/TestApp/res/values/donottranslate_strings.xml
+++ b/testapps/TestRcsApp/TestApp/res/values/donottranslate_strings.xml
@@ -72,6 +72,8 @@
<string name="browse">Browse</string>
<string name="upload">Upload</string>
<string name="upload_file_gba">Upload File with GBA</string>
+ <string name="setCarrierLockMode">CarrierLock</string>
+
<string name="invalid_parameters">Invalid Parameters</string>
<string name="server">Server:</string>
<string name="file_name">File Name:</string>
@@ -79,6 +81,13 @@
<string name="file_empty">File is empty</string>
<string name="version_info">Version: %s</string>
+ <string name="no_LockMode">NoLock/ UnLocked</string>
+ <string name="no_LockTo_VZW">Lock to Verizon</string>
+ <string name="no_LockTo_ATT">Lock to ATT</string>
+ <string name="no_LockTo_TMO">Lock to TMO</string>
+ <string name="no_LockTo_KOODOS">Lock to KOODO</string>
+ <string name="no_LockTo_TELUS">Lock to TELUS</string>
+
<string-array name="rcs_profile">
<item>UP_1.0</item>
<item>UP_2.3</item>
diff --git a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/MainActivity.java b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/MainActivity.java
index 89c5268..5d2db73 100644
--- a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/MainActivity.java
+++ b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/MainActivity.java
@@ -29,6 +29,8 @@
import androidx.appcompat.app.AppCompatActivity;
+import com.google.android.sample.rcsclient.carrierLock.CarrieLockModeListActivity;
+
/** An activity to show function list. */
public class MainActivity extends AppCompatActivity {
private static final String TAG = "TestRcsApp.MainActivity";
@@ -39,6 +41,7 @@
private Button mMessageClientButton;
private Button mFileUploadButton;
private TextView mVersionInfo;
+ private Button mCarrierLockModeListBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -56,6 +59,7 @@
mGbaButton = (Button) this.findViewById(R.id.gba);
mFileUploadButton = findViewById(R.id.uploadFile);
mVersionInfo = this.findViewById(R.id.version_info);
+ mCarrierLockModeListBtn = findViewById(R.id.setCarrierLockMode);
mProvisionButton.setOnClickListener(view -> {
Intent intent = new Intent(this, ProvisioningActivity.class);
MainActivity.this.startActivity(intent);
@@ -90,6 +94,11 @@
appVersionName);
mVersionInfo.setText(version);
}
+
+ mCarrierLockModeListBtn.setOnClickListener(view -> {
+ Intent intent = new Intent(this, CarrieLockModeListActivity.class);
+ MainActivity.this.startActivity(intent);
+ });
}
@Override
diff --git a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrieLockModeListActivity.java b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrieLockModeListActivity.java
new file mode 100644
index 0000000..6547aeb
--- /dev/null
+++ b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrieLockModeListActivity.java
@@ -0,0 +1,79 @@
+/*
+ * 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.google.android.sample.rcsclient.carrierLock;
+
+import android.os.Bundle;
+import android.widget.Button;
+import android.widget.Toast;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.android.sample.rcsclient.R;
+
+public class CarrieLockModeListActivity extends AppCompatActivity {
+
+ private final CarrierLockProvider mCarrierLockProvider = new CarrierLockProvider();
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.CarrierLockListLayout);
+
+ Button noLockModeBtn = this.findViewById(R.id.noLockMode);
+ assert noLockModeBtn != null;
+ noLockModeBtn.setOnClickListener(view -> {
+ mCarrierLockProvider.setLockMode(CarrierRestriction.UNLOCKED);
+ Toast.makeText(this, "Lock mode set to UNLOCKED", Toast.LENGTH_LONG).show();
+ });
+
+ Button vzwLockModeBtn = this.findViewById(R.id.lockToVZW);
+ assert vzwLockModeBtn != null;
+ vzwLockModeBtn.setOnClickListener(view -> {
+ mCarrierLockProvider.setLockMode(CarrierRestriction.LOCK_TO_VZW);
+ Toast.makeText(this, "Lock mode set to VZW", Toast.LENGTH_LONG).show();
+ });
+
+ Button attLockModeBtn = this.findViewById(R.id.lockToATT);
+ assert attLockModeBtn != null;
+ attLockModeBtn.setOnClickListener(view -> {
+ mCarrierLockProvider.setLockMode(CarrierRestriction.LOCK_TO_ATT);
+ Toast.makeText(this, "Lock mode set to ATT", Toast.LENGTH_LONG).show();
+ });
+
+ Button tmoLockModeBtn = this.findViewById(R.id.lockToTMO);
+ assert tmoLockModeBtn != null;
+ tmoLockModeBtn.setOnClickListener(view -> {
+ mCarrierLockProvider.setLockMode(CarrierRestriction.LOCK_TO_TMO);
+ Toast.makeText(this, "Lock mode set to TMO", Toast.LENGTH_LONG).show();
+ });
+
+ Button koodoLockModeBtn = this.findViewById(R.id.lockToKOODOS);
+ assert koodoLockModeBtn != null;
+ koodoLockModeBtn.setOnClickListener(view -> {
+ mCarrierLockProvider.setLockMode(CarrierRestriction.LOCK_TO_KOODO);
+ Toast.makeText(this, "Lock mode set to KOODO", Toast.LENGTH_LONG).show();
+ });
+
+ Button telusLockModeBtn = this.findViewById(R.id.lockToTELUS);
+ assert telusLockModeBtn != null;
+ telusLockModeBtn.setOnClickListener(view -> {
+ mCarrierLockProvider.setLockMode(CarrierRestriction.LOCK_TO_TELUS);
+ Toast.makeText(this, "Lock mode set to TELUS", Toast.LENGTH_LONG).show();
+ });
+ }
+}
diff --git a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrierLockProvider.java b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrierLockProvider.java
new file mode 100644
index 0000000..8fa3cd6
--- /dev/null
+++ b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrierLockProvider.java
@@ -0,0 +1,175 @@
+/*
+ * 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.google.android.sample.rcsclient.carrierLock;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.util.Log;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringJoiner;
+
+public class CarrierLockProvider extends ContentProvider {
+
+ public static final String AUTHORITY = "com.sample.lockProvider";
+ public static final String TAG = "TestCarrierLockProvider";
+
+ public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/carrierLock");
+ // content://com.sample.lockProvider/carrierLock
+
+ private static CarrierRestriction mLockMode = CarrierRestriction.UNLOCKED;
+ private static final ArrayList<Integer> mCarrierIds = new ArrayList<>();
+
+ @Override
+ public boolean onCreate() {
+ return true;
+ }
+
+ @Override
+ public Bundle call(String method, String args, Bundle extras) {
+ Bundle result = new Bundle();
+ Log.d(TAG, "call query STARTED on method = " + method);
+ switch (method) {
+ case "getCarrierRestrictionStatus":
+ try {
+ if (mLockMode == CarrierRestriction.UNLOCKED) {
+ result.putInt("restriction_status", 0); // Unlocked
+ } else {
+ result.putInt("restriction_status", 2); // Locked/Restricted
+ }
+ mCarrierIds.clear();
+ Log.d(TAG, "Query come : Lock mode set to " + mLockMode);
+ switch (mLockMode) {
+ case UNLOCKED:
+ // Do Nothing
+ break;
+ case LOCK_TO_VZW:
+ mCarrierIds.add(1839);
+ break;
+ case LOCK_TO_ATT:
+ mCarrierIds.add(1187);
+ mCarrierIds.add(10021);
+ mCarrierIds.add(2119);
+ mCarrierIds.add(2120);
+ mCarrierIds.add(1779);
+ mCarrierIds.add(10028);
+ break;
+ case LOCK_TO_TMO:
+ mCarrierIds.add(1);
+ break;
+ case LOCK_TO_KOODO:
+ mCarrierIds.add(2020);
+ break;
+ case LOCK_TO_TELUS:
+ mCarrierIds.add(1404);
+ break;
+ default:
+ // Nothing
+ }
+ StringJoiner joiner = new StringJoiner(", ");
+ if (!mCarrierIds.isEmpty()) {
+ result.putIntegerArrayList("allowed_carrier_ids", mCarrierIds);
+ for (Integer num : mCarrierIds) {
+ joiner.add(num.toString());
+ }
+ result.putString("PrintableCarrierIds", joiner.toString());
+ Log.d(TAG, "Locked to carrierIds = " + joiner.toString());
+ } else {
+ result.putString("allowed_carrier_ids", "");
+ result.putString("PrintableCarrierIds", "");
+ }
+
+ } catch (Exception e) {
+ Log.e(TAG, " call :: query :: exception = " + e.getMessage());
+ }
+ return result;
+
+ case "getList:":
+ String list = String.valueOf(
+ mCarrierIds.size());
+ result.putString("carrierList", list);
+ return result;
+ default:
+ return null;
+ }
+ }
+
+ private void updateLockValue(int lockValue) {
+ Log.d(TAG, "updateLockValue through ADB to = " + lockValue);
+ switch (lockValue) {
+ case 1:
+ mLockMode = CarrierRestriction.LOCK_TO_VZW;
+ break;
+ case 2:
+ mLockMode = CarrierRestriction.LOCK_TO_ATT;
+ break;
+ case 3:
+ mLockMode = CarrierRestriction.LOCK_TO_TMO;
+ break;
+ case 4:
+ mLockMode = CarrierRestriction.LOCK_TO_KOODO;
+ break;
+ case 5:
+ mLockMode = CarrierRestriction.LOCK_TO_TELUS;
+ break;
+ default:
+ mLockMode = CarrierRestriction.UNLOCKED;
+ break;
+ }
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ Log.d(TAG, "CarrierLockProvider Query");
+ return null;
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return "vnd.android.cursor.dir/vnd." + AUTHORITY + ".books";
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ Log.d(TAG, "CarrierLockProvider insert START");
+ assert values != null;
+ int newValue = values.getAsInteger("newValue");
+ updateLockValue(newValue);
+ return CONTENT_URI;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ public void setLockMode(CarrierRestriction lockMode) {
+ mLockMode = lockMode;
+ Log.d(TAG, "Setting lockMode to " + mLockMode);
+ }
+}
\ No newline at end of file
diff --git a/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrierRestriction.java b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrierRestriction.java
new file mode 100644
index 0000000..34f9e7b
--- /dev/null
+++ b/testapps/TestRcsApp/TestApp/src/com/google/android/sample/rcsclient/carrierLock/CarrierRestriction.java
@@ -0,0 +1,26 @@
+/*
+ * 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.google.android.sample.rcsclient.carrierLock;
+
+public enum CarrierRestriction {
+ UNLOCKED,
+ LOCK_TO_VZW,
+ LOCK_TO_ATT,
+ LOCK_TO_TMO,
+ LOCK_TO_KOODO,
+ LOCK_TO_TELUS
+}
diff --git a/testapps/TestRcsApp/aosp_test_rcsclient/lint-baseline.xml b/testapps/TestRcsApp/aosp_test_rcsclient/lint-baseline.xml
index e0c7c3e..b2110a3 100644
--- a/testapps/TestRcsApp/aosp_test_rcsclient/lint-baseline.xml
+++ b/testapps/TestRcsApp/aosp_test_rcsclient/lint-baseline.xml
@@ -1,48 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 8.0.0-dev" type="baseline" dependencies="true" variant="all" version="8.0.0-dev">
+<issues format="6" by="lint 8.4.0-alpha01" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha01">
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.net.ConnectivityManager#registerQosCallback`"
- errorLine1=" connectivityManager.registerQosCallback(new QosSocketInfo(network, socket),"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/msrp/MsrpSession.java"
- line="118"
- column="33"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.net.ConnectivityManager#unregisterQosCallback`"
- errorLine1=" connectivityManager.unregisterQosCallback(qosCallback);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/msrp/MsrpSession.java"
- line="181"
- column="29"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#bootstrapAuthenticationRequest`"
- errorLine1=" telephonyManager.bootstrapAuthenticationRequest("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `new android.telephony.gba.UaSecurityProtocolIdentifier.Builder`"
+ errorLine1=" new UaSecurityProtocolIdentifier.Builder();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
- line="97"
- column="26"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.gba.UaSecurityProtocolIdentifier.Builder#build`"
- errorLine1=" UaSecurityProtocolIdentifier spId = builder.build();"
- errorLine2=" ~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
- line="79"
- column="53"/>
+ line="55"
+ column="17"/>
</issue>
<issue
@@ -91,673 +58,57 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.DelegateRegistrationState#getRegisteredFeatureTags`"
- errorLine1=" .getRegisteredFeatureTags()"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.gba.UaSecurityProtocolIdentifier.Builder#build`"
+ errorLine1=" UaSecurityProtocolIdentifier spId = builder.build();"
+ errorLine2=" ~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="139"
- column="34"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.DelegateRegistrationState#getRegisteredFeatureTags`"
- errorLine1=" Set<String> registeredFt = registrationState.getRegisteredFeatureTags();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="223"
- column="58"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.FeatureTagState#getFeatureTag`"
- errorLine1=' stringBuilder.append(featureTagState.getFeatureTag()).append(" ").append('
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="220"
- column="54"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.FeatureTagState#getState`"
- errorLine1=" featureTagState.getState());"
- errorLine2=" ~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="221"
- column="41"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ImsManager#getSipDelegateManager`"
- errorLine1=" this.sipDelegateManager = imsManager.getSipDelegateManager(subscriptionId);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="77"
- column="46"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable`"
- errorLine1=" return provisioningManager.isRcsVolteSingleRegistrationCapable();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
- line="166"
- column="36"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback`"
- errorLine1=" provisioningManager.registerRcsProvisioningCallback(executorService, callback);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
- line="147"
- column="33"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#setRcsClientConfiguration`"
- errorLine1=" provisioningManager.setRcsClientConfiguration(clientConfiguration);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
- line="111"
- column="29"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#triggerRcsReconfiguration`"
- errorLine1=" provisioningManager.triggerRcsReconfiguration();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
- line="176"
- column="29"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback`"
- errorLine1=" provisioningManager.unregisterRcsProvisioningCallback(callback);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
- line="158"
- column="33"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getHomeDomain`"
- errorLine1=' + ", \n\tmHomeDomain=" + config.getHomeDomain()'
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="246"
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
+ line="79"
column="53"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getHomeDomain`"
- errorLine1=" return mConfiguration.getHomeDomain();"
- errorLine2=" ~~~~~~~~~~~~~">
+ message="Cast to `BootstrapAuthenticationCallback` requires API level 31 (current min is 30)"
+ errorLine1=" new TelephonyManager.BootstrapAuthenticationCallback() {"
+ errorLine2=" ^">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="317"
- column="35"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
+ line="81"
+ column="17"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getImei`"
- errorLine1=' + ", \n\tmImei=" + config.getImei()'
- errorLine2=" ~~~~~~~">
+ message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyManager.BootstrapAuthenticationCallback`"
+ errorLine1=" new TelephonyManager.BootstrapAuthenticationCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="247"
- column="47"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
+ line="81"
+ column="21"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getImei`"
- errorLine1=" return mConfiguration.getImei();"
- errorLine2=" ~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.TelephonyManager#bootstrapAuthenticationRequest`"
+ errorLine1=" telephonyManager.bootstrapAuthenticationRequest("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="357"
- column="35"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
+ line="97"
+ column="26"/>
</issue>
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getIpSecConfiguration`"
- errorLine1=' + ", \n\tmIpSecConfiguration=" + config.getIpSecConfiguration()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `new android.telephony.ims.SipMessage`"
+ errorLine1=" return new SipMessage(startLine, headers.toString(), rawContent);"
+ errorLine2=" ~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="259"
- column="61"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getIpSecConfiguration`"
- errorLine1=" SipDelegateConfiguration.IpSecConfiguration c = mConfiguration.getIpSecConfiguration();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="333"
- column="76"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getLocalAddress`"
- errorLine1=' + ", \n\tmLocalAddr=" + config.getLocalAddress()'
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="239"
- column="52"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getLocalAddress`"
- errorLine1=" return mConfiguration.getLocalAddress().getAddress().getHostAddress();"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="296"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getLocalAddress`"
- errorLine1=" return mConfiguration.getLocalAddress().getPort();"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="301"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getMaxUdpPayloadSizeBytes`"
- errorLine1=' + ", \n\tmMaxUdpPayloadSize=" + config.getMaxUdpPayloadSizeBytes()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="243"
- column="60"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getMaxUdpPayloadSizeBytes`"
- errorLine1=" ? mConfiguration.getMaxUdpPayloadSizeBytes() : 1500;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="378"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getMaxUdpPayloadSizeBytes`"
- errorLine1=" return mConfiguration.getMaxUdpPayloadSizeBytes() > 0"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="377"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getNatSocketAddress`"
- errorLine1=" + ", \n\tmNatConfiguration=" + config.getNatSocketAddress() + '}';"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="260"
- column="59"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPrivateUserIdentifier`"
- errorLine1=' + ", \n\tmPrivateUserIdentifier=" + config.getPrivateUserIdentifier()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="245"
- column="64"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicGruuUri`"
- errorLine1=' + ", \n\tmGruu=" + config.getPublicGruuUri()'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="248"
- column="47"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicUserIdentifier`"
- errorLine1=' + ", \n\tmPublicUserIdentifier=" + config.getPublicUserIdentifier()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="244"
- column="63"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicUserIdentifier`"
- errorLine1=" return mConfiguration.getPublicUserIdentifier();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="312"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAssociatedUriHeader`"
- errorLine1=' + ", \n\tmAssociatedUriHeader=" + config.getSipAssociatedUriHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="258"
- column="62"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAssociatedUriHeader`"
- errorLine1=" String associatedUris = mConfiguration.getSipAssociatedUriHeader();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="322"
- column="52"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAuthenticationHeader`"
- errorLine1=' + ", \n\tmSipAuthHeader=" + config.getSipAuthenticationHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="249"
- column="56"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAuthenticationNonce`"
- errorLine1=' + ", \n\tmSipAuthNonce=" + config.getSipAuthenticationNonce()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="250"
- column="55"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipCniHeader`"
- errorLine1=' + ", \n\tmCniHeader=" + config.getSipCniHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="257"
- column="52"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipContactUserParameter`"
- errorLine1=' + ", \n\tmContactUserParam=" + config.getSipContactUserParameter()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="254"
- column="59"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipContactUserParameter`"
- errorLine1=" return mConfiguration.getSipContactUserParameter();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="352"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPaniHeader`"
- errorLine1=' + ", \n\tmPaniHeader=" + config.getSipPaniHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="255"
- column="53"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPaniHeader`"
- errorLine1=" return mConfiguration.getSipPaniHeader();"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="362"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPathHeader`"
- errorLine1=' + ", \n\tmPathHeader=" + config.getSipPathHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="252"
- column="53"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPlaniHeader`"
- errorLine1=' + ", \n\tmPlaniHeader=" + config.getSipPlaniHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="256"
- column="54"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPlaniHeader`"
- errorLine1=" return mConfiguration.getSipPlaniHeader();"
- errorLine2=" ~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="367"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServerAddress`"
- errorLine1=' + ", \n\tmSipServerAddr=" + config.getSipServerAddress()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="240"
- column="56"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServerAddress`"
- errorLine1=" return mConfiguration.getSipServerAddress().getAddress().getHostAddress();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="286"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServerAddress`"
- errorLine1=" return mConfiguration.getSipServerAddress().getPort();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="291"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServiceRouteHeader`"
- errorLine1=' + ", \n\tmServiceRouteHeader=" + config.getSipServiceRouteHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="251"
- column="61"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServiceRouteHeader`"
- errorLine1=" mConfiguration.getSipServiceRouteHeader();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="343"
- column="36"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipUserAgentHeader`"
- errorLine1=' + ", \n\tmUserAgentHeader=" + config.getSipUserAgentHeader()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="253"
- column="58"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipUserAgentHeader`"
- errorLine1=" return mConfiguration.getSipUserAgentHeader();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="372"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getTransportType`"
- errorLine1=' + ", \n\tmTransportType=" + config.getTransportType()'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="238"
- column="56"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getTransportType`"
- errorLine1=" int sipTransport = mConfiguration.getTransportType();"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="306"
- column="47"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getVersion`"
- errorLine1=" + registeredSipConfig.getVersion());"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="127"
- column="63"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getVersion`"
- errorLine1=' + "mVersion=" + config.getVersion()'
- errorLine2=" ~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="237"
- column="44"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getVersion`"
- errorLine1=" return mConfiguration.getVersion();"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="281"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#isSipCompactFormEnabled`"
- errorLine1=' + ", \n\tmIsSipCompactFormEnabled=" + config.isSipCompactFormEnabled()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="241"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#isSipKeepaliveEnabled`"
- errorLine1=' + ", \n\tmIsSipKeepaliveEnabled=" + config.isSipKeepaliveEnabled()'
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="242"
- column="64"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration#getSipSecurityVerifyHeader`"
- errorLine1=" return c.getSipSecurityVerifyHeader();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="337"
- column="22"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConnection#sendMessage`"
- errorLine1=" sipDelegateConnection.sendMessage(MessageConverter.toPlatformMessage(message),"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="271"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#createSipDelegate`"
- errorLine1=" controller.sipDelegateManager.createSipDelegate("
- errorLine2=" ~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="205"
- column="47"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#destroySipDelegate`"
- errorLine1=" sipDelegateManager.destroySipDelegate(context.sipDelegateConnection,"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="92"
- column="32"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipMessage#getContent`"
- errorLine1=" return new SipMessage(message.getStartLine(), headers, message.getContent());"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="395"
- column="76"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipMessage#getHeaderSection`"
- errorLine1=' + message.getHeaderSection().substring(0, 10) + "->"'
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="392"
- column="35"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipMessage#getHeaderSection`"
- errorLine1=" String headers = message.getHeaderSection();"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="387"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipMessage#getStartLine`"
- errorLine1=" return new SipMessage(message.getStartLine(), headers, message.getContent());"
- errorLine2=" ~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="395"
- column="43"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/MessageConverter.java"
+ line="72"
+ column="16"/>
</issue>
<issue
@@ -784,94 +135,6 @@
<issue
id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.net.QosSocketInfo`"
- errorLine1=" connectivityManager.registerQosCallback(new QosSocketInfo(network, socket),"
- errorLine2=" ~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/msrp/MsrpSession.java"
- line="118"
- column="53"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.gba.UaSecurityProtocolIdentifier.Builder`"
- errorLine1=" new UaSecurityProtocolIdentifier.Builder();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
- line="55"
- column="17"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.ims.DelegateRequest`"
- errorLine1=" DelegateRequest request = new DelegateRequest(imsService.getFeatureTags());"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="203"
- column="39"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.ims.RcsClientConfiguration`"
- errorLine1=" return new RcsClientConfiguration("
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
- line="74"
- column="16"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.ims.SipMessage`"
- errorLine1=" return new SipMessage(message.getStartLine(), headers, message.getContent());"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
- line="395"
- column="20"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level 31 (current min is 30): `new android.telephony.ims.SipMessage`"
- errorLine1=" return new SipMessage(startLine, headers.toString(), rawContent);"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/MessageConverter.java"
- line="72"
- column="16"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Cast to `BootstrapAuthenticationCallback` requires API level 31 (current min is 30)"
- errorLine1=" new TelephonyManager.BootstrapAuthenticationCallback() {"
- errorLine2=" ^">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
- line="81"
- column="17"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Cast to `RcsProvisioningCallback` requires API level 31 (current min is 30)"
- errorLine1=" new RcsProvisioningCallback() {"
- errorLine2=" ^">
- <location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
- line="114"
- column="17"/>
- </issue>
-
- <issue
- id="NewApi"
message="Class requires API level 31 (current min is 30): `android.net.QosCallback`"
errorLine1=" private final QosCallback qosCallback = new QosCallback() {"
errorLine2=" ~~~~~~~~~~~">
@@ -883,24 +146,68 @@
<issue
id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.TelephonyManager.BootstrapAuthenticationCallback`"
- errorLine1=" new TelephonyManager.BootstrapAuthenticationCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `new android.net.QosSocketInfo`"
+ errorLine1=" connectivityManager.registerQosCallback(new QosSocketInfo(network, socket),"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/filetransfer/requestexecutor/GbaAuthenticationProvider.java"
- line="81"
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/protocol/msrp/MsrpSession.java"
+ line="118"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ImsManager#getSipDelegateManager`"
+ errorLine1=" this.sipDelegateManager = imsManager.getSipDelegateManager(subscriptionId);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="77"
+ column="46"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#destroySipDelegate`"
+ errorLine1=" sipDelegateManager.destroySipDelegate(context.sipDelegateConnection,"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="92"
+ column="32"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 31 (current min is 30): `android.telephony.ims.stub.DelegateConnectionStateCallback`"
+ errorLine1=" new DelegateConnectionStateCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="114"
column="21"/>
</issue>
<issue
id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager.RcsProvisioningCallback`"
- errorLine1=" new RcsProvisioningCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getVersion`"
+ errorLine1=" + registeredSipConfig.getVersion());"
+ errorLine2=" ~~~~~~~~~~">
<location
- file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
- line="114"
- column="21"/>
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="127"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.DelegateRegistrationState#getRegisteredFeatureTags`"
+ errorLine1=" .getRegisteredFeatureTags()"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="139"
+ column="34"/>
</issue>
<issue
@@ -916,13 +223,684 @@
<issue
id="NewApi"
- message="Class requires API level 31 (current min is 30): `android.telephony.ims.stub.DelegateConnectionStateCallback`"
- errorLine1=" new DelegateConnectionStateCallback() {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ message="Call requires API level 31 (current min is 30): `new android.telephony.ims.DelegateRequest`"
+ errorLine1=" DelegateRequest request = new DelegateRequest(imsService.getFeatureTags());"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
<location
file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="203"
+ column="39"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateManager#createSipDelegate`"
+ errorLine1=" controller.sipDelegateManager.createSipDelegate("
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="205"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.FeatureTagState#getFeatureTag`"
+ errorLine1=' stringBuilder.append(featureTagState.getFeatureTag()).append(" ").append('
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="220"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.FeatureTagState#getState`"
+ errorLine1=" featureTagState.getState());"
+ errorLine2=" ~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="221"
+ column="41"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.DelegateRegistrationState#getRegisteredFeatureTags`"
+ errorLine1=" Set<String> registeredFt = registrationState.getRegisteredFeatureTags();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="223"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getVersion`"
+ errorLine1=' + "mVersion=" + config.getVersion()'
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="237"
+ column="44"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getTransportType`"
+ errorLine1=' + ", \n\tmTransportType=" + config.getTransportType()'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="238"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getLocalAddress`"
+ errorLine1=' + ", \n\tmLocalAddr=" + config.getLocalAddress()'
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="239"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServerAddress`"
+ errorLine1=' + ", \n\tmSipServerAddr=" + config.getSipServerAddress()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="240"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#isSipCompactFormEnabled`"
+ errorLine1=' + ", \n\tmIsSipCompactFormEnabled=" + config.isSipCompactFormEnabled()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="241"
+ column="66"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#isSipKeepaliveEnabled`"
+ errorLine1=' + ", \n\tmIsSipKeepaliveEnabled=" + config.isSipKeepaliveEnabled()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="242"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getMaxUdpPayloadSizeBytes`"
+ errorLine1=' + ", \n\tmMaxUdpPayloadSize=" + config.getMaxUdpPayloadSizeBytes()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="243"
+ column="60"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicUserIdentifier`"
+ errorLine1=' + ", \n\tmPublicUserIdentifier=" + config.getPublicUserIdentifier()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="244"
+ column="63"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPrivateUserIdentifier`"
+ errorLine1=' + ", \n\tmPrivateUserIdentifier=" + config.getPrivateUserIdentifier()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="245"
+ column="64"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getHomeDomain`"
+ errorLine1=' + ", \n\tmHomeDomain=" + config.getHomeDomain()'
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="246"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getImei`"
+ errorLine1=' + ", \n\tmImei=" + config.getImei()'
+ errorLine2=" ~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="247"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicGruuUri`"
+ errorLine1=' + ", \n\tmGruu=" + config.getPublicGruuUri()'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="248"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAuthenticationHeader`"
+ errorLine1=' + ", \n\tmSipAuthHeader=" + config.getSipAuthenticationHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="249"
+ column="56"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAuthenticationNonce`"
+ errorLine1=' + ", \n\tmSipAuthNonce=" + config.getSipAuthenticationNonce()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="250"
+ column="55"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServiceRouteHeader`"
+ errorLine1=' + ", \n\tmServiceRouteHeader=" + config.getSipServiceRouteHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="251"
+ column="61"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPathHeader`"
+ errorLine1=' + ", \n\tmPathHeader=" + config.getSipPathHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="252"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipUserAgentHeader`"
+ errorLine1=' + ", \n\tmUserAgentHeader=" + config.getSipUserAgentHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="253"
+ column="58"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipContactUserParameter`"
+ errorLine1=' + ", \n\tmContactUserParam=" + config.getSipContactUserParameter()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="254"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPaniHeader`"
+ errorLine1=' + ", \n\tmPaniHeader=" + config.getSipPaniHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="255"
+ column="53"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPlaniHeader`"
+ errorLine1=' + ", \n\tmPlaniHeader=" + config.getSipPlaniHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="256"
+ column="54"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipCniHeader`"
+ errorLine1=' + ", \n\tmCniHeader=" + config.getSipCniHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="257"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAssociatedUriHeader`"
+ errorLine1=' + ", \n\tmAssociatedUriHeader=" + config.getSipAssociatedUriHeader()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="258"
+ column="62"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getIpSecConfiguration`"
+ errorLine1=' + ", \n\tmIpSecConfiguration=" + config.getIpSecConfiguration()'
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="259"
+ column="61"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getNatSocketAddress`"
+ errorLine1=" + ", \n\tmNatConfiguration=" + config.getNatSocketAddress() + '}';"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="260"
+ column="59"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConnection#sendMessage`"
+ errorLine1=" sipDelegateConnection.sendMessage(MessageConverter.toPlatformMessage(message),"
+ errorLine2=" ~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="271"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getVersion`"
+ errorLine1=" return mConfiguration.getVersion();"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="281"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServerAddress`"
+ errorLine1=" return mConfiguration.getSipServerAddress().getAddress().getHostAddress();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="286"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServerAddress`"
+ errorLine1=" return mConfiguration.getSipServerAddress().getPort();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="291"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getLocalAddress`"
+ errorLine1=" return mConfiguration.getLocalAddress().getAddress().getHostAddress();"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="296"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getLocalAddress`"
+ errorLine1=" return mConfiguration.getLocalAddress().getPort();"
+ errorLine2=" ~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="301"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getTransportType`"
+ errorLine1=" int sipTransport = mConfiguration.getTransportType();"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="306"
+ column="47"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getPublicUserIdentifier`"
+ errorLine1=" return mConfiguration.getPublicUserIdentifier();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="312"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getHomeDomain`"
+ errorLine1=" return mConfiguration.getHomeDomain();"
+ errorLine2=" ~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="317"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipAssociatedUriHeader`"
+ errorLine1=" String associatedUris = mConfiguration.getSipAssociatedUriHeader();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="322"
+ column="52"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getIpSecConfiguration`"
+ errorLine1=" SipDelegateConfiguration.IpSecConfiguration c = mConfiguration.getIpSecConfiguration();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="333"
+ column="76"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration#getSipSecurityVerifyHeader`"
+ errorLine1=" return c.getSipSecurityVerifyHeader();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="337"
+ column="22"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipServiceRouteHeader`"
+ errorLine1=" mConfiguration.getSipServiceRouteHeader();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="343"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipContactUserParameter`"
+ errorLine1=" return mConfiguration.getSipContactUserParameter();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="352"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getImei`"
+ errorLine1=" return mConfiguration.getImei();"
+ errorLine2=" ~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="357"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPaniHeader`"
+ errorLine1=" return mConfiguration.getSipPaniHeader();"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="362"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipPlaniHeader`"
+ errorLine1=" return mConfiguration.getSipPlaniHeader();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="367"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getSipUserAgentHeader`"
+ errorLine1=" return mConfiguration.getSipUserAgentHeader();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="372"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getMaxUdpPayloadSizeBytes`"
+ errorLine1=" return mConfiguration.getMaxUdpPayloadSizeBytes() > 0"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="377"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipDelegateConfiguration#getMaxUdpPayloadSizeBytes`"
+ errorLine1=" ? mConfiguration.getMaxUdpPayloadSizeBytes() : 1500;"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="378"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipMessage#getHeaderSection`"
+ errorLine1=" String headers = message.getHeaderSection();"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="387"
+ column="38"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipMessage#getHeaderSection`"
+ errorLine1=' + message.getHeaderSection().substring(0, 10) + "->"'
+ errorLine2=" ~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="392"
+ column="35"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipMessage#getContent`"
+ errorLine1=" return new SipMessage(message.getStartLine(), headers, message.getContent());"
+ errorLine2=" ~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="395"
+ column="76"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.SipMessage#getStartLine`"
+ errorLine1=" return new SipMessage(message.getStartLine(), headers, message.getContent());"
+ errorLine2=" ~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="395"
+ column="43"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `new android.telephony.ims.SipMessage`"
+ errorLine1=" return new SipMessage(message.getStartLine(), headers, message.getContent());"
+ errorLine2=" ~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/registration/RegistrationControllerImpl.java"
+ line="395"
+ column="20"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `new android.telephony.ims.RcsClientConfiguration`"
+ errorLine1=" return new RcsClientConfiguration("
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
+ line="74"
+ column="16"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#setRcsClientConfiguration`"
+ errorLine1=" provisioningManager.setRcsClientConfiguration(clientConfiguration);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
+ line="111"
+ column="29"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Cast to `RcsProvisioningCallback` requires API level 31 (current min is 30)"
+ errorLine1=" new RcsProvisioningCallback() {"
+ errorLine2=" ^">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
+ line="114"
+ column="17"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Class requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager.RcsProvisioningCallback`"
+ errorLine1=" new RcsProvisioningCallback() {"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
line="114"
column="21"/>
</issue>
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#registerRcsProvisioningCallback`"
+ errorLine1=" provisioningManager.registerRcsProvisioningCallback(executorService, callback);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
+ line="147"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#unregisterRcsProvisioningCallback`"
+ errorLine1=" provisioningManager.unregisterRcsProvisioningCallback(callback);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
+ line="158"
+ column="33"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#isRcsVolteSingleRegistrationCapable`"
+ errorLine1=" return provisioningManager.isRcsVolteSingleRegistrationCapable();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
+ line="166"
+ column="36"/>
+ </issue>
+
+ <issue
+ id="NewApi"
+ message="Call requires API level 31 (current min is 30): `android.telephony.ims.ProvisioningManager#triggerRcsReconfiguration`"
+ errorLine1=" provisioningManager.triggerRcsReconfiguration();"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~">
+ <location
+ file="packages/services/Telephony/testapps/TestRcsApp/aosp_test_rcsclient/src/com/android/libraries/rcs/simpleclient/provisioning/StaticConfigProvisioningController.java"
+ line="176"
+ column="29"/>
+ </issue>
+
</issues>
\ No newline at end of file
diff --git a/testapps/TestSatelliteApp/AndroidManifest.xml b/testapps/TestSatelliteApp/AndroidManifest.xml
index fb30bf3..eaddf95 100644
--- a/testapps/TestSatelliteApp/AndroidManifest.xml
+++ b/testapps/TestSatelliteApp/AndroidManifest.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2023 The Android Open Source Project
+ ~ Copyright (C) 2024 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.
@@ -46,6 +46,7 @@
<activity android:name=".Provisioning" />
<activity android:name=".MultipleSendReceive" />
<activity android:name=".SendReceive" />
+ <activity android:name=".NbIotSatellite" />
<activity android:name=".TestSatelliteWrapper" />
</application>
</manifest>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_NbIotSatellite.xml b/testapps/TestSatelliteApp/res/layout/activity_NbIotSatellite.xml
new file mode 100644
index 0000000..c33522e
--- /dev/null
+++ b/testapps/TestSatelliteApp/res/layout/activity_NbIotSatellite.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="0"
+ android:textColor="@android:color/holo_blue_dark"
+ android:textSize="20sp"
+ android:text="@string/NbIotSatellite"/>
+ <Button
+ android:id="@+id/testRegisterForSupportedStateChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/testRegisterForSupportedStateChanged"/>
+ <Button
+ android:id="@+id/testUnregisterForSupportedStateChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/testUnregisterForSupportedStateChanged"/>
+ <Button
+ android:id="@+id/testRequestIsSupported"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/testRequestIsSupported"/>
+ <Button
+ android:id="@+id/reportSatelliteSupportedFromModem"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/reportSatelliteSupportedFromModem"/>
+ <Button
+ android:id="@+id/reportSatelliteNotSupportedFromModem"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/reportSatelliteNotSupportedFromModem"/>
+ <Button
+ android:id="@+id/showCurrentSatelliteSupportedStated"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/showCurrentSatelliteSupportedStated"/>
+ <Button
+ android:id="@+id/Back"
+ android:onClick="Back"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="100dp"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/Back"/>
+ <TextView
+ android:id="@+id/text_id"
+ android:layout_width="300dp"
+ android:layout_height="200dp"
+ android:textColor="@android:color/holo_blue_light"
+ android:textSize="15sp" />
+</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml b/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml
index 40e3c69..6aec1da 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_SatelliteControl.xml
@@ -15,7 +15,7 @@
~ limitations under the License
-->
-<LinearLayout
+<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -84,6 +84,48 @@
android:paddingRight="4dp"
android:text="@string/requestTimeForNextSatelliteVisibility"/>
<Button
+ android:id="@+id/removeUserRestrictReason"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/removeUserRestrictReason"/>
+ <Button
+ android:id="@+id/addUserRestrictReason"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/addUserRestrictReason"/>
+ <Button
+ android:id="@+id/getSatellitePlmn"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/getSatellitePlmn"/>
+ <Button
+ android:id="@+id/getAllSatellitePlmn"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/getAllSatellitePlmn"/>
+ <Button
+ android:id="@+id/isSatelliteEnabledForCarrier"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/isSatelliteEnabledForCarrier"/>
+ <Button
+ android:id="@+id/isRequestIsSatelliteEnabledForCarrier"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/isRequestIsSatelliteEnabledForCarrier"/>
+ <Button
+ android:id="@+id/getIsEmergency"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/getIsEmergency"/>
+ <Button
android:id="@+id/Back"
android:onClick="Back"
android:textColor="@android:color/holo_blue_dark"
@@ -102,4 +144,4 @@
android:layout_centerVertical="true"
android:textSize="15dp" />
</LinearLayout>
-</LinearLayout>
+</ScrollView>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml b/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml
index 0753b82..5ba7946 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_SatelliteTestApp.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2023 The Android Open Source Project
+ ~ Copyright (C) 2024 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.
@@ -65,9 +65,17 @@
android:paddingRight="4dp"
android:text="@string/SendReceive"/>
<Button
+ android:id="@+id/NbIotSatellite"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:text="@string/NbIotSatellite"/>
+ <Button
android:id="@+id/TestSatelliteWrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:paddingStart="4dp"
android:paddingEnd="4dp"
android:text="@string/TestSatelliteWrapper"/>
</LinearLayout>
diff --git a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
index c136ce7..7f2f026 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
@@ -14,91 +14,157 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-
-<LinearLayout
+<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="center"
- android:paddingStart="4dp">
+ android:layout_height="match_parent">
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="0dp"
- android:layout_weight="0"
- android:textColor="@android:color/holo_blue_dark"
- android:textSize="20dp"
- android:text="Satellite Wrapper Test"/>
- <Button
- android:id="@+id/requestNtnSignalStrength"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="4dp"
- android:text="@string/requestNtnSignalStrength"/>
- <Button
- android:id="@+id/registerForNtnSignalStrengthChanged"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="4dp"
- android:text="@string/registerForNtnSignalStrengthChanged"/>
- <Button
- android:id="@+id/unregisterForNtnSignalStrengthChanged"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="4dp"
- android:text="@string/unregisterForNtnSignalStrengthChanged"/>
- <Button
- android:id="@+id/isOnlyNonTerrestrialNetworkSubscription"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="4dp"
- android:text="@string/isOnlyNonTerrestrialNetworkSubscription"/>
- <Button
- android:id="@+id/registerForSatelliteCapabilitiesChanged"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="4dp"
- android:text="@string/registerForSatelliteCapabilitiesChanged"/>
- <Button
- android:id="@+id/unregisterForSatelliteCapabilitiesChanged"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingRight="4dp"
- android:text="@string/unregisterForSatelliteCapabilitiesChanged"/>
<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="horizontal">
- <Button
- android:id="@+id/Back"
- android:onClick="Back"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:paddingStart="4dp">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="0"
android:textColor="@android:color/holo_blue_dark"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="10dp"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:paddingRight="4dp"
- android:text="@string/Back"/>
+ android:textSize="20dp"
+ android:text="Satellite Wrapper Test"/>
<Button
- android:id="@+id/ClearLog"
- android:onClick="ClearLog"
- android:textColor="@android:color/holo_blue_dark"
- android:layout_marginTop="10dp"
- android:layout_marginBottom="10dp"
- android:layout_width="0dp"
+ android:id="@+id/requestNtnSignalStrength"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_weight="1"
android:paddingRight="4dp"
- android:text="@string/ClearLog"/>
+ android:text="@string/requestNtnSignalStrength"/>
+ <Button
+ android:id="@+id/registerForNtnSignalStrengthChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/registerForNtnSignalStrengthChanged"/>
+ <Button
+ android:id="@+id/unregisterForNtnSignalStrengthChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/unregisterForNtnSignalStrengthChanged"/>
+ <Button
+ android:id="@+id/isOnlyNonTerrestrialNetworkSubscription"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/isOnlyNonTerrestrialNetworkSubscription"/>
+ <Button
+ android:id="@+id/registerForSatelliteCapabilitiesChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/registerForSatelliteCapabilitiesChanged"/>
+ <Button
+ android:id="@+id/unregisterForSatelliteCapabilitiesChanged"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/unregisterForSatelliteCapabilitiesChanged"/>
+ <Button
+ android:id="@+id/isNonTerrestrialNetwork"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/isNonTerrestrialNetwork"/>
+ <Button
+ android:id="@+id/getAvailableServices"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/getAvailableServices"/>
+ <Button
+ android:id="@+id/isUsingNonTerrestrialNetwork"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/isUsingNonTerrestrialNetwork"/>
+ <Button
+ android:id="@+id/requestAttachEnabledForCarrier_enable"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestAttachEnabledForCarrier_enable"/>
+ <Button
+ android:id="@+id/requestAttachEnabledForCarrier_disable"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestAttachEnabledForCarrier_disable"/>
+ <Button
+ android:id="@+id/requestIsAttachEnabledForCarrier"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/requestIsAttachEnabledForCarrier"/>
+ <Button
+ android:id="@+id/addAttachRestrictionForCarrier"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/addAttachRestrictionForCarrier"/>
+ <Button
+ android:id="@+id/removeAttachRestrictionForCarrier"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/removeAttachRestrictionForCarrier"/>
+ <Button
+ android:id="@+id/getAttachRestrictionReasonsForCarrier"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/getAttachRestrictionReasonsForCarrier"/>
+ <Button
+ android:id="@+id/getSatellitePlmnsForCarrier"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/getSatellitePlmnsForCarrier"/>
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal">
+ <Button
+ android:id="@+id/Back"
+ android:onClick="Back"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="10dp"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingRight="4dp"
+ android:text="@string/Back"/>
+ <Button
+ android:id="@+id/ClearLog"
+ android:onClick="ClearLog"
+ android:textColor="@android:color/holo_blue_dark"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="10dp"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:paddingRight="4dp"
+ android:text="@string/ClearLog"/>
+ </LinearLayout>
+ <ListView
+ android:id="@+id/logListView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:capitalize="characters"
+ android:textColor="@android:color/holo_blue_light"
+ android:layout_centerVertical="true"
+ android:textSize="8dp" />
</LinearLayout>
- <ListView
- android:id="@+id/logListView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:capitalize="characters"
- android:textColor="@android:color/holo_blue_light"
- android:layout_centerVertical="true"
- android:textSize="8dp" />
-</LinearLayout>
+
+</ScrollView>
\ No newline at end of file
diff --git a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
index 8ebe5f3..df2aaf7 100644
--- a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
+++ b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- ~ Copyright (C) 2023 The Android Open Source Project
+ ~ Copyright (C) 2024 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.
@@ -21,6 +21,7 @@
<string name="Provisioning">Provisioning APIs</string>
<string name="MultipleSendReceive">Test multiple poll and send</string>
<string name="SendReceive">Send and Receive datagrams</string>
+ <string name="NbIotSatellite">NB IoT Satellite modem interface test</string>
<string name="enableSatellite">enableSatellite</string>
<string name="disableSatellite">disableSatellite</string>
@@ -30,6 +31,7 @@
<string name="requestSatelliteCapabilities">requestSatelliteCapabilities</string>
<string name="requestIsSatelliteCommunicationAllowedForCurrentLocation">requestIsSatelliteCommunicationAllowedForCurrentLocation</string>
<string name="requestTimeForNextSatelliteVisibility">requestTimeForNextSatelliteVisibility</string>
+ <string name="getIsEmergency">getIsEmergency</string>
<string name="pollPendingSatelliteDatagrams">pollPendingSatelliteDatagrams</string>
<string name="sendSatelliteDatagram">sendSatelliteDatagram</string>
@@ -64,6 +66,30 @@
<string name="isOnlyNonTerrestrialNetworkSubscription">isOnlyNonTerrestrialNetworkSubscription</string>
<string name="registerForSatelliteCapabilitiesChanged">registerForSatelliteCapabilitiesChanged</string>
<string name="unregisterForSatelliteCapabilitiesChanged">unregisterForSatelliteCapabilitiesChanged</string>
+ <string name="isNonTerrestrialNetwork">isNonTerrestrialNetwork</string>
+ <string name="getAvailableServices">getAvailableServices</string>
+ <string name="isUsingNonTerrestrialNetwork">isUsingNonTerrestrialNetwork</string>
+ <string name="requestAttachEnabledForCarrier_enable">requestAttachEnabledForCarrier_enable</string>
+ <string name="requestAttachEnabledForCarrier_disable">requestAttachEnabledForCarrier_disable</string>
+ <string name="requestIsAttachEnabledForCarrier">requestIsAttachEnabledForCarrier</string>
+ <string name="addAttachRestrictionForCarrier">addAttachRestrictionForCarrier</string>
+ <string name="removeAttachRestrictionForCarrier">removeAttachRestrictionForCarrier</string>
+ <string name="getAttachRestrictionReasonsForCarrier">getAttachRestrictionReasonsForCarrier</string>
+ <string name="getSatellitePlmnsForCarrier">getSatellitePlmnsForCarrier</string>
+
+ <string name="removeUserRestrictReason">removeUserRestrictReason</string>
+ <string name="addUserRestrictReason">addUserRestrictReason</string>
+ <string name="getSatellitePlmn">getSatellitePlmn</string>
+ <string name="getAllSatellitePlmn">getAllSatellitePlmn</string>
+ <string name="isSatelliteEnabledForCarrier">isSatelliteEnabledForCarrier</string>
+ <string name="isRequestIsSatelliteEnabledForCarrier">isRequestIsSatelliteEnabledForCarrier</string>
+
+ <string name="testRegisterForSupportedStateChanged">testRegisterForSupportedStateChanged</string>
+ <string name="testUnregisterForSupportedStateChanged">testUnregisterForSupportedStateChanged</string>
+ <string name="testRequestIsSupported">testRequestIsSupported</string>
+ <string name="reportSatelliteSupportedFromModem">reportSatelliteSupportedFromModem</string>
+ <string name="reportSatelliteNotSupportedFromModem">reportSatelliteNotSupportedFromModem</string>
+ <string name="showCurrentSatelliteSupportedStated">showCurrentSatelliteSupportedStated</string>
<string name="Back">Back</string>
<string name="ClearLog">Clear Log</string>
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
index 97f676f..6c0b227 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
@@ -29,11 +29,12 @@
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
+import android.telephony.satellite.EnableRequestAttributes;
import android.telephony.satellite.PointingInfo;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteDatagramCallback;
import android.telephony.satellite.SatelliteManager;
-import android.telephony.satellite.SatelliteStateCallback;
+import android.telephony.satellite.SatelliteModemStateCallback;
import android.telephony.satellite.SatelliteTransmissionUpdateCallback;
import android.telephony.satellite.stub.SatelliteResult;
import android.util.Log;
@@ -61,7 +62,7 @@
private SatelliteManager mSatelliteManager;
private SatelliteDatagramCallbackTestApp mDatagramCallback;
- private SatelliteStateCallbackTestApp mStateCallback;
+ private SatelliteModemStateCallbackTestApp mStateCallback;
private SatelliteTransmissionUpdateCallbackTestApp mCallback;
private android.telephony.satellite.stub.SatelliteDatagram mReceivedDatagram;
@@ -75,32 +76,32 @@
super.onCreate(savedInstanceState);
mSatelliteManager = getSystemService(SatelliteManager.class);
mDatagramCallback = new SatelliteDatagramCallbackTestApp();
- mStateCallback = new SatelliteStateCallbackTestApp();
+ mStateCallback = new SatelliteModemStateCallbackTestApp();
mCallback = new SatelliteTransmissionUpdateCallbackTestApp();
mReceivedDatagram = new android.telephony.satellite.stub.SatelliteDatagram();
setContentView(R.layout.activity_Datagram);
findViewById(R.id.startSatelliteTransmissionUpdates)
- .setOnClickListener(this::startSatelliteTransmissionUpdatesApp);
+ .setOnClickListener(this::startTransmissionUpdatesApp);
findViewById(R.id.stopSatelliteTransmissionUpdates)
- .setOnClickListener(this::stopSatelliteTransmissionUpdatesApp);
+ .setOnClickListener(this::stopTransmissionUpdatesApp);
findViewById(R.id.pollPendingSatelliteDatagrams)
- .setOnClickListener(this::pollPendingSatelliteDatagramsApp);
+ .setOnClickListener(this::pollPendingDatagramsApp);
findViewById(R.id.sendSatelliteDatagram)
- .setOnClickListener(this::sendSatelliteDatagramApp);
+ .setOnClickListener(this::sendDatagramApp);
findViewById(R.id.registerForSatelliteDatagram)
- .setOnClickListener(this::registerForSatelliteDatagramApp);
+ .setOnClickListener(this::registerForIncomingDatagramApp);
findViewById(R.id.unregisterForSatelliteDatagram)
- .setOnClickListener(this::unregisterForSatelliteDatagramApp);
+ .setOnClickListener(this::unregisterForIncomingDatagramApp);
findViewById(R.id.showDatagramSendStateTransition)
.setOnClickListener(this::showDatagramSendStateTransitionApp);
findViewById(R.id.showDatagramReceiveStateTransition)
.setOnClickListener(this::showDatagramReceiveStateTransitionApp);
findViewById(R.id.registerForSatelliteModemStateChanged)
- .setOnClickListener(this::registerForSatelliteModemStateChangedApp);
+ .setOnClickListener(this::registerForModemStateChangedApp);
findViewById(R.id.unregisterForSatelliteModemStateChanged)
- .setOnClickListener(this::unregisterForSatelliteModemStateChangedApp);
+ .setOnClickListener(this::unregisterForModemStateChangedApp);
findViewById(R.id.showSatelliteModemStateTransition)
.setOnClickListener(this::showSatelliteModemStateTransitionApp);
@@ -121,7 +122,7 @@
}
}
- protected class SatelliteStateCallbackTestApp implements SatelliteStateCallback {
+ protected class SatelliteModemStateCallbackTestApp implements SatelliteModemStateCallback {
@Override
public void onSatelliteModemStateChanged(int state) {
mModemState = state;
@@ -153,6 +154,14 @@
}
@Override
+ public void onSendDatagramStateChanged(
+ int datagramType, int state, int sendPendingCount, int errorCode) {
+ Log.d(TAG, "onSendDatagramStateChanged in TestApp: datagramType = " + datagramType
+ + ", state =" + mTransferState + ", sendPendingCount =" + sendPendingCount
+ + ", errorCode=" + errorCode);
+ }
+
+ @Override
public void onReceiveDatagramStateChanged(
int state, int receivePendingCount, int errorCode) {
mTransferState = state;
@@ -166,10 +175,12 @@
}
}
- private void startSatelliteTransmissionUpdatesApp(View view) {
+ private void startTransmissionUpdatesApp(View view) {
TextView textView = findViewById(R.id.text_id);
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, error::offer);
+ mSatelliteManager.requestEnabled(
+ new EnableRequestAttributes.Builder(true).setDemoMode(true).build(),
+ Runnable::run, error::offer);
TextView showErrorStatusTextView = findViewById(R.id.showErrorStatus);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -186,7 +197,7 @@
return;
}
error.clear();
- mSatelliteManager.startSatelliteTransmissionUpdates(Runnable::run, error::offer, mCallback);
+ mSatelliteManager.startTransmissionUpdates(Runnable::run, error::offer, mCallback);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -202,10 +213,10 @@
}
}
- private void stopSatelliteTransmissionUpdatesApp(View view) {
+ private void stopTransmissionUpdatesApp(View view) {
TextView textView = findViewById(R.id.text_id);
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
- mSatelliteManager.stopSatelliteTransmissionUpdates(mCallback, Runnable::run, error::offer);
+ mSatelliteManager.stopTransmissionUpdates(mCallback, Runnable::run, error::offer);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -220,7 +231,7 @@
textView.setText("stopSatelliteTransmissionUpdates exception caught =" + e);
}
}
- private void pollPendingSatelliteDatagramsApp(View view) {
+ private void pollPendingDatagramsApp(View view) {
LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
TextView showErrorStatusTextView = findViewById(R.id.showErrorStatus);
TextView textView = findViewById(R.id.text_id);
@@ -228,7 +239,9 @@
if (SatelliteTestApp.getTestSatelliteService() != null) {
SatelliteTestApp.getTestSatelliteService().sendOnPendingDatagrams();
}
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.requestEnabled(
+ new EnableRequestAttributes.Builder(true).setDemoMode(true).build(),
+ Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -246,61 +259,61 @@
showErrorStatusTextView.setText("Enable SatelliteService exception caught = " + e);
return;
}
- mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.pollPendingDatagrams(Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
textView.setText("Timed out for poll message");
} else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
- textView.setText("Failed to pollPendingSatelliteDatagrams with error = "
+ textView.setText("Failed to pollPendingDatagrams with error = "
+ SatelliteErrorUtils.mapError(value));
} else {
- textView.setText("pollPendingSatelliteDatagrams is successful");
+ textView.setText("pollPendingDatagrams is successful");
}
} catch (InterruptedException e) {
- textView.setText("pollPendingSatelliteDatagrams exception caught =" + e);
+ textView.setText("pollPendingDatagrams exception caught =" + e);
}
}
- private void sendSatelliteDatagramApp(View view) {
+ private void sendDatagramApp(View view) {
TextView textView = findViewById(R.id.text_id);
mSatelliteManager.setDeviceAlignedWithSatellite(true);
LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
String mText = "This is a test datagram message";
SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes());
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
- textView.setText("Timed out for sendSatelliteDatagram");
+ textView.setText("Timed out for sendDatagram");
} else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
- textView.setText("Failed to sendSatelliteDatagram with error = "
+ textView.setText("Failed to sendDatagram with error = "
+ SatelliteErrorUtils.mapError(value));
} else {
- textView.setText("sendSatelliteDatagram is successful");
+ textView.setText("sendDatagram is successful");
}
} catch (InterruptedException e) {
- textView.setText("sendSatelliteDatagram exception caught =" + e);
+ textView.setText("sendDatagram exception caught =" + e);
}
}
- private void registerForSatelliteDatagramApp(View view) {
- int result = mSatelliteManager.registerForSatelliteDatagram(Runnable::run,
+ private void registerForIncomingDatagramApp(View view) {
+ int result = mSatelliteManager.registerForIncomingDatagram(Runnable::run,
mDatagramCallback);
TextView textView = findViewById(R.id.text_id);
if (result == 0) {
- textView.setText("registerForSatelliteDatagram is successful");
+ textView.setText("registerForIncomingDatagram is successful");
} else {
- textView.setText("Status for registerForSatelliteDatagram : "
+ textView.setText("Status for registerForIncomingDatagram : "
+ SatelliteErrorUtils.mapError(result));
}
}
- private void unregisterForSatelliteDatagramApp(View view) {
- mSatelliteManager.unregisterForSatelliteDatagram(mDatagramCallback);
+ private void unregisterForIncomingDatagramApp(View view) {
+ mSatelliteManager.unregisterForIncomingDatagram(mDatagramCallback);
TextView textView = findViewById(R.id.text_id);
- textView.setText("unregisterForSatelliteDatagram is successful");
+ textView.setText("unregisterForIncomingDatagram is successful");
}
private void showDatagramSendStateTransitionApp(View view) {
@@ -315,22 +328,22 @@
+ mShowDatagramReceiveStateTransition);
}
- private void registerForSatelliteModemStateChangedApp(View view) {
- int result = mSatelliteManager.registerForSatelliteModemStateChanged(Runnable::run,
+ private void registerForModemStateChangedApp(View view) {
+ int result = mSatelliteManager.registerForModemStateChanged(Runnable::run,
mStateCallback);
TextView textView = findViewById(R.id.text_id);
if (result == 0) {
- textView.setText("registerForSatelliteModemStateChanged is successful");
+ textView.setText("registerForModemStateChanged is successful");
} else {
- textView.setText("Status for registerForSatelliteModemStateChanged : "
+ textView.setText("Status for registerForModemStateChanged : "
+ SatelliteErrorUtils.mapError(result));
}
}
- private void unregisterForSatelliteModemStateChangedApp(View view) {
- mSatelliteManager.unregisterForSatelliteModemStateChanged(mStateCallback);
+ private void unregisterForModemStateChangedApp(View view) {
+ mSatelliteManager.unregisterForModemStateChanged(mStateCallback);
TextView textView = findViewById(R.id.text_id);
- textView.setText("unregisterForSatelliteModemStateChanged is successful");
+ textView.setText("unregisterForModemStateChanged is successful");
}
private void showSatelliteModemStateTransitionApp(View view) {
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/ILocalSatelliteListener.aidl b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/ILocalSatelliteListener.aidl
index 2c320c8..0a32432 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/ILocalSatelliteListener.aidl
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/ILocalSatelliteListener.aidl
@@ -64,4 +64,10 @@
* enableCellularModemWhileSatelliteModeIsOn from Telephony.
*/
void onEnableCellularModemWhileSatelliteModeIsOn(in boolean enable);
+
+ /**
+ * Indicates that MockSatelliteService has just received the request
+ * setSatellitePlmn from Telephony.
+ */
+ void onSetSatellitePlmn();
}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java
index 3c0b2fd..723f690 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
+import android.telephony.satellite.EnableRequestAttributes;
import android.telephony.satellite.SatelliteDatagram;
import android.telephony.satellite.SatelliteManager;
import android.util.Log;
@@ -66,20 +67,22 @@
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 4);
LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
- mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.requestEnabled(
+ new EnableRequestAttributes.Builder(true).setDemoMode(true).build(),
+ Runnable::run, resultListener::offer);
+ mSatelliteManager.pollPendingDatagrams(Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 3);
- mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.pollPendingDatagrams(Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 2);
- mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.pollPendingDatagrams(Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 1);
- mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.pollPendingDatagrams(Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 0);
- mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.pollPendingDatagrams(Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(1000, TimeUnit.MILLISECONDS);
TextView textView = findViewById(R.id.text_id);
@@ -100,15 +103,15 @@
LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
String mText = "This is a test datagram message";
SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes());
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(1000, TimeUnit.MILLISECONDS);
@@ -127,27 +130,29 @@
private void multipleSendReceiveSatelliteDatagramApp(View view) {
mSatelliteManager.setDeviceAlignedWithSatellite(true);
LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.requestEnabled(
+ new EnableRequestAttributes.Builder(true).setDemoMode(true).build(),
+ Runnable::run, resultListener::offer);
String mText = "This is a test datagram message";
SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes());
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 4);
- mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.pollPendingDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 3);
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 2);
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 1);
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, resultListener::offer);
SatelliteTestApp.getTestSatelliteService().sendOnSatelliteDatagramReceived(
mReceivedDatagram, 0);
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/NbIotSatellite.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/NbIotSatellite.java
new file mode 100644
index 0000000..17646f0
--- /dev/null
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/NbIotSatellite.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.phone.testapps.satellitetestapp;
+
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.os.OutcomeReceiver;
+import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteSupportedStateCallback;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Activity related to NB IoT satellite APIs.
+ */
+public class NbIotSatellite extends Activity {
+
+ private static final String TAG = "NbIotSatellite";
+ private static final String MY_SHARED_PREF = "MySharedPref";
+ private static final String SHARED_PREF_KEY = "supported_stated";
+ TextView mTextView;
+ private boolean mSatelliteSupported = false;
+ public static TestSatelliteService sSatelliteService;
+ private SatelliteManager mSatelliteManager;
+ private TestSatelliteSupportedStateCallback mSatelliteSupportedStateCallback;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ sSatelliteService = SatelliteTestApp.getTestSatelliteService();
+ mSatelliteManager = getSystemService(SatelliteManager.class);
+
+ setContentView(R.layout.activity_NbIotSatellite);
+ findViewById(R.id.testRegisterForSupportedStateChanged)
+ .setOnClickListener(this::testRegisterForSupportedStateChanged);
+ findViewById(R.id.testUnregisterForSupportedStateChanged)
+ .setOnClickListener(this::testUnregisterForSupportedStateChanged);
+ findViewById(R.id.testRequestIsSupported)
+ .setOnClickListener(this::testRequestIsSupported);
+ findViewById(R.id.reportSatelliteSupportedFromModem)
+ .setOnClickListener(this::reportSatelliteSupportedFromModem);
+ findViewById(R.id.reportSatelliteNotSupportedFromModem)
+ .setOnClickListener(this::reportSatelliteNotSupportedFromModem);
+ findViewById(R.id.showCurrentSatelliteSupportedStated)
+ .setOnClickListener(this::showCurrentSatelliteSupportedStated);
+ findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ startActivity(new Intent(NbIotSatellite.this, SatelliteTestApp.class));
+ }
+ });
+
+ mTextView = findViewById(R.id.text_id);
+ }
+
+ protected class TestSatelliteSupportedStateCallback implements SatelliteSupportedStateCallback {
+ @Override
+ public void onSatelliteSupportedStateChanged(boolean supported) {
+ mSatelliteSupported = supported;
+ updateLogMessage("onSatelliteSupportedStateChanged: "
+ + (mSatelliteSupported ? "Satellite is supported"
+ : "Satellite is not supported"));
+ Log.d(TAG, "onSatelliteSupportedStateChanged(): supported="
+ + mSatelliteSupported);
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ private void testRegisterForSupportedStateChanged(View view) {
+ if (mSatelliteSupportedStateCallback == null) {
+ mSatelliteSupportedStateCallback = new TestSatelliteSupportedStateCallback();
+ }
+ int result = mSatelliteManager.registerForSupportedStateChanged(Runnable::run,
+ mSatelliteSupportedStateCallback);
+
+ if (result == SATELLITE_RESULT_SUCCESS) {
+ updateLogMessage("testRegisterForSupportedStateChanged(): "
+ + "registered mSatelliteSupportedStateCallback");
+ } else {
+ updateLogMessage("Failed to registerForSupportedStateChanged(), reason=" + result);
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ private void testUnregisterForSupportedStateChanged(View view) {
+ if (mSatelliteSupportedStateCallback != null) {
+ mSatelliteManager.unregisterForSupportedStateChanged(mSatelliteSupportedStateCallback);
+ mSatelliteSupportedStateCallback = null;
+ updateLogMessage("testUnregisterForSupportedStateChanged(): unregister callback.");
+ } else {
+ updateLogMessage("testUnregisterForSupportedStateChanged(): ignored, "
+ + "mSatelliteSupportedStateCallback is already null");
+ }
+ }
+
+ private void testRequestIsSupported(View view) {
+ final AtomicReference<Boolean> enabled = new AtomicReference<>();
+ final AtomicReference<Integer> errorCode = new AtomicReference<>();
+ OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> mReceiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ enabled.set(result);
+ updateLogMessage("Status for requestIsSupported result: "
+ + enabled.get());
+ }
+
+ @Override
+ public void onError(SatelliteManager.SatelliteException exception) {
+ errorCode.set(exception.getErrorCode());
+ updateLogMessage("Status for requestIsSupported error : "
+ + SatelliteErrorUtils.mapError(errorCode.get()));
+ }
+ };
+ mSatelliteManager.requestIsSupported(Runnable::run, mReceiver);
+ }
+
+ private void showCurrentSatelliteSupportedStated(View view) {
+ boolean mModemSupportedState = sSatelliteService.getSatelliteSupportedState();
+ updateLogMessage("reported supported state is " + mSatelliteSupported
+ + ", modem supported state is " + mModemSupportedState);
+ }
+
+ private void reportSatelliteSupportedFromModem(View view) {
+ sSatelliteService.updateSatelliteSupportedState(true);
+ }
+
+ private void reportSatelliteNotSupportedFromModem(View view) {
+ sSatelliteService.updateSatelliteSupportedState(false);
+ }
+
+ // Fetch the stored data in onResume()
+ // Because this is what will be called when the app opens again
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // Fetching the stored data from the SharedPreference
+ SharedPreferences sh = getSharedPreferences("MySharedPref", MODE_PRIVATE);
+ boolean isProvisioned = sh.getBoolean("provision_state", mSatelliteSupported);
+
+ // Setting the fetched data
+ mSatelliteSupported = isProvisioned;
+ }
+
+ // Store the data in the SharedPreference in the onPause() method
+ // When the user closes the application onPause() will be called and data will be stored
+ @Override
+ protected void onPause() {
+ super.onPause();
+ // Creating a shared pref object with a file name "MySharedPref" in private mode
+ SharedPreferences sharedPreferences = getSharedPreferences(MY_SHARED_PREF, MODE_PRIVATE);
+ SharedPreferences.Editor myEdit = sharedPreferences.edit();
+
+ // write all the data entered by the user in SharedPreference and apply
+ myEdit.putBoolean(SHARED_PREF_KEY, mSatelliteSupported);
+ myEdit.apply();
+ }
+
+ private void updateLogMessage(String message) {
+ runOnUiThread(() -> mTextView.setText(message));
+ }
+
+ protected void onDestroy() {
+ super.onDestroy();
+ SharedPreferences sharedPreferences = getSharedPreferences(MY_SHARED_PREF, MODE_PRIVATE);
+
+ final SharedPreferences.Editor sharedPrefsEditor = sharedPreferences.edit();
+ sharedPrefsEditor.remove(SHARED_PREF_KEY);
+ sharedPrefsEditor.apply();
+ }
+}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Provisioning.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Provisioning.java
index 940435e..20c5ef5 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Provisioning.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Provisioning.java
@@ -55,15 +55,15 @@
setContentView(R.layout.activity_Provisioning);
findViewById(R.id.provisionSatelliteService)
- .setOnClickListener(this::provisionSatelliteServiceApp);
+ .setOnClickListener(this::provisionServiceApp);
findViewById(R.id.deprovisionSatelliteService)
- .setOnClickListener(this::deprovisionSatelliteServiceApp);
+ .setOnClickListener(this::deprovisionServiceApp);
findViewById(R.id.requestIsSatelliteProvisioned)
- .setOnClickListener(this::requestIsSatelliteProvisionedApp);
+ .setOnClickListener(this::requestIsProvisionedApp);
findViewById(R.id.registerForSatelliteProvisionStateChanged)
- .setOnClickListener(this::registerForSatelliteProvisionStateChangedApp);
+ .setOnClickListener(this::registerForProvisionStateChangedApp);
findViewById(R.id.unregisterForSatelliteProvisionStateChanged)
- .setOnClickListener(this::unregisterForSatelliteProvisionStateChangedApp);
+ .setOnClickListener(this::unregisterForProvisionStateChangedApp);
findViewById(R.id.showCurrentSatelliteProvisionState)
.setOnClickListener(this::showCurrentSatelliteProvisionStateApp);
findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
@@ -84,13 +84,13 @@
}
}
- private void provisionSatelliteServiceApp(View view) {
+ private void provisionServiceApp(View view) {
TextView textView = findViewById(R.id.text_id);
CancellationSignal cancellationSignal = new CancellationSignal();
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
String mText = "This is test provision data.";
byte[] testProvisionData = mText.getBytes();
- mSatelliteManager.provisionSatelliteService("SATELLITE_TOKEN", testProvisionData,
+ mSatelliteManager.provisionService("SATELLITE_TOKEN", testProvisionData,
cancellationSignal, Runnable::run, error::offer);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -107,10 +107,10 @@
}
}
- private void deprovisionSatelliteServiceApp(View view) {
+ private void deprovisionServiceApp(View view) {
TextView textView = findViewById(R.id.text_id);
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
- mSatelliteManager.deprovisionSatelliteService("SATELLITE_TOKEN", Runnable::run,
+ mSatelliteManager.deprovisionService("SATELLITE_TOKEN", Runnable::run,
error::offer);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -127,7 +127,7 @@
}
}
- private void requestIsSatelliteProvisionedApp(View view) {
+ private void requestIsProvisionedApp(View view) {
final AtomicReference<Boolean> enabled = new AtomicReference<>();
final AtomicReference<Integer> errorCode = new AtomicReference<>();
OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> mReceiver =
@@ -148,19 +148,19 @@
+ SatelliteErrorUtils.mapError(errorCode.get()));
}
};
- mSatelliteManager.requestIsSatelliteProvisioned(Runnable::run, mReceiver);
+ mSatelliteManager.requestIsProvisioned(Runnable::run, mReceiver);
}
- private void registerForSatelliteProvisionStateChangedApp(View view) {
- int result = mSatelliteManager.registerForSatelliteProvisionStateChanged(Runnable::run,
+ private void registerForProvisionStateChangedApp(View view) {
+ int result = mSatelliteManager.registerForProvisionStateChanged(Runnable::run,
mCallback);
TextView textView = findViewById(R.id.text_id);
textView.setText("Status for registerForSatelliteProvisionStateChanged : "
+ SatelliteErrorUtils.mapError(result));
}
- private void unregisterForSatelliteProvisionStateChangedApp(View view) {
- mSatelliteManager.unregisterForSatelliteProvisionStateChanged(mCallback);
+ private void unregisterForProvisionStateChangedApp(View view) {
+ mSatelliteManager.unregisterForProvisionStateChanged(mCallback);
TextView textView = findViewById(R.id.text_id);
textView.setText("unregisterForSatelliteProvisionStateChanged is successful");
}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
index 4e339a3..a03f04e 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
@@ -20,6 +20,9 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.OutcomeReceiver;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.satellite.EnableRequestAttributes;
import android.telephony.satellite.SatelliteCapabilities;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.stub.SatelliteResult;
@@ -28,6 +31,7 @@
import android.widget.TextView;
import java.time.Duration;
+import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@@ -40,11 +44,13 @@
private static final long TIMEOUT = 3000;
private SatelliteManager mSatelliteManager;
+ private SubscriptionManager mSubscriptionManager;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSatelliteManager = getSystemService(SatelliteManager.class);
+ mSubscriptionManager = getSystemService(SubscriptionManager.class);
setContentView(R.layout.activity_SatelliteControl);
findViewById(R.id.enableSatellite)
@@ -52,18 +58,31 @@
findViewById(R.id.disableSatellite)
.setOnClickListener(this::disableSatelliteApp);
findViewById(R.id.requestIsSatelliteEnabled)
- .setOnClickListener(this::requestIsSatelliteEnabledApp);
+ .setOnClickListener(this::requestIsEnabledApp);
findViewById(R.id.requestIsDemoModeEnabled)
.setOnClickListener(this::requestIsDemoModeEnabledApp);
findViewById(R.id.requestIsSatelliteSupported)
- .setOnClickListener(this::requestIsSatelliteSupportedApp);
+ .setOnClickListener(this::requestIsSupportedApp);
findViewById(R.id.requestSatelliteCapabilities)
- .setOnClickListener(this::requestSatelliteCapabilitiesApp);
+ .setOnClickListener(this::requestCapabilitiesApp);
findViewById(R.id.requestIsSatelliteCommunicationAllowedForCurrentLocation)
- .setOnClickListener(
- this::requestIsSatelliteCommunicationAllowedForCurrentLocationApp);
+ .setOnClickListener(this::requestIsCommunicationAllowedForCurrentLocationApp);
findViewById(R.id.requestTimeForNextSatelliteVisibility)
.setOnClickListener(this::requestTimeForNextSatelliteVisibilityApp);
+ findViewById(R.id.removeUserRestrictReason)
+ .setOnClickListener(this::removeUserRestrictReasonApp);
+ findViewById(R.id.addUserRestrictReason)
+ .setOnClickListener(this::addUserRestrictReasonApp);
+ findViewById(R.id.getSatellitePlmn)
+ .setOnClickListener(this::getSatellitePlmnApp);
+ findViewById(R.id.getAllSatellitePlmn)
+ .setOnClickListener(this::getAllSatellitePlmnApp);
+ findViewById(R.id.isSatelliteEnabledForCarrier)
+ .setOnClickListener(this::isSatelliteEnabledForCarrierApp);
+ findViewById(R.id.isRequestIsSatelliteEnabledForCarrier)
+ .setOnClickListener(this::isRequestIsSatelliteEnabledForCarrierApp);
+ findViewById(R.id.getIsEmergency)
+ .setOnClickListener(this::getIsEmergencyApp);
findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
@@ -74,7 +93,9 @@
private void enableSatelliteApp(View view) {
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, error::offer);
+ mSatelliteManager.requestEnabled(
+ new EnableRequestAttributes.Builder(true).setDemoMode(true).setEmergencyMode(true)
+ .build(), Runnable::run, error::offer);
TextView textView = findViewById(R.id.text_id);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -93,7 +114,8 @@
private void disableSatelliteApp(View view) {
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
- mSatelliteManager.requestSatelliteEnabled(false, true, Runnable::run, error::offer);
+ mSatelliteManager.requestEnabled(new EnableRequestAttributes.Builder(false).build(),
+ Runnable::run, error::offer);
TextView textView = findViewById(R.id.text_id);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -110,7 +132,7 @@
}
}
- private void requestIsSatelliteEnabledApp(View view) {
+ private void requestIsEnabledApp(View view) {
final AtomicReference<Boolean> enabled = new AtomicReference<>();
final AtomicReference<Integer> errorCode = new AtomicReference<>();
OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver =
@@ -120,9 +142,9 @@
enabled.set(result);
TextView textView = findViewById(R.id.text_id);
if (enabled.get()) {
- textView.setText("requestIsSatelliteEnabled is true");
+ textView.setText("requestIsEnabled is true");
} else {
- textView.setText("Status for requestIsSatelliteEnabled result : "
+ textView.setText("Status for requestIsEnabled result : "
+ enabled.get());
}
}
@@ -131,11 +153,11 @@
public void onError(SatelliteManager.SatelliteException exception) {
errorCode.set(exception.getErrorCode());
TextView textView = findViewById(R.id.text_id);
- textView.setText("Status for requestIsSatelliteEnabled error : "
+ textView.setText("Status for requestIsEnabled error : "
+ SatelliteErrorUtils.mapError(errorCode.get()));
}
};
- mSatelliteManager.requestIsSatelliteEnabled(Runnable::run, receiver);
+ mSatelliteManager.requestIsEnabled(Runnable::run, receiver);
}
private void requestIsDemoModeEnabledApp(View view) {
@@ -166,7 +188,7 @@
mSatelliteManager.requestIsDemoModeEnabled(Runnable::run, receiver);
}
- private void requestIsSatelliteSupportedApp(View view) {
+ private void requestIsSupportedApp(View view) {
final AtomicReference<Boolean> enabled = new AtomicReference<>();
final AtomicReference<Integer> errorCode = new AtomicReference<>();
OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver =
@@ -176,9 +198,9 @@
enabled.set(result);
TextView textView = findViewById(R.id.text_id);
if (enabled.get()) {
- textView.setText("requestIsSatelliteSupported is true");
+ textView.setText("requestIsSupported is true");
} else {
- textView.setText("Status for requestIsSatelliteSupported result : "
+ textView.setText("Status for requestIsSupported result : "
+ enabled.get());
}
}
@@ -187,14 +209,14 @@
public void onError(SatelliteManager.SatelliteException exception) {
errorCode.set(exception.getErrorCode());
TextView textView = findViewById(R.id.text_id);
- textView.setText("Status for requestIsSatelliteSupported error : "
+ textView.setText("Status for requestIsSupported error : "
+ SatelliteErrorUtils.mapError(errorCode.get()));
}
};
- mSatelliteManager.requestIsSatelliteSupported(Runnable::run, receiver);
+ mSatelliteManager.requestIsSupported(Runnable::run, receiver);
}
- private void requestSatelliteCapabilitiesApp(View view) {
+ private void requestCapabilitiesApp(View view) {
final AtomicReference<SatelliteCapabilities> capabilities = new AtomicReference<>();
final AtomicReference<Integer> errorCode = new AtomicReference<>();
OutcomeReceiver<SatelliteCapabilities, SatelliteManager.SatelliteException> receiver =
@@ -203,7 +225,7 @@
public void onResult(SatelliteCapabilities result) {
capabilities.set(result);
TextView textView = findViewById(R.id.text_id);
- textView.setText("Status for requestSatelliteCapabilities result: "
+ textView.setText("Status for requestCapabilities result: "
+ capabilities.get());
}
@@ -211,17 +233,17 @@
public void onError(SatelliteManager.SatelliteException exception) {
errorCode.set(exception.getErrorCode());
TextView textView = findViewById(R.id.text_id);
- textView.setText("Status for requestSatelliteCapabilities error : "
+ textView.setText("Status for requestCapabilities error : "
+ SatelliteErrorUtils.mapError(errorCode.get()));
}
};
- mSatelliteManager.requestSatelliteCapabilities(Runnable::run, receiver);
+ mSatelliteManager.requestCapabilities(Runnable::run, receiver);
}
- private void requestIsSatelliteCommunicationAllowedForCurrentLocationApp(View view) {
+ private void requestIsCommunicationAllowedForCurrentLocationApp(View view) {
final AtomicReference<Boolean> enabled = new AtomicReference<>();
final AtomicReference<Integer> errorCode = new AtomicReference<>();
- String display = "requestIsSatelliteCommunicationAllowedForCurrentLocation";
+ String display = "requestIsCommunicationAllowedForCurrentLocation";
OutcomeReceiver<Boolean, SatelliteManager.SatelliteException> receiver =
new OutcomeReceiver<>() {
@Override
@@ -244,7 +266,7 @@
+ SatelliteErrorUtils.mapError(errorCode.get()));
}
};
- mSatelliteManager.requestIsSatelliteCommunicationAllowedForCurrentLocation(Runnable::run,
+ mSatelliteManager.requestIsCommunicationAllowedForCurrentLocation(Runnable::run,
receiver);
}
@@ -271,4 +293,94 @@
};
mSatelliteManager.requestTimeForNextSatelliteVisibility(Runnable::run, receiver);
}
+
+ private void removeUserRestrictReasonApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ List<SubscriptionInfo> infoList = mSubscriptionManager.getAvailableSubscriptionInfoList();
+ List<Integer> subIdList = infoList.stream()
+ .map(SubscriptionInfo::getSubscriptionId)
+ .toList();
+ for (int subId : subIdList) {
+ mSatelliteManager.removeAttachRestrictionForCarrier(subId,
+ SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER,
+ Runnable::run, error::offer);
+ }
+
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out to removeAttachRestrictionForCarrier");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to removeAttachRestrictionForCarrier with error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText(subIdList == null || subIdList.isEmpty() ? "no active subId list" :
+ "removeAttachRestrictionForCarrier for all subIdList=" + subIdList);
+ }
+ } catch (InterruptedException e) {
+ textView.setText("removeAttachRestrictionForCarrier exception caught =" + e);
+ }
+ }
+
+ private void addUserRestrictReasonApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
+ List<SubscriptionInfo> infoList = mSubscriptionManager.getAvailableSubscriptionInfoList();
+ List<Integer> subIdList = infoList.stream()
+ .map(SubscriptionInfo::getSubscriptionId)
+ .toList();
+ for (int subId : subIdList) {
+ mSatelliteManager.addAttachRestrictionForCarrier(subId,
+ SatelliteManager.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER,
+ Runnable::run, error::offer);
+ }
+
+ try {
+ Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
+ if (value == null) {
+ textView.setText("Timed out to addAttachRestrictionForCarrier");
+ } else if (value != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ textView.setText("Failed to addAttachRestrictionForCarrier with error = "
+ + SatelliteErrorUtils.mapError(value));
+ } else {
+ textView.setText(subIdList == null || subIdList.isEmpty() ? "no active subId list" :
+ "addAttachRestrictionForCarrier for all subIdList=" + subIdList);
+ }
+ } catch (InterruptedException e) {
+ textView.setText("addAttachRestrictionForCarrier exception caught =" + e);
+ }
+ }
+
+ private void getSatellitePlmnApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("[SatelliteService] getSatellitePlmnApp = "
+ + SatelliteTestApp.getTestSatelliteService().getCarrierPlmnList());
+ }
+
+ private void getAllSatellitePlmnApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("[SatelliteService] getAllSatellitePlmnApp = "
+ + SatelliteTestApp.getTestSatelliteService().getAllSatellitePlmnList());
+ }
+
+ private void isSatelliteEnabledForCarrierApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("[SatelliteService] isSatelliteEnabledForCarrier= "
+ + SatelliteTestApp.getTestSatelliteService().isSatelliteEnabledForCarrier());
+ }
+
+ private void isRequestIsSatelliteEnabledForCarrierApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("[SatelliteService] isRequestIsSatelliteEnabledForCarrier= "
+ + SatelliteTestApp.getTestSatelliteService()
+ .isRequestIsSatelliteEnabledForCarrier());
+ }
+
+ private void getIsEmergencyApp(View view) {
+ TextView textView = findViewById(R.id.text_id);
+ textView.setText("[SatelliteService] getIsEmergencyApp= "
+ + SatelliteTestApp.getTestSatelliteService()
+ .getIsEmergency());
+ }
}
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteErrorUtils.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteErrorUtils.java
index ffdabdf..ef0c85c 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteErrorUtils.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteErrorUtils.java
@@ -16,7 +16,31 @@
package com.android.phone.testapps.satellitetestapp;
-import android.telephony.satellite.stub.SatelliteResult;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ACCESS_BARRED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ERROR;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ILLEGAL_STATE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_BUSY;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NETWORK_ERROR;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NETWORK_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_AUTHORIZED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NO_RESOURCES;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_FAILED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVER_ERROR;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS;
+
import android.util.Log;
/**
@@ -31,44 +55,54 @@
*/
public static String mapError(int error) {
switch (error) {
- case SatelliteResult.SATELLITE_RESULT_SUCCESS:
+ case SATELLITE_RESULT_SUCCESS:
return "SATELLITE_RESULT_SUCCESS";
- case SatelliteResult.SATELLITE_RESULT_ERROR:
+ case SATELLITE_RESULT_ERROR:
return "SATELLITE_RESULT_ERROR";
- case SatelliteResult.SATELLITE_RESULT_SERVER_ERROR:
+ case SATELLITE_RESULT_SERVER_ERROR:
return "SATELLITE_RESULT_SERVER_ERROR";
- case SatelliteResult.SATELLITE_RESULT_SERVICE_ERROR:
+ case SATELLITE_RESULT_SERVICE_ERROR:
return "SATELLITE_RESULT_SERVICE_ERROR";
- case SatelliteResult.SATELLITE_RESULT_MODEM_ERROR:
+ case SATELLITE_RESULT_MODEM_ERROR:
return "SATELLITE_RESULT_MODEM_ERROR";
- case SatelliteResult.SATELLITE_RESULT_NETWORK_ERROR:
+ case SATELLITE_RESULT_NETWORK_ERROR:
return "SATELLITE_RESULT_NETWORK_ERROR";
- case SatelliteResult.SATELLITE_RESULT_INVALID_MODEM_STATE:
+ case SATELLITE_RESULT_INVALID_TELEPHONY_STATE:
+ return "SATELLITE_RESULT_INVALID_TELEPHONY_STATE";
+ case SATELLITE_RESULT_INVALID_MODEM_STATE:
return "SATELLITE_RESULT_INVALID_MODEM_STATE";
- case SatelliteResult.SATELLITE_RESULT_INVALID_ARGUMENTS:
+ case SATELLITE_RESULT_INVALID_ARGUMENTS:
return "SATELLITE_RESULT_INVALID_ARGUMENTS";
- case SatelliteResult.SATELLITE_RESULT_REQUEST_FAILED:
+ case SATELLITE_RESULT_REQUEST_FAILED:
return "SATELLITE_RESULT_REQUEST_FAILED";
- case SatelliteResult.SATELLITE_RESULT_RADIO_NOT_AVAILABLE:
+ case SATELLITE_RESULT_RADIO_NOT_AVAILABLE:
return "SATELLITE_RESULT_RADIO_NOT_AVAILABLE";
- case SatelliteResult.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED:
+ case SATELLITE_RESULT_REQUEST_NOT_SUPPORTED:
return "SATELLITE_RESULT_REQUEST_NOT_SUPPORTED";
- case SatelliteResult.SATELLITE_RESULT_NO_RESOURCES:
+ case SATELLITE_RESULT_NO_RESOURCES:
return "SATELLITE_RESULT_NO_RESOURCES";
- case SatelliteResult.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED:
+ case SATELLITE_RESULT_SERVICE_NOT_PROVISIONED:
return "SATELLITE_RESULT_SERVICE_NOT_PROVISIONED";
- case SatelliteResult.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS:
+ case SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS:
return "SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS";
- case SatelliteResult.SATELLITE_RESULT_REQUEST_ABORTED:
+ case SATELLITE_RESULT_REQUEST_ABORTED:
return "SATELLITE_RESULT_REQUEST_ABORTED";
- case SatelliteResult.SATELLITE_RESULT_ACCESS_BARRED:
+ case SATELLITE_RESULT_ACCESS_BARRED:
return "SATELLITE_RESULT_ACCESS_BARRED";
- case SatelliteResult.SATELLITE_RESULT_NETWORK_TIMEOUT:
+ case SATELLITE_RESULT_NETWORK_TIMEOUT:
return "SATELLITE_RESULT_NETWORK_TIMEOUT";
- case SatelliteResult.SATELLITE_RESULT_NOT_REACHABLE:
+ case SATELLITE_RESULT_NOT_REACHABLE:
return "SATELLITE_RESULT_NOT_REACHABLE";
- case SatelliteResult.SATELLITE_RESULT_NOT_AUTHORIZED:
+ case SATELLITE_RESULT_NOT_AUTHORIZED:
return "SATELLITE_RESULT_NOT_AUTHORIZED";
+ case SATELLITE_RESULT_NOT_SUPPORTED:
+ return "SATELLITE_RESULT_NOT_SUPPORTED";
+ case SATELLITE_RESULT_REQUEST_IN_PROGRESS:
+ return "SATELLITE_RESULT_REQUEST_IN_PROGRESS";
+ case SATELLITE_RESULT_MODEM_BUSY:
+ return "SATELLITE_RESULT_MODEM_BUSY";
+ case SATELLITE_RESULT_ILLEGAL_STATE:
+ return "SATELLITE_RESULT_ILLEGAL_STATE";
}
Log.d(TAG, "Received invalid satellite service error: " + error);
return "SATELLITE_RESULT_SERVICE_ERROR";
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
index ced9a06..7c4ae00 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -89,6 +89,13 @@
startActivity(intent);
}
});
+ findViewById(R.id.NbIotSatellite).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent intent = new Intent(SatelliteTestApp.this, NbIotSatellite.class);
+ startActivity(intent);
+ }
+ });
findViewById(R.id.TestSatelliteWrapper).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
@@ -138,6 +145,11 @@
public void onEnableCellularModemWhileSatelliteModeIsOn(boolean enable) {
Log.d(TAG, "onEnableCellularModemWhileSatelliteModeIsOn");
}
+
+ @Override
+ public void onSetSatellitePlmn() {
+ Log.d(TAG, "onSetSatellitePlmn");
+ }
};
private class TestSatelliteServiceConnection implements ServiceConnection {
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java
index a64aa5d..ede2377 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java
@@ -21,6 +21,7 @@
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.OutcomeReceiver;
+import android.telephony.satellite.EnableRequestAttributes;
import android.telephony.satellite.PointingInfo;
import android.telephony.satellite.SatelliteCapabilities;
import android.telephony.satellite.SatelliteDatagram;
@@ -107,6 +108,14 @@
}
@Override
+ public void onSendDatagramStateChanged(
+ int datagramType, int state, int sendPendingCount, int errorCode) {
+ Log.d(TAG, "onSendDatagramStateChanged in TestApp for sendReceive: state = "
+ + state + ", sendPendingCount =" + sendPendingCount + ", errorCode="
+ + errorCode + ", datagramType = " + datagramType);
+ }
+
+ @Override
public void onReceiveDatagramStateChanged(
int state, int receivePendingCount, int errorCode) {
Log.d(TAG, "onReceiveDatagramStateChanged in TestApp for sendReceive: state = "
@@ -124,7 +133,7 @@
SatelliteDatagram datagram = new SatelliteDatagram(mMessageInput.getBytes());
//Sending Message
- mSatelliteManager.sendSatelliteDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ mSatelliteManager.sendDatagram(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
datagram, true, Runnable::run, error::offer);
TextView messageStatusTextView = findViewById(R.id.messageStatus);
try {
@@ -139,7 +148,7 @@
+ mEnterMessage.getText().toString());
}
} catch (InterruptedException e) {
- messageStatusTextView.setText("sendSatelliteDatagram exception caught = " + e);
+ messageStatusTextView.setText("sendDatagram exception caught = " + e);
}
}
@@ -148,16 +157,18 @@
byte[] testProvisionData = mMessageOutput.getBytes();
setupForTransferringDatagram(testProvisionData);
- int result = mSatelliteManager.registerForSatelliteDatagram(Runnable::run, mCallback);
+ int result = mSatelliteManager.registerForIncomingDatagram(Runnable::run, mCallback);
TextView showErrorStatusTextView = findViewById(R.id.showErrorStatus);
if (result != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
- showErrorStatusTextView.setText("Status for registerForSatelliteDatagram : "
+ showErrorStatusTextView.setText("Status for registerForIncomingDatagram : "
+ SatelliteErrorUtils.mapError(result));
}
if (SatelliteTestApp.getTestSatelliteService() != null) {
SatelliteTestApp.getTestSatelliteService().sendOnPendingDatagrams();
}
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.requestEnabled(
+ new EnableRequestAttributes.Builder(true).setDemoMode(true).build(),
+ Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -173,7 +184,7 @@
return;
}
- mSatelliteManager.pollPendingSatelliteDatagrams(Runnable::run, resultListener::offer);
+ mSatelliteManager.pollPendingDatagrams(Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -185,7 +196,7 @@
mMessageStatusTextView.setText("Successfully polled pending messages");
}
} catch (InterruptedException e) {
- mMessageStatusTextView.setText("pollPendingSatelliteDatagrams exception caught = " + e);
+ mMessageStatusTextView.setText("pollPendingDatagrams exception caught = " + e);
}
}
@@ -195,7 +206,7 @@
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
//Provisioning
- mSatelliteManager.provisionSatelliteService("SATELLITE_TOKEN", provisionData,
+ mSatelliteManager.provisionService("SATELLITE_TOKEN", provisionData,
cancellationSignal, Runnable::run, error::offer);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -233,12 +244,14 @@
+ SatelliteErrorUtils.mapError(errorCode.get()));
}
};
- mSatelliteManager.requestSatelliteCapabilities(Runnable::run, receiver);
+ mSatelliteManager.requestCapabilities(Runnable::run, receiver);
//Satellite Position
SatelliteTransmissionUpdateCallbackTestApp callback =
new SatelliteTransmissionUpdateCallbackTestApp();
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, error::offer);
+ mSatelliteManager.requestEnabled(
+ new EnableRequestAttributes.Builder(true).setDemoMode(true).build(),
+ Runnable::run, error::offer);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -254,7 +267,7 @@
}
error.clear();
- mSatelliteManager.startSatelliteTransmissionUpdates(Runnable::run, error::offer, callback);
+ mSatelliteManager.startTransmissionUpdates(Runnable::run, error::offer, callback);
// Position update
android.telephony.satellite.stub.PointingInfo pointingInfo =
new android.telephony.satellite.stub.PointingInfo();
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
index 929a2e5..d79240e 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2023 The Android Open Source Project
+ * Copyright (C) 2024 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.
@@ -41,7 +41,9 @@
import com.android.internal.util.FunctionalUtils;
import com.android.telephony.Rlog;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -94,6 +96,11 @@
private boolean mIsSupported;
private int mModemState;
private boolean mIsCellularModemEnabledMode;
+ private List<String> mCarrierPlmnList = new ArrayList<>();
+ private List<String> mAllPlmnList = new ArrayList<>();
+ private boolean mIsSatelliteEnabledForCarrier;
+ private boolean mIsRequestIsSatelliteEnabledForCarrier;
+ private boolean mIsEmergnecy;
/**
* Create TestSatelliteService using the Executor specified for methods being called from
@@ -109,6 +116,9 @@
mIsSupported = true;
mModemState = SatelliteModemState.SATELLITE_MODEM_STATE_OFF;
mIsCellularModemEnabledMode = false;
+ mIsSatelliteEnabledForCarrier = false;
+ mIsRequestIsSatelliteEnabledForCarrier = false;
+ mIsEmergnecy = false;
}
/**
@@ -176,8 +186,9 @@
@Override
public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
- @NonNull IIntegerConsumer errorCallback) {
- logd("requestSatelliteEnabled: mErrorCode=" + mErrorCode + " enable = " + enableSatellite);
+ boolean isEmergency, @NonNull IIntegerConsumer errorCallback) {
+ logd("requestSatelliteEnabled: mErrorCode=" + mErrorCode + " enable = " + enableSatellite
+ + " isEmergency=" + isEmergency);
if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
runWithExecutor(() -> errorCallback.accept(mErrorCode));
return;
@@ -188,6 +199,7 @@
} else {
disableSatellite(errorCallback);
}
+ mIsEmergnecy = isEmergency;
}
private void enableSatellite(@NonNull IIntegerConsumer errorCallback) {
@@ -330,14 +342,14 @@
if (mLocalListener != null) {
runWithExecutor(() -> mLocalListener.onPollPendingSatelliteDatagrams());
} else {
- loge("pollPendingSatelliteDatagrams: mLocalListener is null");
+ loge("pollPendingDatagrams: mLocalListener is null");
}
}
@Override
public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency,
@NonNull IIntegerConsumer errorCallback) {
- logd("sendSatelliteDatagram: mErrorCode=" + mErrorCode);
+ logd("sendDatagram: mErrorCode=" + mErrorCode);
if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
runWithExecutor(() -> errorCallback.accept(mErrorCode));
} else {
@@ -347,7 +359,7 @@
if (mLocalListener != null) {
runWithExecutor(() -> mLocalListener.onSendSatelliteDatagram(datagram, isEmergency));
} else {
- loge("sendSatelliteDatagram: mLocalListener is null");
+ loge("sendDatagram: mLocalListener is null");
}
}
@@ -363,22 +375,6 @@
}
@Override
- public void requestIsSatelliteCommunicationAllowedForCurrentLocation(
- @NonNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback) {
- logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: mErrorCode=" + mErrorCode);
- if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
- runWithExecutor(() -> errorCallback.accept(mErrorCode));
- return;
- }
-
- if (mIsCommunicationAllowedInLocation) {
- runWithExecutor(() -> callback.accept(true));
- } else {
- runWithExecutor(() -> callback.accept(false));
- }
- }
-
- @Override
public void requestTimeForNextSatelliteVisibility(@NonNull IIntegerConsumer errorCallback,
@NonNull IIntegerConsumer callback) {
logd("requestTimeForNextSatelliteVisibility: mErrorCode=" + mErrorCode);
@@ -389,6 +385,55 @@
runWithExecutor(() -> callback.accept(SATELLITE_ALWAYS_VISIBLE));
}
+ @Override
+ public void setSatellitePlmn(int simLogicalSlotIndex, List<String> carrierPlmnList,
+ List<String> allSatellitePlmnList, IIntegerConsumer resultCallback) {
+ logd("setSatellitePlmn: simLogicalSlotIndex=" + simLogicalSlotIndex + " , carrierPlmnList="
+ + carrierPlmnList + " , allSatellitePlmnList=" + allSatellitePlmnList);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> resultCallback.accept(mErrorCode));
+ return;
+ }
+ runWithExecutor(() -> resultCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+
+ mCarrierPlmnList = carrierPlmnList;
+ mAllPlmnList = allSatellitePlmnList;
+
+ if (mLocalListener != null) {
+ runWithExecutor(() -> mLocalListener.onSetSatellitePlmn());
+ } else {
+ loge("setSatellitePlmn: mLocalListener is null");
+ }
+ }
+
+ @Override
+ public void setSatelliteEnabledForCarrier(int simLogicalSlotIndex, boolean satelliteEnabled,
+ IIntegerConsumer callback) {
+ logd("setSatelliteEnabledForCarrier: simLogicalSlotIndex=" + simLogicalSlotIndex
+ + ", satelliteEnabled=" + satelliteEnabled);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> callback.accept(mErrorCode));
+ return;
+ }
+
+ mIsSatelliteEnabledForCarrier = satelliteEnabled;
+ runWithExecutor(() -> callback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS));
+ }
+
+ @Override
+ public void requestIsSatelliteEnabledForCarrier(int simLogicalSlotIndex,
+ IIntegerConsumer resultCallback, IBooleanConsumer callback) {
+ logd("requestIsSatelliteEnabledForCarrier: simLogicalSlotIndex=" + simLogicalSlotIndex);
+ if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
+ runWithExecutor(() -> resultCallback.accept(mErrorCode));
+ mIsRequestIsSatelliteEnabledForCarrier = false;
+ return;
+ }
+
+ runWithExecutor(() -> callback.accept(mIsSatelliteEnabledForCarrier));
+ mIsRequestIsSatelliteEnabledForCarrier = true;
+ }
+
public void setLocalSatelliteListener(@NonNull ILocalSatelliteListener listener) {
logd("setLocalSatelliteListener: listener=" + listener);
mLocalListener = listener;
@@ -426,6 +471,16 @@
}
/**
+ * Helper method to report satellite supported from modem side for testing purpose.
+ * @param supported whether satellite is supported from modem or not.
+ */
+ public void sendOnSatelliteSupportedStateChanged(boolean supported) {
+ logd("sendOnSatelliteSupportedStateChanged: supported=" + supported);
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(() ->
+ listener.onSatelliteSupportedStateChanged(supported)));
+ }
+
+ /**
* Helper method to verify that the satellite modem is properly configured to receive
* requests.
*
@@ -508,6 +563,42 @@
}
}
+ public List<String> getCarrierPlmnList() {
+ return mCarrierPlmnList;
+ }
+
+ public List<String> getAllSatellitePlmnList() {
+ return mAllPlmnList;
+ }
+
+ public boolean isSatelliteEnabledForCarrier() {
+ return mIsSatelliteEnabledForCarrier;
+ }
+
+ public boolean isRequestIsSatelliteEnabledForCarrier() {
+ return mIsRequestIsSatelliteEnabledForCarrier;
+ }
+
+ public boolean getIsEmergency() {
+ return mIsEmergnecy;
+ }
+
+ /**
+ * Helper methoid to provide a way to set supported state from test application to mock modem.
+ * @param supported whether satellite is supported by modem or not.
+ */
+ public void updateSatelliteSupportedState(boolean supported) {
+ logd("updateSatelliteSupportedState: supported=" + supported);
+ mIsSupported = supported;
+ mRemoteListeners.values().forEach(listener -> runWithExecutor(
+ () -> listener.onSatelliteSupportedStateChanged(mIsSupported)));
+
+ }
+
+ public boolean getSatelliteSupportedState() {
+ return mIsSupported;
+ }
+
/**
* Log the message to the radio buffer with {@code DEBUG} priority.
*
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
index 792c984..27967f4 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
@@ -23,7 +23,6 @@
import android.os.OutcomeReceiver;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.wrapper.NtnSignalStrengthCallbackWrapper;
import android.telephony.satellite.wrapper.NtnSignalStrengthWrapper;
import android.telephony.satellite.wrapper.SatelliteCapabilitiesCallbackWrapper;
@@ -37,11 +36,12 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.function.Consumer;
import java.util.stream.Collectors;
-
/**
* Activity related to SatelliteControl APIs for satellite.
*/
@@ -55,6 +55,7 @@
private NtnSignalStrengthCallback mNtnSignalStrengthCallback = null;
private SatelliteCapabilitiesCallbackWrapper mSatelliteCapabilitiesCallback;
private SubscriptionManager mSubscriptionManager;
+ private int mSubId;
private ListView mLogListView;
@@ -63,6 +64,7 @@
super.onCreate(savedInstanceState);
mSatelliteManagerWrapper = SatelliteManagerWrapper.getInstance(this);
mSubscriptionManager = getSystemService(SubscriptionManager.class);
+ mSubId = getActiveSubId();
setContentView(R.layout.activity_TestSatelliteWrapper);
findViewById(R.id.requestNtnSignalStrength)
@@ -74,9 +76,29 @@
findViewById(R.id.isOnlyNonTerrestrialNetworkSubscription)
.setOnClickListener(this::isOnlyNonTerrestrialNetworkSubscription);
findViewById(R.id.registerForSatelliteCapabilitiesChanged)
- .setOnClickListener(this::registerForSatelliteCapabilitiesChanged);
+ .setOnClickListener(this::registerForCapabilitiesChanged);
findViewById(R.id.unregisterForSatelliteCapabilitiesChanged)
- .setOnClickListener(this::unregisterForSatelliteCapabilitiesChanged);
+ .setOnClickListener(this::unregisterForCapabilitiesChanged);
+ findViewById(R.id.isNonTerrestrialNetwork)
+ .setOnClickListener(this::isNonTerrestrialNetwork);
+ findViewById(R.id.getAvailableServices)
+ .setOnClickListener(this::getAvailableServices);
+ findViewById(R.id.isUsingNonTerrestrialNetwork)
+ .setOnClickListener(this::isUsingNonTerrestrialNetwork);
+ findViewById(R.id.requestAttachEnabledForCarrier_enable)
+ .setOnClickListener(this::requestAttachEnabledForCarrier_enable);
+ findViewById(R.id.requestAttachEnabledForCarrier_disable)
+ .setOnClickListener(this::requestAttachEnabledForCarrier_disable);
+ findViewById(R.id.requestIsAttachEnabledForCarrier)
+ .setOnClickListener(this::requestIsAttachEnabledForCarrier);
+ findViewById(R.id.addAttachRestrictionForCarrier)
+ .setOnClickListener(this::addAttachRestrictionForCarrier);
+ findViewById(R.id.removeAttachRestrictionForCarrier)
+ .setOnClickListener(this::removeAttachRestrictionForCarrier);
+ findViewById(R.id.getAttachRestrictionReasonsForCarrier)
+ .setOnClickListener(this::getAttachRestrictionReasonsForCarrier);
+ findViewById(R.id.getSatellitePlmnsForCarrier)
+ .setOnClickListener(this::getSatellitePlmnsForCarrier);
findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
@@ -109,21 +131,24 @@
if (mSatelliteManagerWrapper != null) {
if (mNtnSignalStrengthCallback != null) {
- Log.d(TAG, "unregisterForNtnSignalStrengthChanged()");
+ logd("unregisterForNtnSignalStrengthChanged()");
mSatelliteManagerWrapper.unregisterForNtnSignalStrengthChanged(
mNtnSignalStrengthCallback);
}
if (mSatelliteCapabilitiesCallback != null) {
- Log.d(TAG, "unregisterForSatelliteCapabilitiesChanged()");
- mSatelliteManagerWrapper.unregisterForSatelliteCapabilitiesChanged(
+ logd("unregisterForCapabilitiesChanged()");
+ mSatelliteManagerWrapper.unregisterForCapabilitiesChanged(
mSatelliteCapabilitiesCallback);
}
}
+ mSubscriptionManager = null;
+ mSatelliteManagerWrapper = null;
+ mExecutor.shutdown();
}
private void requestNtnSignalStrength(View view) {
addLogMessage("requestNtnSignalStrength");
- Log.d(TAG, "requestNtnSignalStrength");
+ logd("requestNtnSignalStrength");
OutcomeReceiver<NtnSignalStrengthWrapper,
SatelliteManagerWrapper.SatelliteExceptionWrapper> receiver =
new OutcomeReceiver<>() {
@@ -140,7 +165,7 @@
if (exception != null) {
String onError = "requestNtnSignalStrength exception: "
+ translateResultCodeToString(exception.getErrorCode());
- Log.d(TAG, onError);
+ logd(onError);
addLogMessage(onError);
}
}
@@ -148,18 +173,18 @@
try {
mSatelliteManagerWrapper.requestNtnSignalStrength(mExecutor, receiver);
- } catch (SecurityException | IllegalStateException ex) {
+ } catch (SecurityException ex) {
String errorMessage = "requestNtnSignalStrength: " + ex.getMessage();
- Log.d(TAG, errorMessage);
+ logd(errorMessage);
addLogMessage(errorMessage);
}
}
private void registerForNtnSignalStrengthChanged(View view) {
addLogMessage("registerForNtnSignalStrengthChanged");
- Log.d(TAG, "registerForNtnSignalStrengthChanged()");
+ logd("registerForNtnSignalStrengthChanged()");
if (mNtnSignalStrengthCallback == null) {
- Log.d(TAG, "create new NtnSignalStrengthCallback instance.");
+ logd("create new NtnSignalStrengthCallback instance.");
mNtnSignalStrengthCallback = new NtnSignalStrengthCallback();
}
@@ -167,24 +192,16 @@
mSatelliteManagerWrapper.registerForNtnSignalStrengthChanged(mExecutor,
mNtnSignalStrengthCallback);
} catch (Exception ex) {
- String errorMessage;
- if (ex instanceof SatelliteManager.SatelliteException) {
- errorMessage =
- "registerForNtnSignalStrengthChanged: " + translateResultCodeToString(
- ((SatelliteManager.SatelliteException) ex).getErrorCode());
- } else {
- errorMessage = "registerForNtnSignalStrengthChanged: " + ex.getMessage();
- }
- Log.d(TAG, errorMessage);
+ String errorMessage = "registerForNtnSignalStrengthChanged: " + ex.getMessage();
+ logd(errorMessage);
addLogMessage(errorMessage);
mNtnSignalStrengthCallback = null;
-
}
}
private void unregisterForNtnSignalStrengthChanged(View view) {
addLogMessage("unregisterForNtnSignalStrengthChanged");
- Log.d(TAG, "unregisterForNtnSignalStrengthChanged()");
+ logd("unregisterForNtnSignalStrengthChanged()");
if (mNtnSignalStrengthCallback != null) {
mSatelliteManagerWrapper.unregisterForNtnSignalStrengthChanged(
mNtnSignalStrengthCallback);
@@ -197,7 +214,7 @@
private void isOnlyNonTerrestrialNetworkSubscription(View view) {
addLogMessage("isOnlyNonTerrestrialNetworkSubscription");
- Log.d(TAG, "isOnlyNonTerrestrialNetworkSubscription()");
+ logd("isOnlyNonTerrestrialNetworkSubscription()");
List<SubscriptionInfo> infoList = mSubscriptionManager.getAvailableSubscriptionInfoList();
List<Integer> subIdList = infoList.stream()
.map(SubscriptionInfo::getSubscriptionId)
@@ -222,34 +239,34 @@
}
}
- private void registerForSatelliteCapabilitiesChanged(View view) {
- addLogMessage("registerForSatelliteCapabilitiesChanged");
- Log.d(TAG, "registerForSatelliteCapabilitiesChanged()");
+ private void registerForCapabilitiesChanged(View view) {
+ addLogMessage("registerForCapabilitiesChanged");
+ logd("registerForCapabilitiesChanged()");
if (mSatelliteCapabilitiesCallback == null) {
mSatelliteCapabilitiesCallback =
SatelliteCapabilities -> {
String message = "Received SatelliteCapabillities : "
+ SatelliteCapabilities;
- Log.d(TAG, message);
- runOnUiThread(() -> addLogMessage(message));
+ logd(message);
+ addLogMessage(message);
};
}
- int result = mSatelliteManagerWrapper.registerForSatelliteCapabilitiesChanged(mExecutor,
+ int result = mSatelliteManagerWrapper.registerForCapabilitiesChanged(mExecutor,
mSatelliteCapabilitiesCallback);
if (result != SatelliteManagerWrapper.SATELLITE_RESULT_SUCCESS) {
String onError = translateResultCodeToString(result);
- Log.d(TAG, onError);
+ logd(onError);
addLogMessage(onError);
mSatelliteCapabilitiesCallback = null;
}
}
- private void unregisterForSatelliteCapabilitiesChanged(View view) {
- addLogMessage("unregisterForSatelliteCapabilitiesChanged");
- Log.d(TAG, "unregisterForSatelliteCapabilitiesChanged()");
+ private void unregisterForCapabilitiesChanged(View view) {
+ addLogMessage("unregisterForCapabilitiesChanged");
+ logd("unregisterForCapabilitiesChanged()");
if (mSatelliteCapabilitiesCallback != null) {
- mSatelliteManagerWrapper.unregisterForSatelliteCapabilitiesChanged(
+ mSatelliteManagerWrapper.unregisterForCapabilitiesChanged(
mSatelliteCapabilitiesCallback);
mSatelliteCapabilitiesCallback = null;
addLogMessage("mSatelliteCapabilitiesCallback was unregistered");
@@ -263,11 +280,237 @@
public void onNtnSignalStrengthChanged(
@NonNull NtnSignalStrengthWrapper ntnSignalStrength) {
String message = "Received NTN SignalStrength : " + ntnSignalStrength.getLevel();
- Log.d(TAG, message);
- runOnUiThread(() -> addLogMessage(message));
+ logd(message);
+ addLogMessage(message);
}
}
+ private void isNonTerrestrialNetwork(View view) {
+ boolean isNonTerrestrialNetwork = mSatelliteManagerWrapper.isNonTerrestrialNetwork(mSubId);
+ addLogMessage("isNonTerrestrialNetwork=" + isNonTerrestrialNetwork);
+ logd("isNonTerrestrialNetwork=" + isNonTerrestrialNetwork);
+ }
+
+ private void getAvailableServices(View view) {
+ List<Integer> as = mSatelliteManagerWrapper.getAvailableServices(mSubId);
+ String availableServices = as.stream().map(Object::toString).collect(
+ Collectors.joining(", "));
+ addLogMessage("getAvailableServices=" + availableServices);
+ logd("getAvailableServices=" + availableServices);
+ }
+
+ private void isUsingNonTerrestrialNetwork(View view) {
+ boolean isUsingNonTerrestrialNetwork =
+ mSatelliteManagerWrapper.isUsingNonTerrestrialNetwork(mSubId);
+ addLogMessage("isUsingNonTerrestrialNetwork=" + isUsingNonTerrestrialNetwork);
+ logd("isUsingNonTerrestrialNetwork=" + isUsingNonTerrestrialNetwork);
+ }
+
+ private void requestAttachEnabledForCarrier_enable(View view) {
+ addLogMessage("requestAttachEnabledForCarrier");
+ logd("requestAttachEnabledForCarrier");
+
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ addLogMessage("requestAttachEnabledForCarrier: Subscription ID is invalid");
+ logd("requestAttachEnabledForCarrier: Subscription ID is invalid");
+ return;
+ }
+
+ Consumer<Integer> callback = result -> {
+ addLogMessage("requestAttachEnabledForCarrier result: " + result);
+ logd("requestAttachEnabledForCarrier result: " + result);
+ };
+
+ try {
+ mSatelliteManagerWrapper.requestAttachEnabledForCarrier(mSubId, true, mExecutor,
+ callback);
+ } catch (SecurityException | IllegalArgumentException ex) {
+ String errorMessage = "requestAttachEnabledForCarrier: " + ex.getMessage();
+ logd(errorMessage);
+ addLogMessage(errorMessage);
+ }
+ }
+
+ private void requestAttachEnabledForCarrier_disable(View view) {
+ addLogMessage("requestAttachEnabledForCarrier");
+ logd("requestAttachEnabledForCarrier");
+
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ addLogMessage("requestAttachEnabledForCarrier: Subscription ID is invalid");
+ logd("requestAttachEnabledForCarrier: Subscription ID is invalid");
+ return;
+ }
+
+ Consumer<Integer> callback = result -> {
+ addLogMessage("requestAttachEnabledForCarrier result: " + result);
+ logd("requestAttachEnabledForCarrier result: " + result);
+ };
+
+ try {
+ mSatelliteManagerWrapper.requestAttachEnabledForCarrier(mSubId, false, mExecutor,
+ callback);
+ } catch (SecurityException | IllegalArgumentException ex) {
+ String errorMessage = "requestAttachEnabledForCarrier: " + ex.getMessage();
+ logd(errorMessage);
+ addLogMessage(errorMessage);
+ }
+ }
+
+ private void requestIsAttachEnabledForCarrier(View view) {
+ logd("requestIsAttachEnabledForCarrier");
+ addLogMessage("requestIsAttachEnabledForCarrier");
+
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ addLogMessage("requestIsAttachEnabledForCarrier: Subscription ID is invalid");
+ logd("requestIsAttachEnabledForCarrier: Subscription ID is invalid");
+ return;
+ }
+
+ OutcomeReceiver<Boolean,
+ SatelliteManagerWrapper.SatelliteExceptionWrapper> receiver =
+ new OutcomeReceiver<>() {
+ @Override
+ public void onResult(Boolean result) {
+ logd("requestIsAttachEnabledForCarrier: onResult=" + result);
+ addLogMessage("requestIsAttachEnabledForCarrier: onResult=" + result);
+ }
+
+ @Override
+ public void onError(
+ SatelliteManagerWrapper.SatelliteExceptionWrapper exception) {
+ if (exception != null) {
+ String onError = "requestIsAttachEnabledForCarrier exception: "
+ + translateResultCodeToString(exception.getErrorCode());
+ logd(onError);
+ addLogMessage(onError);
+ }
+ }
+ };
+
+ try {
+ mSatelliteManagerWrapper.requestIsAttachEnabledForCarrier(mSubId, mExecutor, receiver);
+ } catch (SecurityException | IllegalStateException | IllegalArgumentException ex) {
+ String errorMessage = "requestIsAttachEnabledForCarrier: " + ex.getMessage();
+ logd(errorMessage);
+ addLogMessage(errorMessage);
+ }
+ }
+
+ private void addAttachRestrictionForCarrier(View view) {
+ addLogMessage("addAttachRestrictionForCarrier");
+ logd("addAttachRestrictionForCarrier");
+
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ addLogMessage("addAttachRestrictionForCarrier: Subscription ID is invalid");
+ logd("addAttachRestrictionForCarrier: Subscription ID is invalid");
+ return;
+ }
+
+ int reason = SatelliteManagerWrapper.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
+
+ Consumer<Integer> callback = result -> {
+ addLogMessage("addAttachRestrictionForCarrier result: " + result);
+ logd("addAttachRestrictionForCarrier result: " + result);
+ };
+
+ try {
+ mSatelliteManagerWrapper.addAttachRestrictionForCarrier(mSubId, reason, mExecutor,
+ callback);
+ } catch (SecurityException | IllegalArgumentException ex) {
+ String errorMessage = "addAttachRestrictionForCarrier: " + ex.getMessage();
+ logd(errorMessage);
+ addLogMessage(errorMessage);
+ }
+ }
+
+ private void removeAttachRestrictionForCarrier(View view) {
+ addLogMessage("removeAttachRestrictionForCarrier");
+ logd("removeAttachRestrictionForCarrier");
+
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ addLogMessage("removeAttachRestrictionForCarrier: Subscription ID is invalid");
+ logd("removeAttachRestrictionForCarrier: Subscription ID is invalid");
+ return;
+ }
+
+ int reason = SatelliteManagerWrapper.SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER;
+
+ Consumer<Integer> callback = result -> {
+ addLogMessage("removeAttachRestrictionForCarrier result: " + result);
+ logd("removeAttachRestrictionForCarrier result: " + result);
+ };
+
+ try {
+ mSatelliteManagerWrapper.removeAttachRestrictionForCarrier(mSubId, reason, mExecutor,
+ callback);
+ } catch (SecurityException | IllegalArgumentException ex) {
+ String errorMessage = "removeAttachRestrictionForCarrier: " + ex.getMessage();
+ logd(errorMessage);
+ addLogMessage(errorMessage);
+ }
+ }
+
+ private void getAttachRestrictionReasonsForCarrier(View view) {
+ addLogMessage("getAttachRestrictionReasonsForCarrier");
+ logd("getAttachRestrictionReasonsForCarrier");
+
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ addLogMessage("getAttachRestrictionReasonsForCarrier: Subscription ID is invalid");
+ logd("getAttachRestrictionReasonsForCarrier: Subscription ID is invalid");
+ return;
+ }
+
+ try {
+ Set<Integer> reasons = mSatelliteManagerWrapper.getAttachRestrictionReasonsForCarrier(
+ mSubId);
+ String stringReasons = reasons.stream().map(Object::toString).collect(
+ Collectors.joining(", "));
+ logd("getAttachRestrictionReasonsForCarrier=" + stringReasons);
+ addLogMessage("getAttachRestrictionReasonsForCarrier=" + stringReasons);
+ } catch (SecurityException | IllegalArgumentException ex) {
+ String errorMessage = "getAttachRestrictionReasonsForCarrier: " + ex.getMessage();
+ logd(errorMessage);
+ addLogMessage(errorMessage);
+ }
+ }
+
+ private void getSatellitePlmnsForCarrier(View view) {
+ addLogMessage("getSatellitePlmnsForCarrier");
+ logd("getSatellitePlmnsForCarrier");
+
+ if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ addLogMessage("getSatellitePlmnsForCarrier: Subscription ID is invalid");
+ logd("getSatellitePlmnsForCarrier: Subscription ID is invalid");
+ return;
+ }
+
+ try {
+ List<String> reasons = mSatelliteManagerWrapper.getSatellitePlmnsForCarrier(
+ mSubId);
+ String stringReasons = reasons.stream().collect(Collectors.joining(", "));
+ logd("getSatellitePlmnsForCarrier=" + stringReasons);
+ addLogMessage("getSatellitePlmnsForCarrier=" + stringReasons);
+ } catch (SecurityException | IllegalArgumentException ex) {
+ String errorMessage = "getSatellitePlmnsForCarrier: " + ex.getMessage();
+ logd(errorMessage);
+ addLogMessage(errorMessage);
+ }
+ }
+
+ private int getActiveSubId() {
+ int subId;
+ List<SubscriptionInfo> subscriptionInfoList =
+ mSubscriptionManager.getActiveSubscriptionInfoList();
+
+ if (subscriptionInfoList != null && subscriptionInfoList.size() > 0) {
+ subId = subscriptionInfoList.get(0).getSubscriptionId();
+ } else {
+ subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+ logd("getActiveSubId() returns " + subId);
+ return subId;
+ }
+
private String translateResultCodeToString(
@SatelliteManagerWrapper.SatelliteResult int result) {
switch (result) {
@@ -317,14 +560,24 @@
return "SATELLITE_RESULT_REQUEST_IN_PROGRESS";
case SatelliteManagerWrapper.SATELLITE_RESULT_MODEM_BUSY:
return "SATELLITE_RESULT_MODEM_BUSY";
+ case SatelliteManagerWrapper.SATELLITE_RESULT_ILLEGAL_STATE:
+ return "SATELLITE_RESULT_ILLEGAL_STATE";
default:
return "INVALID CODE: " + result;
}
}
private void addLogMessage(String message) {
- mLogMessages.add(message);
- mAdapter.notifyDataSetChanged();
- mLogListView.setSelection(mAdapter.getCount() - 1);
+ runOnUiThread(() -> {
+ mLogMessages.add(message);
+ mAdapter.notifyDataSetChanged();
+ mLogListView.setSelection(mAdapter.getCount() - 1);
+ });
+ }
+
+ private static void logd(String message) {
+ if (message != null) {
+ Log.d(TAG, message);
+ }
}
}
diff --git a/tests/Android.bp b/tests/Android.bp
index 3015f76..6914839 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -50,10 +50,10 @@
"testables",
"platform-compat-test-rules",
"flag-junit",
+ "telephony_flags_core_java_lib",
"satellite-s2storage-rw",
"satellite-s2storage-testutils",
"s2-geometry-library-java",
- "telephony-satellite",
],
test_suites: [
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index 111df53..a96ce2e 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -19,6 +19,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
@@ -61,6 +62,7 @@
@Mock SubscriptionManager mMockSubscriptionManager;
@Mock ImsManager mMockImsManager;
@Mock UserManager mMockUserManager;
+ @Mock PackageManager mPackageManager;
private final SparseArray<PersistableBundle> mCarrierConfigs = new SparseArray<>();
@@ -80,6 +82,7 @@
int subId = (int) invocation.getArguments()[0];
return getTestConfigs(subId);
}).when(mMockCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
+ when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
}
@Override
@@ -145,6 +148,11 @@
}
@Override
+ public PackageManager getPackageManager() {
+ return mPackageManager;
+ }
+
+ @Override
public ContentResolver getContentResolver() {
return null;
}
diff --git a/tests/src/com/android/phone/CarrierConfigLoaderTest.java b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
index bd2e4f7..f4197d9 100644
--- a/tests/src/com/android/phone/CarrierConfigLoaderTest.java
+++ b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
@@ -21,6 +21,7 @@
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -30,6 +31,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
@@ -56,12 +58,17 @@
import com.android.TelephonyTestBase;
import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
@@ -76,10 +83,14 @@
*/
@RunWith(AndroidJUnit4.class)
public class CarrierConfigLoaderTest extends TelephonyTestBase {
+ @Rule
+ public TestRule compatChangeRule = new PlatformCompatChangeRule();
+ private static final String TAG = CarrierConfigLoaderTest.class.getSimpleName();
private static final int DEFAULT_PHONE_ID = 0;
private static final int DEFAULT_SUB_ID = SubscriptionManager.getDefaultSubscriptionId();
private static final String PLATFORM_CARRIER_CONFIG_PACKAGE = "com.android.carrierconfig";
+ private static final String PLATFORM_CARRIER_CONFIG_FEATURE = "com.android.carrierconfig";
private static final long PLATFORM_CARRIER_CONFIG_PACKAGE_VERSION_CODE = 1;
private static final String CARRIER_CONFIG_EXAMPLE_KEY =
CarrierConfigManager.KEY_CARRIER_USSD_METHOD_INT;
@@ -92,6 +103,7 @@
@Mock SubscriptionManagerService mSubscriptionManagerService;
@Mock SharedPreferences mSharedPreferences;
@Mock TelephonyRegistryManager mTelephonyRegistryManager;
+ @Mock FeatureFlags mFeatureFlags;
private TelephonyManager mTelephonyManager;
private CarrierConfigLoader mCarrierConfigLoader;
@@ -118,6 +130,8 @@
doReturn(Build.FINGERPRINT).when(mSharedPreferences).getString(eq("build_fingerprint"),
any());
doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(new String[]{TAG}).when(mPackageManager).getPackagesForUid(anyInt());
+
doReturn(mResources).when(mContext).getResources();
doReturn(InstrumentationRegistry.getTargetContext().getFilesDir()).when(
mContext).getFilesDir();
@@ -141,7 +155,8 @@
mHandlerThread.start();
mTestableLooper = new TestableLooper(mHandlerThread.getLooper());
- mCarrierConfigLoader = new CarrierConfigLoader(mContext, mTestableLooper.getLooper());
+ mCarrierConfigLoader = new CarrierConfigLoader(mContext, mTestableLooper.getLooper(),
+ mFeatureFlags);
mHandler = mCarrierConfigLoader.getHandler();
// Clear all configs to have the same starting point.
@@ -412,6 +427,34 @@
assertThat(dumpContent).doesNotContain("Permission Denial:");
}
+ @Test
+ @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
+ public void testGetConfigForSubIdWithFeature_withTelephonyFeatureMapping() {
+ doNothing().when(mContext).enforcePermission(
+ eq(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE),
+ anyInt(), anyInt(), anyString());
+
+ doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ doReturn(false).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
+
+ // Not defined required feature, expect UnsupportedOperationException
+ assertThrows(UnsupportedOperationException.class,
+ () -> mCarrierConfigLoader.getConfigForSubIdWithFeature(DEFAULT_SUB_ID,
+ PLATFORM_CARRIER_CONFIG_PACKAGE, PLATFORM_CARRIER_CONFIG_FEATURE));
+
+ doReturn(true).when(mPackageManager).hasSystemFeature(
+ eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
+
+ // Defined required feature, not expect UnsupportedOperationException
+ try {
+ mCarrierConfigLoader.getConfigForSubIdWithFeature(DEFAULT_SUB_ID,
+ PLATFORM_CARRIER_CONFIG_PACKAGE, PLATFORM_CARRIER_CONFIG_FEATURE);
+ } catch (UnsupportedOperationException e) {
+ fail("not expected UnsupportedOperationException");
+ }
+ }
+
private static PersistableBundle getTestConfig() {
PersistableBundle config = new PersistableBundle();
config.putInt(CARRIER_CONFIG_EXAMPLE_KEY, CARRIER_CONFIG_EXAMPLE_VALUE);
diff --git a/tests/src/com/android/phone/DiagnosticDataCollectorTest.java b/tests/src/com/android/phone/DiagnosticDataCollectorTest.java
index e0d89bc..983d135 100644
--- a/tests/src/com/android/phone/DiagnosticDataCollectorTest.java
+++ b/tests/src/com/android/phone/DiagnosticDataCollectorTest.java
@@ -25,6 +25,7 @@
import static org.mockito.Mockito.verify;
import android.os.DropBoxManager;
+import android.os.SystemClock;
import android.telephony.TelephonyManager;
import org.junit.After;
@@ -94,30 +95,37 @@
@Test
public void testPersistForTelecomDumpsys() throws IOException, InterruptedException {
- TelephonyManager.EmergencyCallDiagnosticParams dp =
- new TelephonyManager.EmergencyCallDiagnosticParams();
- dp.setTelecomDumpSysCollection(true);
- mDiagnosticDataCollector.persistEmergencyDianosticData(mConfig, dp, "test_tag_telecom");
+ TelephonyManager.EmergencyCallDiagnosticData.Builder callDiagnosticBuilder =
+ new TelephonyManager.EmergencyCallDiagnosticData.Builder();
+ TelephonyManager.EmergencyCallDiagnosticData ecdData =
+ callDiagnosticBuilder.setTelecomDumpsysCollectionEnabled(true).build();
+ mDiagnosticDataCollector.persistEmergencyDianosticData(
+ mConfig, ecdData, "test_tag_telecom");
verifyCmdAndDropboxTag(TELECOM_DUMPSYS_COMMAND, "test_tag_telecom", false);
}
@Test
public void testPersistForTelephonyDumpsys() throws IOException, InterruptedException {
- TelephonyManager.EmergencyCallDiagnosticParams dp =
- new TelephonyManager.EmergencyCallDiagnosticParams();
- dp.setTelephonyDumpSysCollection(true);
- mDiagnosticDataCollector.persistEmergencyDianosticData(mConfig, dp, "test_tag_telephony");
+ TelephonyManager.EmergencyCallDiagnosticData.Builder callDiagnosticBuilder =
+ new TelephonyManager.EmergencyCallDiagnosticData.Builder();
+ TelephonyManager.EmergencyCallDiagnosticData ecdData =
+ callDiagnosticBuilder.setTelephonyDumpsysCollectionEnabled(true).build();
+ mDiagnosticDataCollector.persistEmergencyDianosticData(
+ mConfig, ecdData, "test_tag_telephony");
verifyCmdAndDropboxTag(TELEPHONY_DUMPSYS_COMMAND, "test_tag_telephony", false);
}
@Test
public void testPersistForLogcat() throws IOException, InterruptedException {
- TelephonyManager.EmergencyCallDiagnosticParams dp =
- new TelephonyManager.EmergencyCallDiagnosticParams();
- dp.setLogcatCollection(true, System.currentTimeMillis());
- mDiagnosticDataCollector.persistEmergencyDianosticData(mConfig, dp, "test_tag_logcat");
+ TelephonyManager.EmergencyCallDiagnosticData.Builder callDiagnosticBuilder =
+ new TelephonyManager.EmergencyCallDiagnosticData.Builder();
+ TelephonyManager.EmergencyCallDiagnosticData ecdData =
+ callDiagnosticBuilder.setLogcatCollectionStartTimeMillis(
+ SystemClock.elapsedRealtime()).build();
+ mDiagnosticDataCollector.persistEmergencyDianosticData(
+ mConfig, ecdData, "test_tag_logcat");
verifyCmdAndDropboxTag(LOGCAT_BINARY, "test_tag_logcat", true);
}
diff --git a/tests/src/com/android/phone/ImsProvisioningControllerTest.java b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
index db83cca..6599f03 100644
--- a/tests/src/com/android/phone/ImsProvisioningControllerTest.java
+++ b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
@@ -68,14 +68,16 @@
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.ImsConfigImplBase;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
import android.util.Log;
+import androidx.test.filters.SmallTest;
+
import com.android.ims.FeatureConnector;
import com.android.ims.ImsConfig;
import com.android.ims.ImsManager;
import com.android.ims.RcsFeatureManager;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
import org.junit.Before;
@@ -168,6 +170,9 @@
@Mock
IBinder mIbinder1;
+ @Mock
+ FeatureFlags mFeatureFlags;
+
private SubscriptionManager.OnSubscriptionsChangedListener mSubChangedListener;
private Handler mHandler;
@@ -191,7 +196,7 @@
TestImsProvisioningController() {
super(mPhone, 2, mHandlerThread.getLooper(),
mMmTelFeatureConnector, mRcsFeatureConnector,
- mImsProvisioningLoader);
+ mImsProvisioningLoader, mFeatureFlags);
}
protected int getSubId(int slotId) {
@@ -368,8 +373,6 @@
}
// verify other interactions
- verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
- verifyNoMoreInteractions(mIFeatureProvisioningCallback1);
verifyNoMoreInteractions(mImsConfig);
}
@@ -407,8 +410,6 @@
verify(mImsConfig, times(1)).setConfig(eq(key), anyInt());
// verify other interactions
- verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
- verifyNoMoreInteractions(mIFeatureProvisioningCallback1);
verifyNoMoreInteractions(mImsConfig);
}
@@ -925,8 +926,6 @@
verify(mImsConfig, times(1)).setConfig(
eq(KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE), eq(PROVISIONING_VALUE_ENABLED));
- verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
- verifyNoMoreInteractions(mIFeatureProvisioningCallback1);
verifyNoMoreInteractions(mImsConfig);
verifyNoMoreInteractions(mImsProvisioningLoader);
}
@@ -1848,6 +1847,184 @@
verifyNoMoreInteractions(mImsConfig);
}
+ @Test
+ @SmallTest
+ public void initialNotifyMmTelProvisioningStatusWhenCallbackRegistered() throws Exception {
+ when(mFeatureFlags.notifyInitialImsProvisioningStatus()).thenReturn(true);
+
+ createImsProvisioningController();
+
+ // Provisioning required for capability on all network type
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_UT_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_SMS_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0,
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_CALL_COMPOSER_INT_ARRAY, RADIO_TECHS);
+
+ // Stored provisioning Status
+ mMmTelProvisioningStorage = new int[][] {
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_LTE, 0},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_CROSS_SIM, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_NR, 1},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_LTE, 0},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_IWLAN, 0},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_CROSS_SIM, 1},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_NR, 1},
+ {CAPABILITY_TYPE_UT, REGISTRATION_TECH_LTE, 0},
+ {CAPABILITY_TYPE_UT, REGISTRATION_TECH_IWLAN, 0},
+ {CAPABILITY_TYPE_UT, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_UT, REGISTRATION_TECH_NR, 0},
+ {CAPABILITY_TYPE_SMS, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_SMS, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_SMS, REGISTRATION_TECH_CROSS_SIM, 1},
+ {CAPABILITY_TYPE_SMS, REGISTRATION_TECH_NR, 1},
+ {CAPABILITY_TYPE_CALL_COMPOSER, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_CALL_COMPOSER, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_CALL_COMPOSER, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_CALL_COMPOSER, REGISTRATION_TECH_NR, 1}
+ };
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+ processAllMessages();
+
+ for (int[] capa: mMmTelProvisioningStorage) {
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onFeatureProvisioningChanged(eq(capa[0]), eq(capa[1]), eq(capa[2] == 1));
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void initialNotifyRcsProvisioningStatusWhenCallbackRegistered() throws Exception {
+ when(mFeatureFlags.notifyInitialImsProvisioningStatus()).thenReturn(true);
+
+ createImsProvisioningController();
+
+ // Provisioning required capability : PRESENCE, tech : all
+ setCarrierConfig(mSubId0,
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY, RADIO_TECHS);
+
+ // Stored provisioning Status
+ mRcsProvisioningStorage = new int[][]{
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_NR, 1}
+ };
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+ processAllMessages();
+
+ for (int[] capa: mRcsProvisioningStorage) {
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onRcsFeatureProvisioningChanged(eq(capa[0]), eq(capa[1]), eq(capa[2] == 1));
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void initialNotifyMmTelProvisioningStatusWhenImsServiceConnected() throws Exception {
+ when(mFeatureFlags.notifyInitialImsProvisioningStatus()).thenReturn(true);
+
+ createImsProvisioningController();
+
+ // Provisioning required for capability on all network type
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VOICE_INT_ARRAY,
+ RADIO_TECHS);
+ setCarrierConfig(mSubId0, CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_VIDEO_INT_ARRAY,
+ RADIO_TECHS);
+
+ // Stored provisioning Status
+ mMmTelProvisioningStorage = new int[][] {
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_IWLAN, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_CROSS_SIM, 1},
+ {CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_NR, 1},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_IWLAN, 0},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_VIDEO, REGISTRATION_TECH_NR, 1},
+ };
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+ processAllMessages();
+
+ // clear interactions
+ clearInvocations(mIFeatureProvisioningCallback0);
+
+ // ImsService connected
+ mMmTelConnectorListener0.getValue().connectionReady(mImsManager, mSubId0);
+
+ for (int[] capa: mMmTelProvisioningStorage) {
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onFeatureProvisioningChanged(eq(capa[0]), eq(capa[1]), eq(capa[2] == 1));
+ }
+
+ verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
+ }
+
+ @Test
+ @SmallTest
+ public void initialNotifyRcsProvisioningStatusWhenRcsServiceConnected() throws Exception {
+ when(mFeatureFlags.notifyInitialImsProvisioningStatus()).thenReturn(true);
+
+ createImsProvisioningController();
+
+ // Provisioning required capability : PRESENCE, tech : all
+ setCarrierConfig(mSubId0,
+ CarrierConfigManager.Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY, RADIO_TECHS);
+
+ // Stored provisioning Status
+ mRcsProvisioningStorage = new int[][]{
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_LTE, 1},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_IWLAN, 0},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_CROSS_SIM, 0},
+ {CAPABILITY_TYPE_PRESENCE_UCE, REGISTRATION_TECH_NR, 1}
+ };
+
+ try {
+ mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+ mSubId0, mIFeatureProvisioningCallback0);
+ } catch (Exception e) {
+ throw new AssertionError("not expected exception", e);
+ }
+ processAllMessages();
+
+ // clear interactions
+ clearInvocations(mIFeatureProvisioningCallback0);
+
+ // ImsService connected
+ mRcsConnectorListener0.getValue().connectionReady(mRcsFeatureManager, mSubId0);
+
+ for (int[] capa: mRcsProvisioningStorage) {
+ verify(mIFeatureProvisioningCallback0, times(1))
+ .onRcsFeatureProvisioningChanged(eq(capa[0]), eq(capa[1]), eq(capa[2] == 1));
+ }
+
+ verifyNoMoreInteractions(mIFeatureProvisioningCallback0);
+ }
+
private void createImsProvisioningController() throws Exception {
if (Looper.myLooper() == null) {
Looper.prepare();
diff --git a/tests/src/com/android/phone/ImsProvisioningLoaderTest.java b/tests/src/com/android/phone/ImsProvisioningLoaderTest.java
index 61cab1d..207e454 100644
--- a/tests/src/com/android/phone/ImsProvisioningLoaderTest.java
+++ b/tests/src/com/android/phone/ImsProvisioningLoaderTest.java
@@ -28,10 +28,10 @@
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
diff --git a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
index 2bd87be..c86502b 100644
--- a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
+++ b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
@@ -48,10 +48,11 @@
import android.os.Looper;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyRegistryManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
import android.util.Log;
+import androidx.test.filters.SmallTest;
+
import com.android.TelephonyTestBase;
import com.android.ims.FeatureConnector;
import com.android.ims.ImsManager;
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
index 150703d..bd47b94 100644
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -20,8 +20,11 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
@@ -31,8 +34,11 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
+import android.compat.testing.PlatformCompatChangeRule;
import android.content.Context;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.permission.flags.Flags;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -49,12 +55,19 @@
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Locale;
/**
@@ -62,9 +75,14 @@
*/
@RunWith(AndroidJUnit4.class)
public class PhoneInterfaceManagerTest extends TelephonyTestBase {
+ @Rule
+ public TestRule compatChangeRule = new PlatformCompatChangeRule();
+
private PhoneInterfaceManager mPhoneInterfaceManager;
private SharedPreferences mSharedPreferences;
private IIntegerConsumer mIIntegerConsumer;
+ private static final String sDebugPackageName =
+ PhoneInterfaceManagerTest.class.getPackageName();
@Mock
PhoneGlobals mPhoneGlobals;
@@ -72,16 +90,22 @@
Phone mPhone;
@Mock
FeatureFlags mFeatureFlags;
-
+ @Mock
+ PackageManager mPackageManager;
@Mock
private SubscriptionManagerService mSubscriptionManagerService;
+ @Mock
+ private AppOpsManager mAppOps;
+
@Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Before
@UiThreadTest
public void setUp() throws Exception {
super.setUp();
+ doReturn(sDebugPackageName).when(mPhoneGlobals).getOpPackageName();
+
// 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
@@ -92,7 +116,17 @@
TelephonyManager.setupISubForTest(mSubscriptionManagerService);
mSharedPreferences = mPhoneInterfaceManager.getSharedPreferences();
mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED).commit();
+ mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED).commit();
mIIntegerConsumer = mock(IIntegerConsumer.class);
+
+ // In order not to affect the existing implementation, define a telephony features
+ // and disabled enforce_telephony_feature_mapping_for_public_apis feature flag
+ mPhoneInterfaceManager.setFeatureFlags(mFeatureFlags);
+ doReturn(false).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ mPhoneInterfaceManager.setPackageManager(mPackageManager);
+ doReturn(true).when(mPackageManager).hasSystemFeature(anyString());
+
+ mPhoneInterfaceManager.setAppOpsManager(mAppOps);
}
@Test
@@ -269,6 +303,108 @@
mPhoneInterfaceManager).getDefaultPhone();
}
+ @Test
+ public void setNullCipherNotificationsEnabled_allReqsMet_successfullyEnabled() {
+ setModemSupportsNullCipherNotification(true);
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+ doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED));
+
+ mPhoneInterfaceManager.setNullCipherNotificationsEnabled(true);
+
+ assertTrue(
+ mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, false));
+ }
+
+ @Test
+ public void setNullCipherNotificationsEnabled_allReqsMet_successfullyDisabled() {
+ setModemSupportsNullCipherNotification(true);
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+ doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ assertFalse(mSharedPreferences.contains(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED));
+
+ mPhoneInterfaceManager.setNullCipherNotificationsEnabled(false);
+
+ assertFalse(
+ mSharedPreferences.getBoolean(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED, true));
+ }
+
+ @Test
+ public void setNullCipherNotificationsEnabled_lackingNecessaryHal_throwsException() {
+ setModemSupportsNullCipherNotification(true);
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+ doReturn(102).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+
+ assertThrows(UnsupportedOperationException.class,
+ () -> mPhoneInterfaceManager.setNullCipherNotificationsEnabled(true));
+ }
+
+ @Test
+ public void setNullCipherNotificationsEnabled_lackingModemSupport_throwsException() {
+ setModemSupportsNullCipherNotification(false);
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+ doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+
+ assertThrows(UnsupportedOperationException.class,
+ () -> mPhoneInterfaceManager.setNullCipherNotificationsEnabled(true));
+ }
+
+ @Test
+ public void setNullCipherNotificationsEnabled_lackingPermissions_throwsException() {
+ setModemSupportsNullCipherNotification(true);
+ doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doThrow(SecurityException.class).when(mPhoneInterfaceManager).enforceModifyPermission();
+
+ assertThrows(SecurityException.class, () ->
+ mPhoneInterfaceManager.setNullCipherNotificationsEnabled(true));
+ }
+
+ @Test
+ public void isNullCipherNotificationsEnabled_allReqsMet_returnsTrue() {
+ setModemSupportsNullCipherNotification(true);
+ doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+ doReturn(true).when(mPhone).getNullCipherNotificationsPreferenceEnabled();
+
+ assertTrue(mPhoneInterfaceManager.isNullCipherNotificationsEnabled());
+ }
+
+ @Test
+ public void isNullCipherNotificationsEnabled_lackingNecessaryHal_throwsException() {
+ setModemSupportsNullCipherNotification(true);
+ doReturn(102).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+
+ assertThrows(UnsupportedOperationException.class, () ->
+ mPhoneInterfaceManager.isNullCipherNotificationsEnabled());
+ }
+
+ @Test
+ public void isNullCipherNotificationsEnabled_lackingModemSupport_throwsException() {
+ setModemSupportsNullCipherNotification(false);
+ doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doNothing().when(mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+
+ assertThrows(UnsupportedOperationException.class, () ->
+ mPhoneInterfaceManager.isNullCipherNotificationsEnabled());
+ }
+
+ @Test
+ public void isNullCipherNotificationsEnabled_lackingPermissions_throwsException() {
+ setModemSupportsNullCipherNotification(true);
+ doReturn(202).when(mPhoneInterfaceManager).getHalVersion(anyInt());
+ doThrow(SecurityException.class).when(
+ mPhoneInterfaceManager).enforceReadPrivilegedPermission(anyString());
+
+ assertThrows(SecurityException.class, () ->
+ mPhoneInterfaceManager.isNullCipherNotificationsEnabled());
+ }
+
+ private void setModemSupportsNullCipherNotification(boolean enable) {
+ doReturn(enable).when(mPhone).isNullCipherNotificationSupported();
+ doReturn(mPhone).when(mPhoneInterfaceManager).getDefaultPhone();
+ }
+
/**
* Verify getCarrierRestrictionStatus throws exception for invalid caller package name.
*/
@@ -287,7 +423,8 @@
*/
@Test
public void getCarrierRestrictionStatus() {
- when(mPhoneInterfaceManager.validateCallerAndGetCarrierId(anyString())).thenReturn(1);
+ when(mPhoneInterfaceManager.validateCallerAndGetCarrierIds(anyString())).thenReturn(
+ Collections.singleton(1));
mPhoneInterfaceManager.getCarrierRestrictionStatus(mIIntegerConsumer,
"com.test.package");
}
@@ -296,37 +433,18 @@
public void notifyEnableDataWithAppOps_enableByUser_doNoteOp() {
mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
String packageName = "INVALID_PACKAGE";
- String error = "";
- try {
- mPhoneInterfaceManager.setDataEnabledForReason(1,
- TelephonyManager.DATA_ENABLED_REASON_USER, true, packageName);
- } catch (SecurityException expected) {
- // The test doesn't have access to note the op, but we're just interested that it makes
- // the attempt.
- error = expected.getMessage();
- }
-
- String appop = "ENABLE_MOBILE_DATA_BY_USER";
- assertTrue("expected error to contain " + packageName + " but it didn't: " + error,
- error.contains(packageName));
- assertTrue("expected error to contain " + appop + " but it didn't: " + error,
- error.contains(appop));
+ mPhoneInterfaceManager.setDataEnabledForReason(1,
+ TelephonyManager.DATA_ENABLED_REASON_USER, true, packageName);
+ verify(mAppOps).noteOpNoThrow(eq(AppOpsManager.OPSTR_ENABLE_MOBILE_DATA_BY_USER), anyInt(),
+ eq(packageName), isNull(), isNull());
}
@Test
public void notifyEnableDataWithAppOps_enableByCarrier_doNotNoteOp() {
mSetFlagsRule.enableFlags(Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER);
String packageName = "INVALID_PACKAGE";
- String error = "";
- try {
- mPhoneInterfaceManager.setDataEnabledForReason(1,
- TelephonyManager.DATA_ENABLED_REASON_CARRIER, true, packageName);
- } catch (SecurityException expected) {
- // The test doesn't have access to note the op, but we're just interested that it makes
- // the attempt.
- error = expected.getMessage();
- }
- assertEquals("Expected error to be empty, was " + error, error, "");
+ verify(mAppOps, never()).noteOpNoThrow(eq(AppOpsManager.OPSTR_ENABLE_MOBILE_DATA_BY_USER),
+ anyInt(), eq(packageName), isNull(), isNull());
}
@Test
@@ -359,4 +477,57 @@
}
assertEquals("Expected error to be empty, was " + error, error, "");
}
+
+ @Test
+ @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
+ public void testWithTelephonyFeatureAndCompatChanges() throws Exception {
+ doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ mPhoneInterfaceManager.setFeatureFlags(mFeatureFlags);
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+
+ try {
+ // FEATURE_TELEPHONY_CALLING
+ mPhoneInterfaceManager.handlePinMmiForSubscriber(1, "123456789");
+
+ // FEATURE_TELEPHONY_RADIO_ACCESS
+ mPhoneInterfaceManager.toggleRadioOnOffForSubscriber(1);
+ } catch (Exception e) {
+ fail("Not expect exception " + e.getMessage());
+ }
+ }
+
+ @Test
+ @EnableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
+ public void testWithoutTelephonyFeatureAndCompatChanges() throws Exception {
+ // telephony features is not defined, expect UnsupportedOperationException.
+ doReturn(false).when(mPackageManager).hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_CALLING);
+ doReturn(false).when(mPackageManager).hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS);
+ mPhoneInterfaceManager.setPackageManager(mPackageManager);
+ doReturn(true).when(mFeatureFlags).enforceTelephonyFeatureMappingForPublicApis();
+ mPhoneInterfaceManager.setFeatureFlags(mFeatureFlags);
+ doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
+
+ assertThrows(UnsupportedOperationException.class,
+ () -> mPhoneInterfaceManager.handlePinMmiForSubscriber(1, "123456789"));
+ assertThrows(UnsupportedOperationException.class,
+ () -> mPhoneInterfaceManager.toggleRadioOnOffForSubscriber(1));
+ }
+
+ @Test
+ public void testGetCurrentPackageNameWithNoKnownPackage() throws Exception {
+ Field field = PhoneInterfaceManager.class.getDeclaredField("mApp");
+ field.setAccessible(true);
+ Field modifiersField = Field.class.getDeclaredField("accessFlags");
+ modifiersField.setAccessible(true);
+ modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
+ field.set(mPhoneInterfaceManager, mPhoneGlobals);
+
+ doReturn(mPackageManager).when(mPhoneGlobals).getPackageManager();
+ doReturn(null).when(mPackageManager).getPackagesForUid(anyInt());
+
+ String packageName = mPhoneInterfaceManager.getCurrentPackageName();
+ assertEquals(null, packageName);
+ }
}
diff --git a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
index 57f9f6b..fe13d56 100644
--- a/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
+++ b/tests/src/com/android/phone/RcsProvisioningMonitorTest.java
@@ -61,10 +61,11 @@
import android.telephony.ims.aidl.IRcsConfigCallback;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
import android.util.Log;
+import androidx.test.filters.SmallTest;
+
import com.android.ims.FeatureConnector;
import com.android.ims.RcsFeatureManager;
import com.android.internal.telephony.ITelephony;
diff --git a/tests/src/com/android/phone/ServiceStateProviderTest.java b/tests/src/com/android/phone/ServiceStateProviderTest.java
index 4bbde79..ab26e94 100644
--- a/tests/src/com/android/phone/ServiceStateProviderTest.java
+++ b/tests/src/com/android/phone/ServiceStateProviderTest.java
@@ -64,9 +64,9 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.test.mock.MockContentResolver;
-import android.test.suitebuilder.annotation.SmallTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
import libcore.junit.util.compat.CoreCompatChangeRule;
@@ -123,6 +123,11 @@
public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
throw new TestNotifierException();
}
+ @Override
+ public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork,
+ int userHandle) {
+ throw new TestNotifierException();
+ }
};
doReturn(mContentResolver).when(mContext).getContentResolver();
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessControllerTest.java
index 84c233a..16a256d 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessControllerTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessControllerTest.java
@@ -80,13 +80,14 @@
SatelliteOnDeviceAccessController accessController = null;
try {
accessController = SatelliteOnDeviceAccessController.create(mFile);
+ int s2Level = accessController.getS2Level();
// Verify an edge cell of range 1 not in the output file
S2CellId s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1000, 999));
S2LatLng s2LatLng = s2CellId.toLatLng();
SatelliteOnDeviceAccessController.LocationToken locationToken =
- accessController.createLocationTokenForLatLng(
- s2LatLng.latDegrees(), s2LatLng.lngDegrees());
+ SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ s2LatLng.latDegrees(), s2LatLng.lngDegrees(), s2Level);
boolean isAllowed = accessController.isSatCommunicationAllowedAtLocation(locationToken);
assertTrue(isAllowed != isAllowedList);
@@ -96,8 +97,8 @@
s2LatLng = s2CellId.toLatLng();
// Lookup using location token
- locationToken = accessController.createLocationTokenForLatLng(
- s2LatLng.latDegrees(), s2LatLng.lngDegrees());
+ locationToken = SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ s2LatLng.latDegrees(), s2LatLng.lngDegrees(), s2Level);
isAllowed = accessController.isSatCommunicationAllowedAtLocation(locationToken);
assertTrue(isAllowed == isAllowedList);
}
@@ -105,8 +106,8 @@
// Verify the middle cell not in the output file
s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1000, 2000));
s2LatLng = s2CellId.toLatLng();
- locationToken = accessController.createLocationTokenForLatLng(
- s2LatLng.latDegrees(), s2LatLng.lngDegrees());
+ locationToken = SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ s2LatLng.latDegrees(), s2LatLng.lngDegrees(), s2Level);
isAllowed = accessController.isSatCommunicationAllowedAtLocation(locationToken);
assertTrue(isAllowed != isAllowedList);
@@ -114,8 +115,8 @@
for (int suffix = 2001; suffix < 3000; suffix++) {
s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1000, suffix));
s2LatLng = s2CellId.toLatLng();
- locationToken = accessController.createLocationTokenForLatLng(
- s2LatLng.latDegrees(), s2LatLng.lngDegrees());
+ locationToken = SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ s2LatLng.latDegrees(), s2LatLng.lngDegrees(), s2Level);
isAllowed = accessController.isSatCommunicationAllowedAtLocation(locationToken);
assertTrue(isAllowed == isAllowedList);
}
@@ -123,16 +124,16 @@
// Verify an edge cell of range 2 not in the output file
s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1000, 3000));
s2LatLng = s2CellId.toLatLng();
- locationToken = accessController.createLocationTokenForLatLng(
- s2LatLng.latDegrees(), s2LatLng.lngDegrees());
+ locationToken = SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ s2LatLng.latDegrees(), s2LatLng.lngDegrees(), s2Level);
isAllowed = accessController.isSatCommunicationAllowedAtLocation(locationToken);
assertTrue(isAllowed != isAllowedList);
// Verify an edge cell of range 3 not in the output file
s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1001, 999));
s2LatLng = s2CellId.toLatLng();
- locationToken = accessController.createLocationTokenForLatLng(
- s2LatLng.latDegrees(), s2LatLng.lngDegrees());
+ locationToken = SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ s2LatLng.latDegrees(), s2LatLng.lngDegrees(), s2Level);
isAllowed = accessController.isSatCommunicationAllowedAtLocation(locationToken);
assertTrue(isAllowed != isAllowedList);
@@ -140,8 +141,8 @@
for (int suffix = 1000; suffix < 2000; suffix++) {
s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1001, suffix));
s2LatLng = s2CellId.toLatLng();
- locationToken = accessController.createLocationTokenForLatLng(
- s2LatLng.latDegrees(), s2LatLng.lngDegrees());
+ locationToken = SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ s2LatLng.latDegrees(), s2LatLng.lngDegrees(), s2Level);
isAllowed = accessController.isSatCommunicationAllowedAtLocation(locationToken);
assertTrue(isAllowed == isAllowedList);
}
@@ -149,8 +150,8 @@
// Verify an edge cell of range 3 not in the output file
s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1001, 2000));
s2LatLng = s2CellId.toLatLng();
- locationToken = accessController.createLocationTokenForLatLng(
- s2LatLng.latDegrees(), s2LatLng.lngDegrees());
+ locationToken = SatelliteOnDeviceAccessController.createLocationTokenForLatLng(
+ s2LatLng.latDegrees(), s2LatLng.lngDegrees(), s2Level);
isAllowed = accessController.isSatCommunicationAllowedAtLocation(locationToken);
assertTrue(isAllowed != isAllowedList);
} catch (Exception ex) {
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
new file mode 100644
index 0000000..aabc0fb
--- /dev/null
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
@@ -0,0 +1,688 @@
+/*
+ * 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.satellite.accesscontrol;
+
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_CONFIG_DATA_UPDATED;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.GOOGLE_US_SAN_SAT_S2_FILE_NAME;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.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.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+import android.os.AsyncResult;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ResultReceiver;
+import android.telecom.TelecomManager;
+import android.telephony.satellite.SatelliteManager;
+import android.testing.TestableLooper;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyCountryDetector;
+import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.SatelliteConfig;
+import com.android.internal.telephony.satellite.SatelliteConfigParser;
+import com.android.internal.telephony.satellite.SatelliteController;
+import com.android.internal.telephony.satellite.SatelliteModemInterface;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/** Unit test for {@link SatelliteAccessController} */
+@RunWith(AndroidJUnit4.class)
+public class SatelliteAccessControllerTest {
+ private static final String TAG = "SatelliteAccessControllerTest";
+ private static final String[] TEST_SATELLITE_COUNTRY_CODES = {"US", "CA", "UK"};
+ private static final String TEST_SATELLITE_S2_FILE = "sat_s2_file.dat";
+ private static final boolean TEST_SATELLITE_ALLOW = true;
+ private static final int TEST_LOCATION_FRESH_DURATION_SECONDS = 10;
+ private static final long TEST_LOCATION_FRESH_DURATION_NANOS =
+ TimeUnit.SECONDS.toNanos(TEST_LOCATION_FRESH_DURATION_SECONDS);
+ private static final long TIMEOUT = 500;
+ private static final List<String> EMPTY_STRING_LIST = new ArrayList<>();
+ private static final List<String> LOCATION_PROVIDERS =
+ listOf(LocationManager.NETWORK_PROVIDER, LocationManager.GPS_PROVIDER);
+ private static final int SUB_ID = 0;
+
+ @Mock
+ private LocationManager mMockLocationManager;
+ @Mock
+ private TelecomManager mMockTelecomManager;
+ @Mock
+ private TelephonyCountryDetector mMockCountryDetector;
+ @Mock
+ private SatelliteController mMockSatelliteController;
+ @Mock
+ private SatelliteModemInterface mMockSatelliteModemInterface;
+ @Mock
+ private Context mMockContext;
+ @Mock
+ private Phone mMockPhone;
+ @Mock
+ private Phone mMockPhone2;
+ @Mock
+ private FeatureFlags mMockFeatureFlags;
+ @Mock
+ private Resources mMockResources;
+ @Mock
+ private SatelliteOnDeviceAccessController mMockSatelliteOnDeviceAccessController;
+ @Mock
+ Location mMockLocation0;
+ @Mock
+ Location mMockLocation1;
+ @Mock
+ File mMockSatS2File;
+ @Mock
+ SharedPreferences mMockSharedPreferences;
+ @Mock
+ private SharedPreferences.Editor mMockSharedPreferencesEditor;
+
+ private Looper mLooper;
+ private TestableLooper mTestableLooper;
+ private Phone[] mPhones;
+ private TestSatelliteAccessController mSatelliteAccessControllerUT;
+
+ @Captor
+ private ArgumentCaptor<CancellationSignal> mLocationRequestCancellationSignalCaptor;
+ @Captor
+ private ArgumentCaptor<Consumer<Location>> mLocationRequestConsumerCaptor;
+ @Captor
+ private ArgumentCaptor<Handler> mConfigUpdateHandlerCaptor;
+ @Captor
+ private ArgumentCaptor<Integer> mConfigUpdateIntCaptor;
+ @Captor
+ private ArgumentCaptor<Object> mConfigUpdateObjectCaptor;
+ private boolean mQueriedSatelliteAllowed = false;
+ private int mQueriedSatelliteAllowedResultCode = SATELLITE_RESULT_SUCCESS;
+ private Semaphore mSatelliteAllowedSemaphore = new Semaphore(0);
+ private ResultReceiver mSatelliteAllowedReceiver = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mQueriedSatelliteAllowedResultCode = resultCode;
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
+ mQueriedSatelliteAllowed = resultData.getBoolean(
+ KEY_SATELLITE_COMMUNICATION_ALLOWED);
+ } else {
+ logd("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist.");
+ mQueriedSatelliteAllowed = false;
+ }
+ } else {
+ logd("mSatelliteAllowedReceiver: resultCode=" + resultCode);
+ mQueriedSatelliteAllowed = false;
+ }
+ try {
+ mSatelliteAllowedSemaphore.release();
+ } catch (Exception ex) {
+ fail("mSatelliteAllowedReceiver: Got exception in releasing semaphore, ex=" + ex);
+ }
+ }
+ };
+
+ @Before
+ public void setUp() throws Exception {
+ logd("setUp");
+ MockitoAnnotations.initMocks(this);
+
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ HandlerThread handlerThread = new HandlerThread("SatelliteAccessControllerTest");
+ handlerThread.start();
+ mLooper = handlerThread.getLooper();
+ mTestableLooper = new TestableLooper(mLooper);
+ when(mMockContext.getSystemServiceName(LocationManager.class)).thenReturn(
+ Context.LOCATION_SERVICE);
+ when(mMockContext.getSystemServiceName(TelecomManager.class)).thenReturn(
+ Context.TELECOM_SERVICE);
+ when(mMockContext.getSystemService(LocationManager.class)).thenReturn(
+ mMockLocationManager);
+ when(mMockContext.getSystemService(TelecomManager.class)).thenReturn(
+ mMockTelecomManager);
+ mPhones = new Phone[]{mMockPhone, mMockPhone2};
+ replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ replaceInstance(SatelliteController.class, "sInstance", null,
+ mMockSatelliteController);
+ replaceInstance(SatelliteModemInterface.class, "sInstance", null,
+ mMockSatelliteModemInterface);
+ replaceInstance(TelephonyCountryDetector.class, "sInstance", null,
+ mMockCountryDetector);
+ when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockResources.getStringArray(
+ com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
+ .thenReturn(TEST_SATELLITE_COUNTRY_CODES);
+ when(mMockResources.getBoolean(
+ com.android.internal.R.bool.config_oem_enabled_satellite_access_allow))
+ .thenReturn(TEST_SATELLITE_ALLOW);
+ when(mMockResources.getString(
+ com.android.internal.R.string.config_oem_enabled_satellite_s2cell_file))
+ .thenReturn(TEST_SATELLITE_S2_FILE);
+ when(mMockResources.getInteger(com.android.internal.R.integer
+ .config_oem_enabled_satellite_location_fresh_duration))
+ .thenReturn(TEST_LOCATION_FRESH_DURATION_SECONDS);
+
+ when(mMockLocationManager.getProviders(true)).thenReturn(LOCATION_PROVIDERS);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER))
+ .thenReturn(mMockLocation0);
+ when(mMockLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER))
+ .thenReturn(mMockLocation1);
+ when(mMockLocation0.getLatitude()).thenReturn(0.0);
+ when(mMockLocation0.getLongitude()).thenReturn(0.0);
+ when(mMockLocation1.getLatitude()).thenReturn(1.0);
+ when(mMockLocation1.getLongitude()).thenReturn(1.0);
+ when(mMockSatelliteOnDeviceAccessController.isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class))).thenReturn(true);
+
+ when(mMockContext.getSharedPreferences(anyString(), anyInt())).thenReturn(
+ mMockSharedPreferences);
+ when(mMockSharedPreferences.getBoolean(anyString(), anyBoolean())).thenReturn(true);
+ when(mMockSharedPreferences.getStringSet(anyString(), any()))
+ .thenReturn(Set.of(TEST_SATELLITE_COUNTRY_CODES));
+ doReturn(mMockSharedPreferencesEditor).when(mMockSharedPreferences).edit();
+ doReturn(mMockSharedPreferencesEditor).when(mMockSharedPreferencesEditor)
+ .putBoolean(anyString(), anyBoolean());
+ doReturn(mMockSharedPreferencesEditor).when(mMockSharedPreferencesEditor)
+ .putStringSet(anyString(), any());
+
+ mSatelliteAccessControllerUT = new TestSatelliteAccessController(mMockContext,
+ mMockFeatureFlags, mLooper, mMockLocationManager, mMockTelecomManager,
+ mMockSatelliteOnDeviceAccessController, mMockSatS2File);
+ mTestableLooper.processAllMessages();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logd("tearDown");
+ if (mTestableLooper != null) {
+ mTestableLooper.destroy();
+ mTestableLooper = null;
+ }
+
+ if (mLooper != null) {
+ mLooper.quit();
+ mLooper = null;
+ }
+ }
+
+ @Test
+ public void testGetInstance() {
+ SatelliteAccessController inst1 =
+ SatelliteAccessController.getOrCreateInstance(mMockContext, mMockFeatureFlags);
+ SatelliteAccessController inst2 =
+ SatelliteAccessController.getOrCreateInstance(mMockContext, mMockFeatureFlags);
+ assertEquals(inst1, inst2);
+ }
+
+ @Test
+ public void testRequestIsSatelliteCommunicationAllowedForCurrentLocation() throws Exception {
+ // OEM-enabled satellite is not supported
+ when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, mQueriedSatelliteAllowedResultCode);
+
+ // OEM-enabled satellite is supported
+ when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ // Satellite is not supported
+ setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
+ clearAllInvocations();
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertFalse(mQueriedSatelliteAllowed);
+
+ // Failed to query whether satellite is supported or not
+ setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_MODEM_ERROR);
+ clearAllInvocations();
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_MODEM_ERROR, mQueriedSatelliteAllowedResultCode);
+
+ // Network country codes are available.
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ clearAllInvocations();
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(listOf("US", "CA"));
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // Network country codes are not available. TelecomManager.isInEmergencyCall() returns true.
+ // On-device access controller will be used. Last known location is available and fresh.
+ clearAllInvocations();
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(EMPTY_STRING_LIST);
+ when(mMockTelecomManager.isInEmergencyCall()).thenReturn(true);
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos = TEST_LOCATION_FRESH_DURATION_NANOS + 1;
+ when(mMockLocation0.getElapsedRealtimeNanos()).thenReturn(2L);
+ when(mMockLocation1.getElapsedRealtimeNanos()).thenReturn(0L);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ assertTrue(
+ mSatelliteAccessControllerUT.isKeepOnDeviceAccessControllerResourcesTimerStarted());
+ verify(mMockSatelliteOnDeviceAccessController).isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // Move time forward and verify resources are cleaned up
+ clearAllInvocations();
+ mTestableLooper.moveTimeForward(mSatelliteAccessControllerUT
+ .getKeepOnDeviceAccessControllerResourcesTimeoutMillis());
+ mTestableLooper.processAllMessages();
+ assertFalse(
+ mSatelliteAccessControllerUT.isKeepOnDeviceAccessControllerResourcesTimerStarted());
+ assertTrue(mSatelliteAccessControllerUT.isSatelliteOnDeviceAccessControllerReset());
+ verify(mMockSatelliteOnDeviceAccessController).close();
+
+ // Restore SatelliteOnDeviceAccessController for next verification
+ mSatelliteAccessControllerUT.setSatelliteOnDeviceAccessController(
+ mMockSatelliteOnDeviceAccessController);
+
+ // Network country codes are not available. TelecomManager.isInEmergencyCall() returns
+ // false. Phone0 is in ECM. On-device access controller will be used. Last known location is
+ // not fresh.
+ clearAllInvocations();
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(EMPTY_STRING_LIST);
+ when(mMockTelecomManager.isInEmergencyCall()).thenReturn(false);
+ when(mMockPhone.isInEcm()).thenReturn(true);
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos = TEST_LOCATION_FRESH_DURATION_NANOS + 1;
+ when(mMockLocation0.getElapsedRealtimeNanos()).thenReturn(0L);
+ when(mMockLocation1.getElapsedRealtimeNanos()).thenReturn(0L);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ assertFalse(
+ mSatelliteAccessControllerUT.isKeepOnDeviceAccessControllerResourcesTimerStarted());
+ verify(mMockLocationManager).getCurrentLocation(eq(LocationManager.GPS_PROVIDER),
+ any(LocationRequest.class), mLocationRequestCancellationSignalCaptor.capture(),
+ any(Executor.class), mLocationRequestConsumerCaptor.capture());
+ assertTrue(mSatelliteAccessControllerUT.isWaitForCurrentLocationTimerStarted());
+ sendLocationRequestResult(mMockLocation0);
+ assertFalse(mSatelliteAccessControllerUT.isWaitForCurrentLocationTimerStarted());
+ // The LocationToken should be already in the cache
+ verify(mMockSatelliteOnDeviceAccessController, never()).isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // Timed out to wait for current location. No cached country codes.
+ clearAllInvocations();
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(EMPTY_STRING_LIST);
+ when(mMockTelecomManager.isInEmergencyCall()).thenReturn(false);
+ when(mMockPhone.isInEcm()).thenReturn(true);
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos = TEST_LOCATION_FRESH_DURATION_NANOS + 1;
+ when(mMockLocation0.getElapsedRealtimeNanos()).thenReturn(0L);
+ when(mMockLocation1.getElapsedRealtimeNanos()).thenReturn(0L);
+ when(mMockCountryDetector.getCachedLocationCountryIsoInfo()).thenReturn(new Pair<>("", 0L));
+ when(mMockCountryDetector.getCachedNetworkCountryIsoInfo()).thenReturn(new HashMap<>());
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ assertFalse(
+ mSatelliteAccessControllerUT.isKeepOnDeviceAccessControllerResourcesTimerStarted());
+ verify(mMockLocationManager).getCurrentLocation(anyString(), any(LocationRequest.class),
+ any(CancellationSignal.class), any(Executor.class), any(Consumer.class));
+ assertTrue(mSatelliteAccessControllerUT.isWaitForCurrentLocationTimerStarted());
+ // Timed out
+ mTestableLooper.moveTimeForward(
+ mSatelliteAccessControllerUT.getWaitForCurrentLocationTimeoutMillis());
+ mTestableLooper.processAllMessages();
+ assertFalse(mSatelliteAccessControllerUT.isWaitForCurrentLocationTimerStarted());
+ verify(mMockSatelliteOnDeviceAccessController, never()).isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+ verifyCountryDetectorApisCalled();
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS,
+ mQueriedSatelliteAllowedResultCode);
+ assertFalse(mQueriedSatelliteAllowed);
+
+ // Network country codes are not available. TelecomManager.isInEmergencyCall() returns
+ // false. No phone is in ECM. Last known location is not fresh. Cached country codes should
+ // be used for verifying satellite allow. No cached country codes are available.
+ clearAllInvocations();
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(EMPTY_STRING_LIST);
+ when(mMockCountryDetector.getCachedLocationCountryIsoInfo()).thenReturn(new Pair<>("", 0L));
+ when(mMockCountryDetector.getCachedNetworkCountryIsoInfo()).thenReturn(new HashMap<>());
+ when(mMockTelecomManager.isInEmergencyCall()).thenReturn(false);
+ when(mMockPhone.isInEcm()).thenReturn(false);
+ when(mMockPhone2.isInEcm()).thenReturn(false);
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos = TEST_LOCATION_FRESH_DURATION_NANOS + 1;
+ when(mMockLocation0.getElapsedRealtimeNanos()).thenReturn(0L);
+ when(mMockLocation1.getElapsedRealtimeNanos()).thenReturn(0L);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockLocationManager, never()).getCurrentLocation(anyString(),
+ any(LocationRequest.class), any(CancellationSignal.class), any(Executor.class),
+ any(Consumer.class));
+ verify(mMockSatelliteOnDeviceAccessController, never()).isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+ verifyCountryDetectorApisCalled();
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertFalse(mQueriedSatelliteAllowed);
+
+ // Network country codes are not available. TelecomManager.isInEmergencyCall() returns
+ // false. No phone is in ECM. Last known location is not fresh. Cached country codes should
+ // be used for verifying satellite allow. Cached country codes are available.
+ clearAllInvocations();
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(EMPTY_STRING_LIST);
+ when(mMockCountryDetector.getCachedLocationCountryIsoInfo())
+ .thenReturn(new Pair<>("US", 5L));
+ Map<String, Long> cachedNetworkCountryCodes = new HashMap<>();
+ cachedNetworkCountryCodes.put("UK", 1L);
+ cachedNetworkCountryCodes.put("US", 3L);
+ when(mMockCountryDetector.getCachedNetworkCountryIsoInfo())
+ .thenReturn(cachedNetworkCountryCodes);
+ when(mMockTelecomManager.isInEmergencyCall()).thenReturn(false);
+ when(mMockPhone.isInEcm()).thenReturn(false);
+ when(mMockPhone2.isInEcm()).thenReturn(false);
+ mSatelliteAccessControllerUT.elapsedRealtimeNanos = TEST_LOCATION_FRESH_DURATION_NANOS + 1;
+ when(mMockLocation0.getElapsedRealtimeNanos()).thenReturn(0L);
+ when(mMockLocation1.getElapsedRealtimeNanos()).thenReturn(0L);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockLocationManager, never()).getCurrentLocation(anyString(),
+ any(LocationRequest.class), any(CancellationSignal.class), any(Executor.class),
+ any(Consumer.class));
+ verify(mMockSatelliteOnDeviceAccessController, never()).isSatCommunicationAllowedAtLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+ verifyCountryDetectorApisCalled();
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertTrue(mQueriedSatelliteAllowed);
+ }
+
+ @Test
+ public void testUpdateSatelliteConfigData() throws Exception {
+ verify(mMockSatelliteController).registerForConfigUpdateChanged(
+ mConfigUpdateHandlerCaptor.capture(), mConfigUpdateIntCaptor.capture(),
+ mConfigUpdateObjectCaptor.capture());
+
+ assertSame(mConfigUpdateHandlerCaptor.getValue(), mSatelliteAccessControllerUT);
+ assertSame(mConfigUpdateIntCaptor.getValue(), EVENT_CONFIG_DATA_UPDATED);
+ assertSame(mConfigUpdateObjectCaptor.getValue(), mMockContext);
+
+ // These APIs are executed during loadRemoteConfigs
+ verify(mMockSharedPreferences, times(1)).getStringSet(anyString(), any());
+ verify(mMockSharedPreferences, times(1)).getBoolean(anyString(), anyBoolean());
+
+ // satelliteConfig is null
+ SatelliteConfigParser spyConfigParser =
+ spy(new SatelliteConfigParser("test".getBytes()));
+ doReturn(spyConfigParser).when(mMockSatelliteController).getSatelliteConfigParser();
+ assertNull(spyConfigParser.getConfig());
+
+ sendConfigUpdateChangedEvent(mMockContext);
+ verify(mMockSharedPreferences, never()).edit();
+
+ // satelliteConfig has invalid country codes
+ SatelliteConfig mockConfig = mock(SatelliteConfig.class);
+ doReturn(List.of("USA", "JAP")).when(mockConfig).getDeviceSatelliteCountryCodes();
+ doReturn(mockConfig).when(mMockSatelliteController).getSatelliteConfig();
+ doReturn(false).when(mockConfig).isSatelliteDataForAllowedRegion();
+
+ sendConfigUpdateChangedEvent(mMockContext);
+ verify(mMockSharedPreferences, never()).edit();
+
+ // satelliteConfig does not have is_allow_access_control data
+ doReturn(List.of(TEST_SATELLITE_COUNTRY_CODES))
+ .when(mockConfig).getDeviceSatelliteCountryCodes();
+ doReturn(null).when(mockConfig).isSatelliteDataForAllowedRegion();
+
+ sendConfigUpdateChangedEvent(mMockContext);
+ verify(mMockSharedPreferences, never()).edit();
+
+ // satelliteConfig doesn't have S2CellFile
+ File mockFile = mock(File.class);
+ doReturn(false).when(mockFile).exists();
+ doReturn(List.of(TEST_SATELLITE_COUNTRY_CODES))
+ .when(mockConfig).getDeviceSatelliteCountryCodes();
+ doReturn(true).when(mockConfig).isSatelliteDataForAllowedRegion();
+ doReturn(mockFile).when(mockConfig).getSatelliteS2CellFile(mMockContext);
+
+ sendConfigUpdateChangedEvent(mMockContext);
+ verify(mMockSharedPreferences, never()).edit();
+
+ // satelliteConfig has valid data
+ doReturn(mockConfig).when(mMockSatelliteController).getSatelliteConfig();
+ File testS2File = mSatelliteAccessControllerUT
+ .getTestSatelliteS2File(GOOGLE_US_SAN_SAT_S2_FILE_NAME);
+ doReturn(List.of(TEST_SATELLITE_COUNTRY_CODES))
+ .when(mockConfig).getDeviceSatelliteCountryCodes();
+ doReturn(true).when(mockConfig).isSatelliteDataForAllowedRegion();
+ doReturn(testS2File).when(mockConfig).getSatelliteS2CellFile(mMockContext);
+
+ sendConfigUpdateChangedEvent(mMockContext);
+ verify(mMockSharedPreferences, times(2)).edit();
+ }
+
+ private void sendConfigUpdateChangedEvent(Context context) {
+ Message msg = mSatelliteAccessControllerUT.obtainMessage(EVENT_CONFIG_DATA_UPDATED);
+ msg.obj = new AsyncResult(context, SATELLITE_RESULT_SUCCESS, null);
+ msg.sendToTarget();
+ mTestableLooper.processAllMessages();
+ }
+
+ private void clearAllInvocations() {
+ clearInvocations(mMockSatelliteController);
+ clearInvocations(mMockSatelliteOnDeviceAccessController);
+ clearInvocations(mMockLocationManager);
+ clearInvocations(mMockCountryDetector);
+ }
+
+ private void verifyCountryDetectorApisCalled() {
+ verify(mMockCountryDetector).getCurrentNetworkCountryIso();
+ verify(mMockCountryDetector).getCachedLocationCountryIsoInfo();
+ verify(mMockCountryDetector).getCachedLocationCountryIsoInfo();
+ }
+
+ private boolean waitForRequestIsSatelliteAllowedForCurrentLocationResult(Semaphore semaphore,
+ int expectedNumberOfEvents) {
+ for (int i = 0; i < expectedNumberOfEvents; i++) {
+ try {
+ if (!semaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) {
+ logd("Timeout to receive "
+ + "requestIsCommunicationAllowedForCurrentLocation()"
+ + " callback");
+ return false;
+ }
+ } catch (Exception ex) {
+ logd("waitForRequestIsSatelliteSupportedResult: Got exception=" + ex);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void sendLocationRequestResult(Location location) {
+ mLocationRequestConsumerCaptor.getValue().accept(location);
+ mTestableLooper.processAllMessages();
+ }
+
+ private void setUpResponseForRequestIsSatelliteSupported(
+ boolean isSatelliteSupported, @SatelliteManager.SatelliteResult int error) {
+ doAnswer(invocation -> {
+ ResultReceiver resultReceiver = invocation.getArgument(1);
+ if (error == SATELLITE_RESULT_SUCCESS) {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, isSatelliteSupported);
+ resultReceiver.send(error, bundle);
+ } else {
+ resultReceiver.send(error, Bundle.EMPTY);
+ }
+ return null;
+ }).when(mMockSatelliteController).requestIsSatelliteSupported(anyInt(),
+ any(ResultReceiver.class));
+ }
+
+ @SafeVarargs
+ private static <E> List<E> listOf(E... values) {
+ return Arrays.asList(values);
+ }
+
+ private static void logd(String message) {
+ Log.d(TAG, message);
+ }
+
+ 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 static class TestSatelliteAccessController extends SatelliteAccessController {
+ public long elapsedRealtimeNanos = 0;
+
+ /**
+ * Create a SatelliteAccessController instance.
+ *
+ * @param context The context associated with the
+ * {@link SatelliteAccessController} instance.
+ * @param featureFlags The FeatureFlags that are supported.
+ * @param looper The Looper to run the SatelliteAccessController
+ * on.
+ * @param locationManager The LocationManager for querying current
+ * location of the
+ * device.
+ * @param satelliteOnDeviceAccessController The on-device satellite access controller
+ * instance.
+ */
+ protected TestSatelliteAccessController(Context context, FeatureFlags featureFlags,
+ Looper looper, LocationManager locationManager, TelecomManager telecomManager,
+ SatelliteOnDeviceAccessController satelliteOnDeviceAccessController,
+ File s2CellFile) {
+ super(context, featureFlags, looper, locationManager, telecomManager,
+ satelliteOnDeviceAccessController, s2CellFile);
+ }
+
+ @Override
+ protected long getElapsedRealtimeNanos() {
+ return elapsedRealtimeNanos;
+ }
+
+ public boolean isKeepOnDeviceAccessControllerResourcesTimerStarted() {
+ return hasMessages(EVENT_KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT);
+ }
+
+ public boolean isSatelliteOnDeviceAccessControllerReset() {
+ synchronized (mLock) {
+ return (mSatelliteOnDeviceAccessController == null);
+ }
+ }
+
+ public void setSatelliteOnDeviceAccessController(
+ @Nullable SatelliteOnDeviceAccessController accessController) {
+ synchronized (mLock) {
+ mSatelliteOnDeviceAccessController = accessController;
+ }
+ }
+
+ public long getKeepOnDeviceAccessControllerResourcesTimeoutMillis() {
+ return KEEP_ON_DEVICE_ACCESS_CONTROLLER_RESOURCES_TIMEOUT_MILLIS;
+ }
+
+ public long getWaitForCurrentLocationTimeoutMillis() {
+ return WAIT_FOR_CURRENT_LOCATION_TIMEOUT_MILLIS;
+ }
+
+ public boolean isWaitForCurrentLocationTimerStarted() {
+ return hasMessages(EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT);
+ }
+ }
+}
diff --git a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApiTest.java b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApiTest.java
new file mode 100644
index 0000000..f7cbc55
--- /dev/null
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApiTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2024 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.satellite.entitlement;
+
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_DISABLED;
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_ENABLED;
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE;
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_PROVISIONING;
+
+import static org.junit.Assert.assertEquals;
+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.anyVararg;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.libraries.entitlement.ServiceEntitlement;
+import com.android.libraries.entitlement.ServiceEntitlementRequest;
+
+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.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class SatelliteEntitlementApiTest {
+ private static final String TEST_URL = "https://test.url";
+ private static final List<String> TEST_PLMN_ALLOWED = Arrays.asList("31026", "302820");
+ private static final String TEST_APP_NAME = "androidSatmode";
+ @Mock
+ Context mContext;
+ @Mock
+ ServiceEntitlement mServiceEntitlement;
+ @Mock
+ CarrierConfigManager mCarrierConfigManager;
+ @Mock
+ TelephonyManager mTelephonyManager;
+ private PersistableBundle mCarrierConfigBundle;
+ private SatelliteEntitlementApi mSatelliteEntitlementAPI;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ doReturn(Context.CARRIER_CONFIG_SERVICE).when(mContext).getSystemServiceName(
+ CarrierConfigManager.class);
+ doReturn(mCarrierConfigManager).when(mContext).getSystemService(
+ Context.CARRIER_CONFIG_SERVICE);
+ mCarrierConfigBundle = new PersistableBundle();
+ doReturn(mCarrierConfigBundle)
+ .when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyVararg());
+ doReturn(Context.TELEPHONY_SERVICE).when(mContext).getSystemServiceName(
+ TelephonyManager.class);
+ doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+ doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
+
+ mSatelliteEntitlementAPI = new SatelliteEntitlementApi(mContext, mCarrierConfigBundle,
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
+
+ mCarrierConfigBundle.putString(
+ CarrierConfigManager.ImsServiceEntitlement.KEY_ENTITLEMENT_SERVER_URL_STRING,
+ TEST_URL);
+ mCarrierConfigBundle.putString(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_APP_NAME_STRING,
+ TEST_APP_NAME);
+
+ Field fieldServiceEntitlement = SatelliteEntitlementApi.class.getDeclaredField(
+ "mServiceEntitlement");
+ fieldServiceEntitlement.setAccessible(true);
+ fieldServiceEntitlement.set(mSatelliteEntitlementAPI, mServiceEntitlement);
+ }
+
+ @Test
+ public void testCheckEntitlementStatus() throws Exception {
+ // Get the EntitlementStatus to DISABLED
+ int expectedEntitlementStatus = SATELLITE_ENTITLEMENT_STATUS_DISABLED;
+ doReturn(getResponse(SATELLITE_ENTITLEMENT_STATUS_DISABLED))
+ .when(mServiceEntitlement)
+ .queryEntitlementStatus(eq(ServiceEntitlement.APP_SATELLITE_ENTITLEMENT), any());
+ SatelliteEntitlementResult result =
+ mSatelliteEntitlementAPI.checkEntitlementStatus();
+ assertNotNull(result);
+ assertEquals(expectedEntitlementStatus, result.getEntitlementStatus());
+ assertTrue(result.getAllowedPLMNList().size() == 0);
+
+ // Get the EntitlementStatus to ENABLED
+ expectedEntitlementStatus = SATELLITE_ENTITLEMENT_STATUS_ENABLED;
+ doReturn(getResponse(SATELLITE_ENTITLEMENT_STATUS_ENABLED))
+ .when(mServiceEntitlement)
+ .queryEntitlementStatus(eq(ServiceEntitlement.APP_SATELLITE_ENTITLEMENT), any());
+ result = mSatelliteEntitlementAPI.checkEntitlementStatus();
+ assertNotNull(result);
+ assertEquals(expectedEntitlementStatus, result.getEntitlementStatus());
+ assertEquals(TEST_PLMN_ALLOWED, result.getAllowedPLMNList());
+
+ // Get the EntitlementStatus to INCOMPATIBLE
+ expectedEntitlementStatus = SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE;
+ doReturn(getResponse(SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE))
+ .when(mServiceEntitlement)
+ .queryEntitlementStatus(eq(ServiceEntitlement.APP_SATELLITE_ENTITLEMENT), any());
+ result = mSatelliteEntitlementAPI.checkEntitlementStatus();
+ assertNotNull(result);
+ assertEquals(expectedEntitlementStatus, result.getEntitlementStatus());
+ assertTrue(result.getAllowedPLMNList().size() == 0);
+
+ // Get the EntitlementStatus to PROVISIONING
+ expectedEntitlementStatus = SATELLITE_ENTITLEMENT_STATUS_PROVISIONING;
+ doReturn(getResponse(SATELLITE_ENTITLEMENT_STATUS_PROVISIONING))
+ .when(mServiceEntitlement)
+ .queryEntitlementStatus(eq(ServiceEntitlement.APP_SATELLITE_ENTITLEMENT), any());
+ result = mSatelliteEntitlementAPI.checkEntitlementStatus();
+ assertNotNull(result);
+ assertEquals(expectedEntitlementStatus, result.getEntitlementStatus());
+ assertTrue(result.getAllowedPLMNList().size() == 0);
+ }
+
+ @Test
+ public void testServiceEntitlementRequest() throws Exception {
+ String expectedAppId = ServiceEntitlement.APP_SATELLITE_ENTITLEMENT;
+ doReturn(getResponse(SATELLITE_ENTITLEMENT_STATUS_DISABLED))
+ .when(mServiceEntitlement)
+ .queryEntitlementStatus(eq(expectedAppId), any());
+ ServiceEntitlementRequest.Builder requestBuilder = ServiceEntitlementRequest.builder();
+ requestBuilder.setAcceptContentType(ServiceEntitlementRequest.ACCEPT_CONTENT_TYPE_JSON);
+ requestBuilder.setAppName(TEST_APP_NAME);
+ ServiceEntitlementRequest expectedRequest = requestBuilder.build();
+
+ mSatelliteEntitlementAPI.checkEntitlementStatus();
+
+ verify(mServiceEntitlement).queryEntitlementStatus(eq(expectedAppId), eq(expectedRequest));
+ }
+
+ private String getResponse(int entitlementStatus) {
+ return "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
+ + "\"EntitlementStatus\":\"" + entitlementStatus + "\""
+ + getPLMNListOrEmpty(entitlementStatus)
+ + "}}";
+ }
+
+ private String getPLMNListOrEmpty(int entitlementStatus) {
+ return entitlementStatus == SATELLITE_ENTITLEMENT_STATUS_ENABLED ? ","
+ + "\"PLMNAllowed\":[{\"PLMN\":\"31026\",\"DataPlanType\":\"unmetered\"},"
+ + "{\"PLMN\":\"302820\",\"DataPlanType\":\"metered\"}]" : "";
+ }
+}
diff --git a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
new file mode 100644
index 0000000..dd9ea65
--- /dev/null
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2024 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.satellite.entitlement;
+
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_ENABLED;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyVararg;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.wifi.WifiInfo;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.testing.TestableLooper;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.TelephonyTestBase;
+import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.satellite.SatelliteController;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
+
+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.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+@RunWith(AndroidJUnit4.class)
+public class SatelliteEntitlementControllerTest extends TelephonyTestBase {
+ private static final String TAG = "SatelliteEntitlementControllerTest";
+ private static final int SUB_ID = 0;
+ private static final int SUB_ID_2 = 1;
+ private static final int[] ACTIVE_SUB_ID = {SUB_ID};
+ private static final int DEFAULT_QUERY_REFRESH_DAY = 30;
+ private static final List<String> PLMN_ALLOWED_LIST = Arrays.asList("31026", "302820");
+ private static final List<String> PLMN_BARRED_LIST = Arrays.asList("12345", "98765");
+ @Mock
+ CarrierConfigManager mCarrierConfigManager;
+ @Mock
+ ConnectivityManager mConnectivityManager;
+ @Mock Network mNetwork;
+ @Mock TelephonyManager mTelephonyManager;
+ @Mock SubscriptionManagerService mMockSubscriptionManagerService;
+ @Mock SatelliteEntitlementApi mSatelliteEntitlementApi;
+ @Mock SatelliteEntitlementResult mSatelliteEntitlementResult;
+ @Mock SatelliteController mSatelliteController;
+ @Mock ExponentialBackoff mExponentialBackoff;
+ private PersistableBundle mCarrierConfigBundle;
+ private TestSatelliteEntitlementController mSatelliteEntitlementController;
+ private Handler mHandler;
+ private TestableLooper mTestableLooper;
+ private List<Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener>>
+ mCarrierConfigChangedListenerList = new ArrayList<>();
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ MockitoAnnotations.initMocks(this);
+
+ replaceInstance(SubscriptionManagerService.class, "sInstance", null,
+ mMockSubscriptionManagerService);
+ replaceInstance(SatelliteController.class, "sInstance", null, mSatelliteController);
+
+ HandlerThread handlerThread = new HandlerThread("SatelliteEntitlementController");
+ handlerThread.start();
+ mHandler = new Handler(handlerThread.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ }
+ };
+ mTestableLooper = new TestableLooper(mHandler.getLooper());
+ doReturn(Context.TELEPHONY_SERVICE).when(mContext).getSystemServiceName(
+ TelephonyManager.class);
+ doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+ doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
+ doReturn(Context.CARRIER_CONFIG_SERVICE).when(mContext).getSystemServiceName(
+ CarrierConfigManager.class);
+ doReturn(mCarrierConfigManager).when(mContext).getSystemService(
+ Context.CARRIER_CONFIG_SERVICE);
+ doAnswer(invocation -> {
+ Executor executor = invocation.getArgument(0);
+ CarrierConfigManager.CarrierConfigChangeListener listener = invocation.getArgument(1);
+ mCarrierConfigChangedListenerList.add(new Pair<>(executor, listener));
+ return null;
+ }).when(mCarrierConfigManager).registerCarrierConfigChangeListener(
+ any(Executor.class),
+ any(CarrierConfigManager.CarrierConfigChangeListener.class));
+ mCarrierConfigBundle = new PersistableBundle();
+ mCarrierConfigBundle.putInt(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT,
+ DEFAULT_QUERY_REFRESH_DAY);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ doReturn(mCarrierConfigBundle)
+ .when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyVararg());
+ doReturn(Context.CONNECTIVITY_SERVICE).when(mContext).getSystemServiceName(
+ ConnectivityManager.class);
+ doReturn(mConnectivityManager).when(mContext).getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ doReturn(mNetwork).when(mConnectivityManager).getActiveNetwork();
+ doReturn(ACTIVE_SUB_ID).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
+ mSatelliteEntitlementController = new TestSatelliteEntitlementController(mContext,
+ mHandler.getLooper(), mSatelliteEntitlementApi);
+ mSatelliteEntitlementController = spy(mSatelliteEntitlementController);
+ doReturn(mSatelliteEntitlementResult).when(
+ mSatelliteEntitlementApi).checkEntitlementStatus();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Test
+ public void testIsQueryAvailable() throws Exception {
+ doReturn(ACTIVE_SUB_ID).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
+
+ // Verify don't start the query when KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL is false.
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
+ verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
+ anyBoolean(), anyList(), anyList(), any());
+
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ // Verify don't start the query when ExponentialBackoff is in progressed.
+ replaceInstance(SatelliteEntitlementController.class, "mExponentialBackoffPerSub",
+ mSatelliteEntitlementController, Map.of(SUB_ID, mExponentialBackoff));
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
+ verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
+ anyBoolean(), anyList(), anyList(), any());
+
+ replaceInstance(SatelliteEntitlementController.class, "mExponentialBackoffPerSub",
+ mSatelliteEntitlementController, new HashMap<>());
+ // Verify don't start the query when Internet is disconnected.
+ doReturn(ACTIVE_SUB_ID).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
+ setInternetConnected(false);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
+ verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
+ anyBoolean(), anyList(), anyList(), any());
+
+ setInternetConnected(true);
+ // Verify don't start the query when last query refresh time is not expired.
+ setLastQueryTime(System.currentTimeMillis());
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
+ verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
+ anyBoolean(), anyList(), anyList(), any());
+
+ // Verify start the query when isQueryAvailable return true
+ setLastQueryTime(0L);
+ doReturn(mSatelliteEntitlementResult).when(
+ mSatelliteEntitlementApi).checkEntitlementStatus();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ PLMN_BARRED_LIST);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
+ anyBoolean(), anyList(), anyList(), any());
+ }
+
+ @Test
+ public void testCheckSatelliteEntitlementStatus() throws Exception {
+ setIsQueryAvailableTrue();
+ // Verify don't call the checkSatelliteEntitlementStatus when getActiveSubIdList is empty.
+ doReturn(new int[]{}).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi, never()).checkEntitlementStatus();
+ // Verify don't call the updateSatelliteEntitlementStatus.
+ verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
+ anyBoolean(), anyList(), anyList(), any());
+
+ // Verify call the checkSatelliteEntitlementStatus with invalid response.
+ setIsQueryAvailableTrue();
+ doReturn(mSatelliteEntitlementResult).when(
+ mSatelliteEntitlementApi).checkEntitlementStatus();
+ replaceInstance(SatelliteEntitlementController.class,
+ "mSatelliteEntitlementResultPerSub", mSatelliteEntitlementController,
+ new HashMap<>());
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is disabled
+ // , empty PLMNAllowed and empty PLMNBarred.
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID),
+ eq(false), eq(new ArrayList<>()), eq(new ArrayList<>()), any());
+
+ // Verify call the checkSatelliteEntitlementStatus with the subscribed result.
+ clearInvocationsForMock();
+ setIsQueryAvailableTrue();
+ doReturn(mSatelliteEntitlementResult).when(
+ mSatelliteEntitlementApi).checkEntitlementStatus();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ PLMN_BARRED_LIST);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
+ // availablePLMNAllowedList and availablePLMNBarredList.
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+
+ // Change subId and verify call the updateSatelliteEntitlementStatus with satellite
+ // service is enable, availablePLMNAllowedList and availablePLMNBarredList
+ clearInvocationsForMock();
+ doReturn(new int[]{SUB_ID_2}).when(mMockSubscriptionManagerService).getActiveSubIdList(
+ true);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID_2), eq(true),
+ eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
+ // availablePLMNAllowedList and empty plmn barred list.
+ clearInvocationsForMock();
+ setIsQueryAvailableTrue();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ new ArrayList<>());
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(PLMN_ALLOWED_LIST), eq(new ArrayList<>()), any());
+
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
+ // empty PLMNAllowedList and PLMNBarredList.
+ clearInvocationsForMock();
+ setIsQueryAvailableTrue();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, new ArrayList<>(),
+ new ArrayList<>());
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(new ArrayList<>()), eq(new ArrayList<>()), any());
+
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable,
+ // empty PLMNAllowedList and availablePLMNBarredList.
+ clearInvocationsForMock();
+ setIsQueryAvailableTrue();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, new ArrayList<>(),
+ PLMN_BARRED_LIST);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(new ArrayList<>()), eq(PLMN_BARRED_LIST), any());
+ }
+
+ @Test
+ public void testCheckSatelliteEntitlementStatusWhenInternetConnected() throws Exception {
+ Field fieldNetworkCallback = SatelliteEntitlementController.class.getDeclaredField(
+ "mNetworkCallback");
+ fieldNetworkCallback.setAccessible(true);
+ ConnectivityManager.NetworkCallback networkCallback =
+ (ConnectivityManager.NetworkCallback) fieldNetworkCallback.get(
+ mSatelliteEntitlementController);
+ Network mockNetwork = mock(Network.class);
+
+ // Verify the called the checkSatelliteEntitlementStatus when Internet is connected.
+ setInternetConnected(true);
+ setLastQueryTime(0L);
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ PLMN_BARRED_LIST);
+
+ networkCallback.onAvailable(mockNetwork);
+ mTestableLooper.processAllMessages();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is available.
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+ }
+
+ @Test
+ public void testCheckSatelliteEntitlementStatusWhenCarrierConfigChanged() throws Exception {
+ // Verify the called the checkSatelliteEntitlementStatus when CarrierConfigChanged
+ // occurred and Internet is connected.
+ setInternetConnected(true);
+ setLastQueryTime(0L);
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST,
+ PLMN_BARRED_LIST);
+ triggerCarrierConfigChanged();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is available.
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
+ }
+
+ private void triggerCarrierConfigChanged() {
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ mTestableLooper.processAllMessages();
+ }
+
+ private void clearInvocationsForMock() {
+ clearInvocations(mSatelliteEntitlementApi);
+ clearInvocations(mSatelliteController);
+ }
+
+ private void setIsQueryAvailableTrue() throws Exception {
+ doReturn(ACTIVE_SUB_ID).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ replaceInstance(SatelliteEntitlementController.class, "mRetryCountPerSub",
+ mSatelliteEntitlementController, new HashMap<>());
+ setInternetConnected(true);
+ setLastQueryTime(0L);
+ replaceInstance(SatelliteEntitlementController.class,
+ "mSatelliteEntitlementResultPerSub", mSatelliteEntitlementController,
+ new HashMap<>());
+ }
+
+ private void setInternetConnected(boolean connected) {
+ NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder().build();
+
+ if (connected) {
+ networkCapabilities = new NetworkCapabilities.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .setTransportInfo(mock(WifiInfo.class))
+ .build();
+ }
+ doReturn(networkCapabilities).when(mConnectivityManager).getNetworkCapabilities(mNetwork);
+ }
+
+ private void setSatelliteEntitlementResult(int entitlementStatus,
+ List<String> plmnAllowedList, List<String> plmnBarredList) {
+ doReturn(entitlementStatus).when(mSatelliteEntitlementResult).getEntitlementStatus();
+ doReturn(plmnAllowedList).when(mSatelliteEntitlementResult).getAllowedPLMNList();
+ doReturn(plmnBarredList).when(mSatelliteEntitlementResult).getBarredPLMNList();
+ }
+
+ private void setLastQueryTime(Long lastQueryTime) throws Exception {
+ Map<Integer, Long> lastQueryTimePerSub = new HashMap<>();
+ replaceInstance(SatelliteEntitlementController.class, "mLastQueryTimePerSub",
+ mSatelliteEntitlementController, lastQueryTimePerSub);
+ lastQueryTimePerSub.put(SUB_ID, lastQueryTime);
+ }
+
+ public static class TestSatelliteEntitlementController extends SatelliteEntitlementController {
+ private SatelliteEntitlementApi mInjectSatelliteEntitlementApi;
+
+ TestSatelliteEntitlementController(@NonNull Context context, @NonNull Looper looper,
+ SatelliteEntitlementApi api) {
+ super(context, looper);
+ mInjectSatelliteEntitlementApi = api;
+ }
+
+ @Override
+ public SatelliteEntitlementApi getSatelliteEntitlementApi(int subId) {
+ logd("getSatelliteEntitlementApi");
+ return mInjectSatelliteEntitlementApi;
+ }
+ }
+
+ private static void logd(String log) {
+ Log.d(TAG, log);
+ }
+}
diff --git a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
new file mode 100644
index 0000000..8e45a73
--- /dev/null
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2024 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.satellite.entitlement;
+
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_DISABLED;
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_ENABLED;
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE;
+import static com.android.phone.satellite.entitlement.SatelliteEntitlementResult.SATELLITE_ENTITLEMENT_STATUS_PROVISIONING;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.telephony.satellite.SatelliteNetworkInfo;
+import com.android.libraries.entitlement.ServiceEntitlement;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class SatelliteEntitlementResponseTest {
+ private static final String TEST_OTHER_APP_ID = "ap201x";
+ private static final List<SatelliteNetworkInfo> TEST_PLMN_DATA_PLAN_TYPE_LIST = Arrays.asList(
+ new SatelliteNetworkInfo("31026", "unmetered"),
+ new SatelliteNetworkInfo("302820", "metered"));
+ private static final List<String> TEST_PLMN_BARRED_LIST = Arrays.asList("31017", "302020");
+ private static final String RESPONSE_WITHOUT_SATELLITE_APP_ID =
+ "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + TEST_OTHER_APP_ID + "\":{"
+ + "\"EntitlementStatus\":\"" + SATELLITE_ENTITLEMENT_STATUS_ENABLED + "\"}}";
+ private static final String RESPONSE_WITHOUT_ENTITLEMENT_STATUS =
+ "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{}}";
+
+ private static final String RESPONSE_WITHOUT_PLMN =
+ "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
+ + "\"EntitlementStatus\":\"" + SATELLITE_ENTITLEMENT_STATUS_ENABLED + "\"}}";
+
+ private static final String RESPONSE_WITHOUT_PLMN_ALLOWED =
+ "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
+ + "\"EntitlementStatus\":\"" + SATELLITE_ENTITLEMENT_STATUS_ENABLED + "\"" + ","
+ + "\"PLMNBarred\":[{\"PLMN\":\"31017\"},"
+ + "{\"PLMN\":\"302020\"}]}}";
+
+ @Test
+ public void testGetSatelliteEntitlementResponse() throws Exception {
+ // Received the body with satellite service enabled.
+ SatelliteEntitlementResponse response = new SatelliteEntitlementResponse(
+ getResponse(SATELLITE_ENTITLEMENT_STATUS_ENABLED));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 2);
+ assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(0).mPlmn,
+ response.getPlmnAllowed().get(0).mPlmn);
+ assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(0).mDataPlanType,
+ response.getPlmnAllowed().get(0).mDataPlanType);
+ assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(1).mPlmn,
+ response.getPlmnAllowed().get(1).mPlmn);
+ assertEquals(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(1).mDataPlanType,
+ response.getPlmnAllowed().get(1).mDataPlanType);
+ assertTrue(response.getPlmnBarredList().size() == 2);
+ assertEquals(TEST_PLMN_BARRED_LIST, response.getPlmnBarredList());
+
+ // Received the empty body.
+ response = new SatelliteEntitlementResponse("");
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_DISABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ // Received the body without satellite app id.
+ response = new SatelliteEntitlementResponse(RESPONSE_WITHOUT_SATELLITE_APP_ID);
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_DISABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ // Received the body without EntitlementStatus.
+ response = new SatelliteEntitlementResponse(RESPONSE_WITHOUT_ENTITLEMENT_STATUS);
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_DISABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ // Received the body with an entitlementStatus value of DISABLED.
+ response = new SatelliteEntitlementResponse(
+ getResponse(SATELLITE_ENTITLEMENT_STATUS_DISABLED));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_DISABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ // Received the body with an entitlementStatus value of INCOMPATIBLE.
+ response = new SatelliteEntitlementResponse(
+ getResponse(SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ // Received the body with an entitlementStatus value of PROVISIONING.
+ response = new SatelliteEntitlementResponse(
+ getResponse(SATELLITE_ENTITLEMENT_STATUS_PROVISIONING));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_PROVISIONING, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ // Received the body without plmn.
+ response = new SatelliteEntitlementResponse(RESPONSE_WITHOUT_PLMN);
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ // Received the body without plmn allowed key.
+ response = new SatelliteEntitlementResponse(RESPONSE_WITHOUT_PLMN_ALLOWED);
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ assertTrue(response.getPlmnBarredList().size() == 2);
+ assertEquals(TEST_PLMN_BARRED_LIST, response.getPlmnBarredList());
+
+ // Received the body without plmn barred key.
+ response = new SatelliteEntitlementResponse(
+ getChangedAllowedPLMNListResponse(TEST_PLMN_DATA_PLAN_TYPE_LIST.get(0).mPlmn,
+ TEST_PLMN_DATA_PLAN_TYPE_LIST.get(1).mPlmn));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 2);
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ String plmn = "123456";
+ // Received the allowed plmn list set as 123456, empty string
+ response = new SatelliteEntitlementResponse(
+ getChangedAllowedPLMNListResponse(plmn, ""));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 1);
+ assertEquals(plmn, response.getPlmnAllowed().get(0).mPlmn);
+
+ // Received the allowed plmn list set as 123456, empty string
+ response = new SatelliteEntitlementResponse(
+ getChangedAllowedPLMNListResponse("", plmn));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 1);
+ assertEquals(plmn, response.getPlmnAllowed().get(0).mPlmn);
+
+ // RReceived the allowed plmn list set as empty strings
+ response = new SatelliteEntitlementResponse(
+ getChangedAllowedPLMNListResponse("", ""));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+
+ // Received the barred plmn list set as 123456, empty string
+ response = new SatelliteEntitlementResponse(
+ getChangedBarredPLMNListResponse(plmn, ""));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnBarredList().size() == 1);
+ assertEquals(plmn, response.getPlmnBarredList().get(0));
+
+ // Received the barred plmn list set as empty string, 123456
+ response = new SatelliteEntitlementResponse(
+ getChangedBarredPLMNListResponse("", plmn));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnBarredList().size() == 1);
+ assertEquals(plmn, response.getPlmnBarredList().get(0));
+
+ // Received the barred plmn list set as empty strings
+ response = new SatelliteEntitlementResponse(
+ getChangedBarredPLMNListResponse("", ""));
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_ENABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnBarredList().size() == 0);
+
+ // Received null
+ response = new SatelliteEntitlementResponse(null);
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_DISABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+
+ // Received empty string
+ response = new SatelliteEntitlementResponse("");
+ assertEquals(SATELLITE_ENTITLEMENT_STATUS_DISABLED, response.getEntitlementStatus());
+ assertTrue(response.getPlmnAllowed().size() == 0);
+ }
+
+ private String getResponse(int entitlementStatus) {
+ return "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
+ + "\"EntitlementStatus\":\"" + entitlementStatus + "\""
+ + getPLMNListOrEmpty(entitlementStatus)
+ + "}}";
+ }
+
+ private String getPLMNListOrEmpty(int entitlementStatus) {
+ return entitlementStatus == SATELLITE_ENTITLEMENT_STATUS_ENABLED ? ","
+ + "\"PLMNAllowed\":[{\"PLMN\":\"31026\",\"DataPlanType\":\"unmetered\"},"
+ + "{\"PLMN\":\"302820\",\"DataPlanType\":\"metered\"}],"
+ + "\"PLMNBarred\":[{\"PLMN\":\"31017\"},"
+ + "{\"PLMN\":\"302020\"}]" : "";
+ }
+
+ private String getAllowedPlmns(String firstPlmn, String secondPlmn) {
+ return ",\"PLMNAllowed\":[{\"PLMN\":\"" + firstPlmn + "\",\"DataPlanType\":\"unmetered\"},"
+ + "{\"PLMN\":\"" + secondPlmn + "\",\"DataPlanType\":\"metered\"}]";
+ }
+
+ private String getBarredPlmns(String firstPlmn, String secondPlmn) {
+ return ",\"PLMNBarred\":[{\"PLMN\":\"" + firstPlmn + "\"}," + "{\"PLMN\":\"" + secondPlmn
+ + "\"}]";
+ }
+
+ private String getChangedAllowedPLMNListResponse(String firstPlmn, String secondPlmn) {
+ return "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
+ + "\"EntitlementStatus\":\"" + SATELLITE_ENTITLEMENT_STATUS_ENABLED + "\""
+ + getAllowedPlmns(firstPlmn, secondPlmn)
+ + "}}";
+ }
+
+ private String getChangedBarredPLMNListResponse(String firstPlmn, String secondPlmn) {
+ return "{\"VERS\":{\"version\":\"1\",\"validity\":\"172800\"},"
+ + "\"TOKEN\":{\"token\":\"ASH127AHHA88SF\"},\""
+ + ServiceEntitlement.APP_SATELLITE_ENTITLEMENT + "\":{"
+ + "\"EntitlementStatus\":\"" + SATELLITE_ENTITLEMENT_STATUS_ENABLED + "\""
+ + ",\"PLMNAllowed\":[{\"PLMN\":\"31026\",\"DataPlanType\":\"unmetered\"},"
+ + "{\"PLMN\":\"302820\",\"DataPlanType\":\"metered\"}]"
+ + getBarredPlmns(firstPlmn, secondPlmn)
+ + "}}";
+ }
+}
diff --git a/tests/src/com/android/phone/security/SafetySourceReceiverTest.java b/tests/src/com/android/phone/security/SafetySourceReceiverTest.java
new file mode 100644
index 0000000..305e698
--- /dev/null
+++ b/tests/src/com/android/phone/security/SafetySourceReceiverTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2024 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.security;
+
+import static android.safetycenter.SafetyCenterManager.ACTION_REFRESH_SAFETY_SOURCES;
+import static android.safetycenter.SafetyCenterManager.EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.Flags;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class SafetySourceReceiverTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ Context mContext;
+
+ SafetySourceReceiver mSafetySourceReceiver;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ SafetySourceReceiver receiver = new SafetySourceReceiver();
+ mSafetySourceReceiver = spy(receiver);
+
+ when(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+ }
+
+ @Test
+ public void testOnReceive() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS,
+ Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS,
+ Flags.FLAG_ENFORCE_TELEPHONY_FEATURE_MAPPING_FOR_PUBLIC_APIS);
+ Phone mockPhone = mock(Phone.class);
+ when(mSafetySourceReceiver.getDefaultPhone()).thenReturn(mockPhone);
+
+ Intent intent = new Intent(ACTION_REFRESH_SAFETY_SOURCES);
+ intent.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, "aBroadcastId");
+ mSafetySourceReceiver.onReceive(mContext, intent);
+
+ verify(mockPhone, times(1)).refreshSafetySources("aBroadcastId");
+ }
+
+ @Test
+ public void testOnReceive_featureFlagsOff() {
+ mSetFlagsRule.disableFlags(
+ Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS,
+ Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS,
+ Flags.FLAG_ENFORCE_TELEPHONY_FEATURE_MAPPING_FOR_PUBLIC_APIS);
+
+ Intent intent = new Intent(ACTION_REFRESH_SAFETY_SOURCES);
+ intent.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, "aBroadcastId");
+ mSafetySourceReceiver.onReceive(mContext, intent);
+
+ verify(mSafetySourceReceiver, never()).getDefaultPhone();
+ }
+
+ @Test
+ public void testOnReceive_phoneNotReadyYet() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS,
+ Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS,
+ Flags.FLAG_ENFORCE_TELEPHONY_FEATURE_MAPPING_FOR_PUBLIC_APIS);
+ when(mSafetySourceReceiver.getDefaultPhone()).thenReturn(null);
+
+ Intent intent = new Intent(ACTION_REFRESH_SAFETY_SOURCES);
+ intent.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, "aBroadcastId");
+
+ // this call succeeding without a NPE means this test has passed. There are no observable
+ // side effects to a null Phone, because all side effects happen on the Phone instance.
+ mSafetySourceReceiver.onReceive(mContext, intent);
+ }
+
+ @Test
+ public void testOnReceive_noTelephonyFeature() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS,
+ Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS,
+ Flags.FLAG_ENFORCE_TELEPHONY_FEATURE_MAPPING_FOR_PUBLIC_APIS);
+
+ when(mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TELEPHONY)).thenReturn(false);
+
+ Phone mockPhone = mock(Phone.class);
+ when(mSafetySourceReceiver.getDefaultPhone()).thenReturn(mockPhone);
+
+ Intent intent = new Intent(ACTION_REFRESH_SAFETY_SOURCES);
+ intent.putExtra(EXTRA_REFRESH_SAFETY_SOURCES_BROADCAST_ID, "aBroadcastId");
+ mSafetySourceReceiver.onReceive(mContext, intent);
+
+ verify(mockPhone, never()).refreshSafetySources(any());
+ }
+}
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index 16a5cdb..71a23e6 100644
--- a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
+++ b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
@@ -41,7 +41,7 @@
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
-import com.android.phone.common.R;
+import com.android.phone.R;
import org.junit.Before;
import org.junit.Test;
@@ -152,7 +152,8 @@
android.telecom.DisconnectCause tcCause =
DisconnectCauseUtil.toTelecomDisconnectCause(
DisconnectCause.BUSY, -1 /* precise label is NOT given */,
- EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags);
+ EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags,
+ false);
assertBusyCauseWithTargetLabel(R.string.callFailed_userBusy, tcCause);
}
@@ -170,7 +171,8 @@
android.telecom.DisconnectCause tcCause =
DisconnectCauseUtil.toTelecomDisconnectCause(DisconnectCause.BUSY,
CallFailCause.USER_BUSY /* Telephony defined a precise label */,
- EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags);
+ EMPTY_STRING, PHONE_ID, null, getBundleWithBusyToneArray(), mFeatureFlags,
+ false);
// Note: The precise label should not be overridden even though the carrier defined
// the cause to play a busy tone
assertBusyCauseWithTargetLabel(R.string.clh_callFailed_user_busy_txt, tcCause);
diff --git a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
index a9207e6..b1572f1 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
@@ -27,7 +27,8 @@
import android.content.ComponentName;
import android.os.Looper;
import android.telecom.PhoneAccountHandle;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/src/com/android/services/telephony/ImsConferenceTest.java b/tests/src/com/android/services/telephony/ImsConferenceTest.java
index e2a199b..ca16bc7 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceTest.java
@@ -40,7 +40,8 @@
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.ims.internal.ConferenceParticipant;
diff --git a/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java b/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
index b7fe988..c7080b4 100644
--- a/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConferenceControllerTest.java
@@ -28,7 +28,8 @@
import android.telecom.Conference;
import android.telecom.Connection;
import android.telecom.PhoneAccount;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import org.junit.Before;
import org.junit.Test;
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index f0a5220..435601f 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -37,7 +37,7 @@
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
-import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -46,6 +46,7 @@
import static org.mockito.Mockito.doAnswer;
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.times;
@@ -80,9 +81,9 @@
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.stub.ImsRegistrationImplBase;
-import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArrayMap;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.TelephonyTestBase;
@@ -223,6 +224,9 @@
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 static final String DISCONNECT_REASON_SATELLITE_ENABLED = "SATELLITE_ENABLED";
+ private static final String DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE =
+ "CARRIER_ROAMING_SATELLITE_MODE";
private android.telecom.Connection mConnection;
@Mock TelephonyConnectionService.TelephonyManagerProxy mTelephonyManagerProxy;
@@ -308,7 +312,7 @@
anyString(), anyInt());
doReturn(CompletableFuture.completedFuture(NOT_DISCONNECTED))
.when(mEmergencyStateTracker)
- .startEmergencyCall(any(), anyString(), eq(false));
+ .startEmergencyCall(any(), any(), eq(false));
replaceInstance(TelephonyConnectionService.class,
"mDomainSelectionMainExecutor", mTestConnectionService, getExecutor());
doReturn(false).when(mDomainSelectionResolver).isDomainSelectionSupported();
@@ -319,10 +323,15 @@
mBinderStub = (IConnectionService.Stub) mTestConnectionService.onBind(null);
mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
mSetFlagsRule.enableFlags(Flags.FLAG_DO_NOT_OVERRIDE_PRECISE_LABEL);
+ mSetFlagsRule.enableFlags(Flags.FLAG_CALL_EXTRA_FOR_NON_HOLD_SUPPORTED_CARRIERS);
}
@After
public void tearDown() throws Exception {
+ if (mTestConnectionService != null
+ && mTestConnectionService.getEmergencyConnection() != null) {
+ mTestConnectionService.onLocalHangup(mTestConnectionService.getEmergencyConnection());
+ }
mTestConnectionService = null;
super.tearDown();
}
@@ -1816,7 +1825,7 @@
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
tcs.add(tc1);
TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
- tcs, SUB1_HANDLE, mTelephonyManagerProxy);
+ tcs, SUB1_HANDLE, false, mTelephonyManagerProxy);
// Would've preferred to use mockito, but can't mock out TelephonyConnection/Connection
// easily.
assertFalse(tc1.wasDisconnected);
@@ -1829,7 +1838,7 @@
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, true);
tcs.add(tc1);
TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
- tcs, SUB2_HANDLE, mTelephonyManagerProxy);
+ tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
// Other call is an emergency call, so don't disconnect it.
assertFalse(tc1.wasDisconnected);
}
@@ -1842,7 +1851,7 @@
android.telecom.Connection.PROPERTY_IS_EXTERNAL_CALL, false);
tcs.add(tc1);
TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
- tcs, SUB2_HANDLE, mTelephonyManagerProxy);
+ tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
// Other call is an external call, so don't disconnect it.
assertFalse(tc1.wasDisconnected);
}
@@ -1854,7 +1863,7 @@
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
tcs.add(tc1);
TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
- tcs, SUB2_HANDLE, mTelephonyManagerProxy);
+ tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
assertTrue(tc1.wasDisconnected);
}
@@ -1868,14 +1877,14 @@
tcs.add(tc1);
tcs.add(tc2);
TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
- tcs, SUB2_HANDLE, mTelephonyManagerProxy);
+ tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
assertTrue(tc1.wasDisconnected);
assertTrue(tc2.wasDisconnected);
}
/**
* Verifies that DSDA or virtual DSDA-enabled devices can support active non-emergency calls on
- * separate subs.
+ * separate subs, when the extra EXTRA_ANSWERING_DROPS_FG_CALL is not set on the incoming call.
*/
@Test
@SmallTest
@@ -1886,10 +1895,26 @@
SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
tcs.add(tc1);
TelephonyConnectionService.maybeDisconnectCallsOnOtherSubs(
- tcs, SUB2_HANDLE, mTelephonyManagerProxy);
+ tcs, SUB2_HANDLE, false, mTelephonyManagerProxy);
assertFalse(tc1.wasDisconnected);
}
+ /**
+ * Verifies that DSDA or virtual DSDA-enabled devices will disconnect the existing call when the
+ * call extra EXTRA_ANSWERING_DROPS_FG_CALL is set on the incoming call on a different sub.
+ */
+ @Test
+ @SmallTest
+ public void testDisconnectDifferentSubForVirtualDsdaDevice_ifCallExtraSet() {
+ 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, true, mTelephonyManagerProxy);
+ assertTrue(tc1.wasDisconnected);
+ }
/**
* For calls on the same sub, the Dialer implements the 'swap' functionality to perform hold and
@@ -1972,6 +1997,27 @@
}
/**
+ * For DSDA devices with AP domain selection service enabled, placing an outgoing call
+ * on a 2nd sub will hold the existing ACTIVE connection on the first sub.
+ */
+ @Test
+ @SmallTest
+ public void testHoldOnOtherSubForVirtualDsdaDeviceWithDomainSelectionEnabled() {
+ when(mTelephonyManagerProxy.isConcurrentCallsPossible()).thenReturn(true);
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+
+ ArrayList<android.telecom.Connection> tcs = new ArrayList<>();
+ SimpleTelephonyConnection tc1 = createTestConnection(SUB1_HANDLE, 0, false);
+ tc1.setTelephonyConnectionActive();
+ tcs.add(tc1);
+
+ Conferenceable c = TelephonyConnectionService.maybeHoldCallsOnOtherSubs(
+ tcs, new ArrayList<>(), SUB2_HANDLE, mTelephonyManagerProxy);
+ assertTrue(c.equals(tc1));
+ assertTrue(tc1.wasHeld);
+ }
+
+ /**
* For DSDA devices, if the existing connection was already held, placing an outgoing call on a
* 2nd sub will not attempt to hold the existing connection on the first sub.
*/
@@ -2124,13 +2170,22 @@
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
@@ -2154,13 +2209,22 @@
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
@@ -2187,14 +2251,23 @@
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mEmergencyStateTracker, times(1))
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mDomainSelectionResolver, times(0))
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyCallDomainSelectionConnection, times(0))
.createEmergencyConnection(any(), any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
@@ -2219,11 +2292,12 @@
assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
android.telephony.DisconnectCause.NOT_VALID));
verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+ verify(mEmergencyCallDomainSelectionConnection).setDisconnectCause(
+ eq(disconnectCause), eq(preciseDisconnectCause), any());
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
- Connection nc = Mockito.mock(Connection.class);
- doReturn(nc).when(mPhone0).dial(anyString(), any(), any());
+ doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
DialArgs dialArgs = argsCaptor.getValue();
@@ -2245,14 +2319,141 @@
TestTelephonyConnection c = setupForReDialForDomainSelection(
mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, null, false,
+ android.telephony.DisconnectCause.ICC_ERROR));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+ verify(mEmergencyCallDomainSelectionConnection).setDisconnectCause(
+ eq(android.telephony.DisconnectCause.ICC_ERROR),
+ eq(com.android.internal.telephony.CallFailCause.NOT_VALID),
+ any());
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+
+ doReturn(mInternalConnection).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 testDomainSelectionRedialFailedWithException() 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);
+
+ CallStateException cse = new CallStateException(CallStateException.ERROR_CALLING_DISABLED,
+ "Calling disabled via ro.telephony.disable-call property");
+ doThrow(cse).when(mPhone0).dial(anyString(), any(), any());
+
+ assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
+ android.telephony.DisconnectCause.NOT_VALID));
+ verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
+ verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
+ verify(mEmergencyStateTracker).endCall(any());
+ }
+
+ @Test
+ public void testDomainSelectionRejectIncoming() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ doReturn(mInternalConnection2).when(mCall).getLatestConnection();
+ doReturn(true).when(mCall).isRinging();
+ doReturn(mCall).when(mPhone0).getRingingCall();
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
+ verify(mDomainSelectionResolver)
+ .getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
+ verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
+ ArgumentCaptor<Connection.Listener> listenerCaptor =
+ ArgumentCaptor.forClass(Connection.Listener.class);
+
+ verify(mInternalConnection2).addListener(listenerCaptor.capture());
+ verify(mCall).hangup();
+ verify(mPhone0, never()).dial(anyString(), any(), any());
+
+ Connection.Listener listener = listenerCaptor.getValue();
+
+ assertNotNull(listener);
+
+ listener.onDisconnect(0);
+
+ verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(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 testDomainSelectionRedialRejectIncoming() 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);
+
+ doReturn(mInternalConnection2).when(mCall).getLatestConnection();
+ doReturn(true).when(mCall).isRinging();
+ doReturn(mCall).when(mPhone0).getRingingCall();
+
assertTrue(mTestConnectionService.maybeReselectDomain(c, null, true,
android.telephony.DisconnectCause.NOT_VALID));
verify(mEmergencyCallDomainSelectionConnection).reselectDomain(any());
- ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
+ ArgumentCaptor<Connection.Listener> listenerCaptor =
+ ArgumentCaptor.forClass(Connection.Listener.class);
- Connection nc = Mockito.mock(Connection.class);
- doReturn(nc).when(mPhone0).dial(anyString(), any(), any());
+ verify(mInternalConnection2).addListener(listenerCaptor.capture());
+ verify(mCall).hangup();
+ verify(mPhone0, never()).dial(anyString(), any(), any());
+
+ Connection.Listener listener = listenerCaptor.getValue();
+
+ assertNotNull(listener);
+
+ listener.onDisconnect(0);
+
+ ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
DialArgs dialArgs = argsCaptor.getValue();
@@ -2324,13 +2525,22 @@
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
@@ -2385,132 +2595,83 @@
@Test
public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_InService()
throws Exception {
- setupForCallTest();
-
- doReturn(false).when(mPhone0).isRadioOn();
- ServiceState ss = new ServiceState();
- ss.setState(ServiceState.STATE_POWER_OFF);
- when(mPhone0.getServiceState()).thenReturn(ss);
- when(mSST.getServiceState()).thenReturn(ss);
-
- setupForDialForDomainSelection(mPhone0, DOMAIN_CS, false);
-
- EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
- EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
- Collections.emptyList(),
- EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
- EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
-
- doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
- doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
- doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
- anyString());
-
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
-
- mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
- createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
- TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
ArgumentCaptor<RadioOnStateListener.Callback> callback =
ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
- any(), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
+ eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
+
+ ServiceState ss = new ServiceState();
+ ss.setState(ServiceState.STATE_OUT_OF_SERVICE);
+ when(testPhone.getServiceState()).thenReturn(ss);
+ when(mSST.getServiceState()).thenReturn(ss);
assertFalse(callback.getValue()
- .isOkToCall(mPhone0, ServiceState.STATE_OUT_OF_SERVICE, false));
+ .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
when(mSST.isRadioOn()).thenReturn(true);
assertFalse(callback.getValue()
- .isOkToCall(mPhone0, ServiceState.STATE_OUT_OF_SERVICE, false));
+ .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+
+ Phone otherPhone = makeTestPhone(1, ServiceState.STATE_OUT_OF_SERVICE, false);
+ when(otherPhone.getServiceState()).thenReturn(ss);
+
+ // Radio on is OK for other phone
+ assertTrue(callback.getValue()
+ .isOkToCall(otherPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
ss.setState(ServiceState.STATE_IN_SERVICE);
assertTrue(callback.getValue()
- .isOkToCall(mPhone0, ServiceState.STATE_IN_SERVICE, false));
+ .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
+
+ mConnection.setDisconnected(null);
}
@Test
public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_Timeout()
throws Exception {
- setupForCallTest();
-
- doReturn(false).when(mPhone0).isRadioOn();
- ServiceState ss = new ServiceState();
- ss.setState(ServiceState.STATE_POWER_OFF);
- when(mPhone0.getServiceState()).thenReturn(ss);
- when(mSST.getServiceState()).thenReturn(ss);
-
- setupForDialForDomainSelection(mPhone0, DOMAIN_CS, false);
-
- EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
- EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
- Collections.emptyList(),
- EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
- EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
-
- doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
- doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
- doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
- anyString());
-
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
-
- mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
- createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
- TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
ArgumentCaptor<RadioOnStateListener.Callback> callback =
ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
- any(), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
+ eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
+ ServiceState ss = new ServiceState();
+ ss.setState(ServiceState.STATE_OUT_OF_SERVICE);
+ when(testPhone.getServiceState()).thenReturn(ss);
+ when(mSST.getServiceState()).thenReturn(ss);
when(mSST.isRadioOn()).thenReturn(true);
assertFalse(callback.getValue()
- .isOkToCall(mPhone0, ServiceState.STATE_OUT_OF_SERVICE, false));
+ .isOkToCall(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
assertTrue(callback.getValue()
- .onTimeout(mPhone0, ServiceState.STATE_OUT_OF_SERVICE, false));
+ .onTimeout(testPhone, ServiceState.STATE_OUT_OF_SERVICE, false));
+
+ mConnection.setDisconnected(null);
}
@Test
public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_CombinedAttach()
throws Exception {
- setupForCallTest();
-
- doReturn(false).when(mPhone0).isRadioOn();
- ServiceState ss = new ServiceState();
- ss.setState(ServiceState.STATE_POWER_OFF);
- when(mPhone0.getServiceState()).thenReturn(ss);
- when(mSST.getServiceState()).thenReturn(ss);
-
- setupForDialForDomainSelection(mPhone0, DOMAIN_CS, false);
-
- EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
- EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
- Collections.emptyList(),
- EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
- EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
-
- doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
- doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
- doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
- anyString());
-
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
-
- mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
- createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
- TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
ArgumentCaptor<RadioOnStateListener.Callback> callback =
ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
- any(), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
+ eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
- when(mSST.isRadioOn()).thenReturn(true);
+ ServiceState ss = new ServiceState();
ss.setState(ServiceState.STATE_IN_SERVICE);
+ when(testPhone.getServiceState()).thenReturn(ss);
+ when(mSST.getServiceState()).thenReturn(ss);
+ when(mSST.isRadioOn()).thenReturn(true);
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo.Builder(3)
.setLteAttachResultType(DataSpecificRegistrationInfo.LTE_ATTACH_TYPE_COMBINED)
@@ -2526,46 +2687,27 @@
ss.addNetworkRegistrationInfo(nri);
assertTrue(callback.getValue()
- .isOkToCall(mPhone0, ServiceState.STATE_IN_SERVICE, false));
+ .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
+
+ mConnection.setDisconnected(null);
}
@Test
public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_PsOnly()
throws Exception {
- setupForCallTest();
-
- doReturn(false).when(mPhone0).isRadioOn();
- ServiceState ss = new ServiceState();
- ss.setState(ServiceState.STATE_POWER_OFF);
- when(mPhone0.getServiceState()).thenReturn(ss);
- when(mSST.getServiceState()).thenReturn(ss);
-
- setupForDialForDomainSelection(mPhone0, DOMAIN_CS, false);
-
- EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
- EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
- Collections.emptyList(),
- EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
- EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
-
- doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
- doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
- doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
- anyString());
-
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
-
- mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
- createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
- TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
ArgumentCaptor<RadioOnStateListener.Callback> callback =
ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
- any(), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
+ eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
- when(mSST.isRadioOn()).thenReturn(true);
+ ServiceState ss = new ServiceState();
ss.setState(ServiceState.STATE_IN_SERVICE);
+ when(testPhone.getServiceState()).thenReturn(ss);
+ when(mSST.getServiceState()).thenReturn(ss);
+ when(mSST.isRadioOn()).thenReturn(true);
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo.Builder(3)
.build();
@@ -2580,48 +2722,29 @@
ss.addNetworkRegistrationInfo(nri);
assertFalse(callback.getValue()
- .isOkToCall(mPhone0, ServiceState.STATE_IN_SERVICE, false));
+ .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
assertTrue(callback.getValue()
- .onTimeout(mPhone0, ServiceState.STATE_IN_SERVICE, false));
+ .onTimeout(testPhone, ServiceState.STATE_IN_SERVICE, false));
+
+ mConnection.setDisconnected(null);
}
@Test
public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_PsOnly_ImsRegistered()
throws Exception {
- setupForCallTest();
-
- doReturn(false).when(mPhone0).isRadioOn();
- ServiceState ss = new ServiceState();
- ss.setState(ServiceState.STATE_POWER_OFF);
- when(mPhone0.getServiceState()).thenReturn(ss);
- when(mSST.getServiceState()).thenReturn(ss);
-
- setupForDialForDomainSelection(mPhone0, DOMAIN_CS, false);
-
- EmergencyNumber emergencyNumber = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "", "",
- EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
- Collections.emptyList(),
- EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
- EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
-
- doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
- doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
- doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
- anyString());
-
when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
-
- mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
- createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
- TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
ArgumentCaptor<RadioOnStateListener.Callback> callback =
ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
- any(), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
+ eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
- when(mSST.isRadioOn()).thenReturn(true);
+ ServiceState ss = new ServiceState();
ss.setState(ServiceState.STATE_IN_SERVICE);
+ when(testPhone.getServiceState()).thenReturn(ss);
+ when(mSST.getServiceState()).thenReturn(ss);
+ when(mSST.isRadioOn()).thenReturn(true);
DataSpecificRegistrationInfo dsri = new DataSpecificRegistrationInfo.Builder(3)
.build();
@@ -2636,9 +2759,28 @@
ss.addNetworkRegistrationInfo(nri);
assertFalse(callback.getValue()
- .isOkToCall(mPhone0, ServiceState.STATE_IN_SERVICE, false));
+ .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, false));
assertTrue(callback.getValue()
- .isOkToCall(mPhone0, ServiceState.STATE_IN_SERVICE, true));
+ .isOkToCall(testPhone, ServiceState.STATE_IN_SERVICE, true));
+
+ mConnection.setDisconnected(null);
+ }
+
+ @Test
+ public void testDomainSelectionNormalRoutingEmergencyNumber_exitingApm_DiscardDialing()
+ throws Exception {
+ when(mDeviceState.isAirplaneModeOn(any())).thenReturn(true);
+ Phone testPhone = setupConnectionServiceInApmForDomainSelection(true);
+
+ ArgumentCaptor<RadioOnStateListener.Callback> callback =
+ ArgumentCaptor.forClass(RadioOnStateListener.Callback.class);
+ verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true),
+ eq(testPhone), eq(false), eq(TIMEOUT_TO_DYNAMIC_ROUTING_MS));
+
+ mConnection.setDisconnected(null);
+
+ assertTrue(callback.getValue()
+ .isOkToCall(testPhone, ServiceState.STATE_POWER_OFF, false));
}
@Test
@@ -2652,6 +2794,7 @@
setupForDialForDomainSelection(mPhone0, selectedDomain, true);
doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
+ doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
TestTelephonyConnection c = setupForReDialForDomainSelection(
mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
@@ -2662,13 +2805,22 @@
assertTrue(mTestConnectionService.maybeReselectDomain(c, reasonInfo, true,
android.telephony.DisconnectCause.NOT_VALID));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
@@ -2693,6 +2845,7 @@
setupForDialForDomainSelection(mPhone0, selectedDomain, true);
doReturn(mPhone0).when(mImsPhone).getDefaultPhone();
+ doReturn(mInternalConnection).when(mPhone0).dial(anyString(), any(), any());
TestTelephonyConnection c = setupForReDialForDomainSelection(
mImsPhone, selectedDomain, preciseDisconnectCause, disconnectCause, false);
@@ -2703,13 +2856,22 @@
assertTrue(mTestConnectionService.maybeReselectDomain(c, reasonInfo, true,
android.telephony.DisconnectCause.NOT_VALID));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
ArgumentCaptor<DialArgs> argsCaptor = ArgumentCaptor.forClass(DialArgs.class);
verify(mPhone0).dial(anyString(), argsCaptor.capture(), any());
@@ -2766,7 +2928,7 @@
DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
- assertEquals(mPhone1.getPhoneId(), attr.getSlotId());
+ assertEquals(mPhone1.getPhoneId(), attr.getSlotIndex());
}
@Test
@@ -2812,7 +2974,7 @@
DomainSelectionService.SelectionAttributes attr = attrCaptor.getValue();
- assertEquals(mPhone1.getPhoneId(), attr.getSlotId());
+ assertEquals(mPhone1.getPhoneId(), attr.getSlotIndex());
}
@Test
@@ -2831,6 +2993,11 @@
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ TelephonyConnection c = mTestConnectionService.getEmergencyConnection();
+
+ assertNotNull(c);
+ assertNull(c.getOriginalConnection());
+
ArgumentCaptor<DomainSelectionConnection.DomainSelectionConnectionCallback> callbackCaptor =
ArgumentCaptor.forClass(
DomainSelectionConnection.DomainSelectionConnectionCallback.class);
@@ -2846,7 +3013,34 @@
callback.onSelectionTerminated(ERROR_UNSPECIFIED);
verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
- verify(mEmergencyStateTracker).endCall(eq(TELECOM_CALL_ID1));
+ verify(mEmergencyStateTracker).endCall(eq(c));
+
+ android.telecom.DisconnectCause disconnectCause = c.getDisconnectCause();
+
+ assertNotNull(disconnectCause);
+ assertEquals(ERROR_UNSPECIFIED, disconnectCause.getTelephonyDisconnectCause());
+ }
+
+ @Test
+ public void testDomainSelectionDialFailedByException() throws Exception {
+ setupForCallTest();
+
+ int selectedDomain = DOMAIN_CS;
+
+ setupForDialForDomainSelection(mPhone0, selectedDomain, true);
+
+ CallStateException cse = new CallStateException(CallStateException.ERROR_CALLING_DISABLED,
+ "Calling disabled via ro.telephony.disable-call property");
+ doThrow(cse).when(mPhone0).dial(anyString(), any(), any());
+
+ mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
+ TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+
+ verify(mEmergencyStateTracker)
+ .startEmergencyCall(any(), any(), anyBoolean());
+ verify(mEmergencyCallDomainSelectionConnection).cancelSelection();
+ verify(mEmergencyStateTracker).endCall(any());
}
@Test
@@ -2859,26 +3053,23 @@
CompletableFuture<Integer> future = new CompletableFuture<>();
doReturn(future).when(mEmergencyStateTracker)
- .startEmergencyCall(any(), anyString(), eq(false));
+ .startEmergencyCall(any(), any(), 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);
+ .startEmergencyCall(eq(mPhone0), any(), eq(false));
// dialing is canceled
- mTestConnectionService.onLocalHangup(c);
+ mTestConnectionService.onLocalHangup(mTestConnectionService.getEmergencyConnection());
// startEmergencyCall has completed
future.complete(NOT_DISCONNECTED);
// verify that createEmergencyConnection is discarded
- verify(mEmergencyCallDomainSelectionConnection, times(0))
+ verify(mEmergencyCallDomainSelectionConnection, never())
.createEmergencyConnection(any(), any());
}
@@ -2900,17 +3091,14 @@
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
- TelephonyConnection c = new TestTelephonyConnection();
- c.setTelecomCallId(TELECOM_CALL_ID1);
-
// dialing is canceled
- mTestConnectionService.onLocalHangup(c);
+ mTestConnectionService.onLocalHangup(mTestConnectionService.getEmergencyConnection());
// domain selection has completed
future.complete(selectedDomain);
// verify that dialing is discarded
- verify(mPhone0, times(0)).dial(anyString(), any(), any());
+ verify(mPhone0, never()).dial(anyString(), any(), any());
}
@Test
@@ -2923,7 +3111,6 @@
TestTelephonyConnection c = setupForReDialForDomainSelection(
mPhone0, selectedDomain, preciseDisconnectCause, disconnectCause, true);
- c.setTelecomCallId(TELECOM_CALL_ID1);
CompletableFuture<Integer> future = new CompletableFuture<>();
doReturn(future).when(mEmergencyCallDomainSelectionConnection)
@@ -2960,20 +3147,28 @@
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));
+ .startEmergencyCall(any(), any(), eq(false));
ImsReasonInfo reasonInfo = new ImsReasonInfo(CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null);
assertTrue(mTestConnectionService.maybeReselectDomain(c, reasonInfo, true,
android.telephony.DisconnectCause.NOT_VALID));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mEmergencyStateTracker)
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
// dialing is canceled
mTestConnectionService.onLocalHangup(c);
@@ -3002,7 +3197,6 @@
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)
@@ -3021,7 +3215,7 @@
future.complete(selectedDomain);
// verify that dialing is discarded
- verify(mPhone0, times(0)).dial(anyString(), any(), any());
+ verify(mPhone0, never()).dial(anyString(), any(), any());
}
@Test
@@ -3036,15 +3230,25 @@
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mSatelliteSOSMessageRecommender).onEmergencyCallStarted(any());
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
verify(mPhone0).dial(anyString(), any(), any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
TestTelephonyConnection c = new TestTelephonyConnection();
+ mTestConnectionService.setEmergencyConnection(c);
c.setTelecomCallId(TELECOM_CALL_ID1);
c.setIsImsConnection(true);
Connection orgConn = c.getOriginalConnection();
@@ -3058,10 +3262,10 @@
connectionListener.onOriginalConnectionConfigured(c);
verify(mEmergencyStateTracker, times(1)).onEmergencyCallDomainUpdated(
- eq(PhoneConstants.PHONE_TYPE_IMS), eq(TELECOM_CALL_ID1));
+ eq(PhoneConstants.PHONE_TYPE_IMS), eq(c));
verify(mEmergencyStateTracker, times(0)).onEmergencyCallStateChanged(
- any(), eq(TELECOM_CALL_ID1));
+ any(), eq(c));
verify(mSatelliteSOSMessageRecommender, times(0))
.onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
@@ -3072,7 +3276,7 @@
// ACTIVE sate is notified
verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
- eq(Call.State.ACTIVE), eq(TELECOM_CALL_ID1));
+ eq(Call.State.ACTIVE), eq(c));
verify(mSatelliteSOSMessageRecommender, times(1))
.onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1),
eq(android.telecom.Connection.STATE_ACTIVE));
@@ -3085,7 +3289,7 @@
// state change not notified any more after CONNECTED once
verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
- any(), eq(TELECOM_CALL_ID1));
+ any(), eq(c));
verify(mSatelliteSOSMessageRecommender, times(1))
.onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
@@ -3097,7 +3301,7 @@
// state change not notified any more after CONNECTED once
verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
- any(), eq(TELECOM_CALL_ID1));
+ any(), eq(c));
verify(mSatelliteSOSMessageRecommender, times(1))
.onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
@@ -3109,7 +3313,7 @@
// domain change notified
verify(mEmergencyStateTracker, times(1)).onEmergencyCallDomainUpdated(
- eq(PhoneConstants.PHONE_TYPE_GSM), eq(TELECOM_CALL_ID1));
+ eq(PhoneConstants.PHONE_TYPE_GSM), eq(c));
// state change to DISCONNECTED
c.setDisconnected(null);
@@ -3119,7 +3323,7 @@
// state change not notified
verify(mEmergencyStateTracker, times(1)).onEmergencyCallStateChanged(
- any(), eq(TELECOM_CALL_ID1));
+ any(), eq(c));
verify(mSatelliteSOSMessageRecommender, times(1))
.onEmergencyCallConnectionStateChanged(eq(TELECOM_CALL_ID1), anyInt());
}
@@ -3136,15 +3340,24 @@
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1,
TEST_EMERGENCY_NUMBER, TELECOM_CALL_ID1));
+ ArgumentCaptor<android.telecom.Connection> connectionCaptor =
+ ArgumentCaptor.forClass(android.telecom.Connection.class);
+
verify(mDomainSelectionResolver)
.getDomainSelectionConnection(eq(mPhone0), eq(SELECTOR_TYPE_CALLING), eq(true));
verify(mEmergencyStateTracker)
- .startEmergencyCall(eq(mPhone0), eq(TELECOM_CALL_ID1), eq(false));
+ .startEmergencyCall(eq(mPhone0), connectionCaptor.capture(), eq(false));
verify(mEmergencyCallDomainSelectionConnection).createEmergencyConnection(any(), any());
verify(mPhone0).dial(anyString(), any(), any());
+ android.telecom.Connection tc = connectionCaptor.getValue();
+
+ assertNotNull(tc);
+ assertEquals(TELECOM_CALL_ID1, tc.getTelecomCallId());
+ assertEquals(mTestConnectionService.getEmergencyConnection(), tc);
+
TestTelephonyConnection c = new TestTelephonyConnection();
- c.setTelecomCallId(TELECOM_CALL_ID1);
+ mTestConnectionService.setEmergencyConnection(c);
c.setIsImsConnection(true);
Connection orgConn = c.getOriginalConnection();
doReturn(PhoneConstants.PHONE_TYPE_IMS).when(orgConn).getPhoneType();
@@ -3156,18 +3369,18 @@
connectionListener.onConnectionPropertiesChanged(c, PROPERTY_WIFI);
verify(mEmergencyStateTracker, times(0)).onEmergencyCallPropertiesChanged(
- anyInt(), anyString());
+ anyInt(), any());
doReturn(Call.State.ACTIVE).when(orgConn).getState();
connectionListener.onConnectionPropertiesChanged(c, PROPERTY_WIFI);
verify(mEmergencyStateTracker, times(1)).onEmergencyCallPropertiesChanged(
- eq(PROPERTY_WIFI), eq(TELECOM_CALL_ID1));
+ eq(PROPERTY_WIFI), eq(c));
connectionListener.onConnectionPropertiesChanged(c, 0);
verify(mEmergencyStateTracker, times(1)).onEmergencyCallPropertiesChanged(
- eq(0), eq(TELECOM_CALL_ID1));
+ eq(0), eq(c));
}
@Test
@@ -3276,11 +3489,13 @@
public void testNormalCallSatelliteEnabled() {
setupForCallTest();
doReturn(true).when(mSatelliteController).isSatelliteEnabled();
+
mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
DisconnectCause disconnectCause = mConnection.getDisconnectCause();
assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
disconnectCause.getTelephonyDisconnectCause());
+ assertEquals(DISCONNECT_REASON_SATELLITE_ENABLED, disconnectCause.getReason());
}
@Test
@@ -3289,30 +3504,53 @@
setupForCallTest();
// Call is not supported while using satellite
- NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
- .setIsNonTerrestrialNetwork(true)
- .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
- .build();
- ServiceState ss = new ServiceState();
- ss.addNetworkRegistrationInfo(nri);
- when(mPhone0.getServiceState()).thenReturn(ss);
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+ when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
+ .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
+
mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
DisconnectCause disconnectCause = mConnection.getDisconnectCause();
assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
disconnectCause.getTelephonyDisconnectCause());
+ assertEquals(DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE, disconnectCause.getReason());
// Call is supported while using satellite
- nri = new NetworkRegistrationInfo.Builder()
- .setIsNonTerrestrialNetwork(true)
- .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE))
- .build();
- ss.addNetworkRegistrationInfo(nri);
+ when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
+ .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE));
+
+ // UnsupportedOperationException is thrown as we cannot perform actual call
+ assertThrows(UnsupportedOperationException.class, () -> mTestConnectionService
+ .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", "TC@2")));
+ }
+
+ @Test
+ public void testNormalCallUsingSatelliteConnectedWithinHysteresisTime() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
+
+ // Call is not supported when device is connected to satellite within hysteresis time
+ setupForCallTest();
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+ when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
+ .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
+
mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
- createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", "TC@2"));
- disconnectCause = mConnection.getDisconnectCause();
- assertNotEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
+ DisconnectCause disconnectCause = mConnection.getDisconnectCause();
+ assertEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
disconnectCause.getTelephonyDisconnectCause());
+ assertEquals(DISCONNECT_REASON_CARRIER_ROAMING_SATELLITE_MODE, disconnectCause.getReason());
+
+ // Call is supported when device is connected to satellite within hysteresis time
+ setupForCallTest();
+ when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any())).thenReturn(
+ List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE));
+
+ // UnsupportedOperationException is thrown as we cannot perform actual call
+ assertThrows(UnsupportedOperationException.class, () -> mTestConnectionService
+ .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", "TC@2")));
}
@Test
@@ -3321,18 +3559,33 @@
setupForCallTest();
// Flag is disabled, so call is supported while using satellite
- NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
- .setIsNonTerrestrialNetwork(true)
- .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
- .build();
- ServiceState ss = new ServiceState();
- ss.addNetworkRegistrationInfo(nri);
- when(mPhone0.getServiceState()).thenReturn(ss);
- mConnection = mTestConnectionService.onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
- createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1));
- DisconnectCause disconnectCause = mConnection.getDisconnectCause();
- assertNotEquals(android.telephony.DisconnectCause.SATELLITE_ENABLED,
- disconnectCause.getTelephonyDisconnectCause());
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+ when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any())).thenReturn(
+ List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE));
+
+ // UnsupportedOperationException is thrown as we cannot perform actual call
+ assertThrows(UnsupportedOperationException.class, () -> mTestConnectionService
+ .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1)));
+ }
+
+ @Test
+ public void testNormalCallUsingNonTerrestrialNetwork_canMakeWifiCall() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
+
+ setupForCallTest();
+ // Call is not supported while using satellite
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+ when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
+ .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
+ // Wi-Fi call is possible
+ doReturn(true).when(mImsPhone).canMakeWifiCall();
+ when(mPhone0.getImsPhone()).thenReturn(mImsPhone);
+
+ // UnsupportedOperationException is thrown as we cannot perform actual call
+ assertThrows(UnsupportedOperationException.class, () -> mTestConnectionService
+ .onCreateOutgoingConnection(PHONE_ACCOUNT_HANDLE_1,
+ createConnectionRequest(PHONE_ACCOUNT_HANDLE_1, "1234", TELECOM_CALL_ID1)));
}
@Test
@@ -3349,6 +3602,50 @@
}
@Test
+ public void testIsAvailableForEmergencyCallsUsingNonTerrestrialNetwork_enableFlag() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
+
+ // Call is not supported while using satellite
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+ when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
+ .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA));
+ Phone mockPhone = Mockito.mock(Phone.class);
+ ServiceState ss = new ServiceState();
+ ss.setEmergencyOnly(true);
+ ss.setState(ServiceState.STATE_EMERGENCY_ONLY);
+ when(mockPhone.getServiceState()).thenReturn(ss);
+
+ assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
+ assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
+ assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+ }
+
+ @Test
+ public void testIsAvailableForEmergencyCallsUsingNonTerrestrialNetwork_disableFlag() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
+
+ // Call is supported while using satellite
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+ when(mSatelliteController.getCapabilitiesForCarrierRoamingSatelliteMode(any()))
+ .thenReturn(List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE));
+ Phone mockPhone = Mockito.mock(Phone.class);
+ ServiceState ss = new ServiceState();
+ ss.setEmergencyOnly(true);
+ ss.setState(ServiceState.STATE_EMERGENCY_ONLY);
+ when(mockPhone.getServiceState()).thenReturn(ss);
+
+ assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY));
+ assertFalse(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL));
+ assertTrue(mTestConnectionService.isAvailableForEmergencyCalls(mockPhone,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN));
+ }
+
+ @Test
public void testIsAvailableForEmergencyCallsForEmergencyRoutingInEmergencyOnly() {
ServiceState mockService = Mockito.mock(ServiceState.class);
when(mockService.isEmergencyOnly()).thenReturn(true);
@@ -3461,6 +3758,30 @@
NORMAL_ROUTED_EMERGENCY_NUMBER));
}
+ /**
+ * Verify where there are two sims, we choose the sim in emergency callback mode for the
+ * next emergency call.
+ */
+ @Test
+ public void testGetPhoneInEmergencyCallbackModeMultiSim() {
+ Phone mockPhone1 = Mockito.mock(Phone.class);
+ Phone mockPhone2 = Mockito.mock(Phone.class);
+
+ when(mPhoneFactoryProxy.getPhones()).thenReturn(
+ new Phone[] {mockPhone1, mockPhone2});
+
+ doReturn(false).when(mEmergencyStateTracker).isInEcm(eq(mockPhone1));
+ doReturn(true).when(mEmergencyStateTracker).isInEcm(eq(mockPhone2));
+
+ // Only applicable for AP domain seleciton service
+ assertNull(mTestConnectionService.getPhoneInEmergencyCallbackMode());
+
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+
+ assertEquals(mockPhone2,
+ mTestConnectionService.getPhoneInEmergencyCallbackMode());
+ }
+
private void setupMockEmergencyNumbers(Phone mockPhone, List<EmergencyNumber> numbers) {
EmergencyNumberTracker emergencyNumberTracker = Mockito.mock(EmergencyNumberTracker.class);
// Yuck. There should really be a fake emergency number class which makes it easy to inject
@@ -3503,9 +3824,54 @@
doReturn(mImsPhone).when(mockPhone).getImsPhone();
}
+ private Phone setupConnectionServiceInApmForDomainSelection(boolean normalRouting) {
+ ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
+ .setAccountHandle(PHONE_ACCOUNT_HANDLE_1)
+ .setAddress(TEST_ADDRESS)
+ .build();
+ Phone testPhone0 = makeTestPhone(0 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+ false /*isEmergencyOnly*/);
+ Phone testPhone1 = makeTestPhone(1 /*phoneId*/, ServiceState.STATE_POWER_OFF,
+ false /*isEmergencyOnly*/);
+ doReturn(GSM_PHONE).when(testPhone0).getPhoneType();
+ doReturn(GSM_PHONE).when(testPhone1).getPhoneType();
+ List<Phone> phones = new ArrayList<>(2);
+ doReturn(false).when(testPhone0).isRadioOn();
+ doReturn(false).when(testPhone1).isRadioOn();
+ phones.add(testPhone0);
+ phones.add(testPhone1);
+ setPhones(phones);
+ setupHandleToPhoneMap(PHONE_ACCOUNT_HANDLE_1, testPhone0);
+ setupDeviceConfig(testPhone0, testPhone1, 0);
+ setupForDialForDomainSelection(testPhone0, DOMAIN_CS, false);
+
+ EmergencyNumber emergencyNumber;
+ if (normalRouting) {
+ emergencyNumber = new EmergencyNumber(TEST_ADDRESS.getSchemeSpecificPart(), "", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ Collections.emptyList(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_DATABASE,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_NORMAL);
+ } else {
+ emergencyNumber = setupEmergencyNumber(TEST_ADDRESS);
+ }
+ doReturn(true).when(mTelephonyManagerProxy).isCurrentEmergencyNumber(anyString());
+ doReturn(emergencyNumber).when(mEmergencyNumberTracker).getEmergencyNumber(anyString());
+ doReturn(Arrays.asList(emergencyNumber)).when(mEmergencyNumberTracker).getEmergencyNumbers(
+ anyString());
+ doReturn(2).when(mTelephonyManagerProxy).getPhoneCount();
+
+ mConnection = mTestConnectionService.onCreateOutgoingConnection(
+ PHONE_ACCOUNT_HANDLE_1, connectionRequest);
+ assertNotNull("test connection was not set up correctly.", mConnection);
+
+ return testPhone0;
+ }
+
private TestTelephonyConnection setupForReDialForDomainSelection(
Phone mockPhone, int domain, int preciseDisconnectCause,
int disconnectCause, boolean fromEmergency) throws Exception {
+ TestTelephonyConnection c = new TestTelephonyConnection();
try {
if (fromEmergency) {
doReturn(CompletableFuture.completedFuture(domain))
@@ -3514,8 +3880,8 @@
replaceInstance(TelephonyConnectionService.class,
"mEmergencyCallDomainSelectionConnection",
mTestConnectionService, mEmergencyCallDomainSelectionConnection);
- replaceInstance(TelephonyConnectionService.class, "mEmergencyCallId",
- mTestConnectionService, TELECOM_CALL_ID1);
+ replaceInstance(TelephonyConnectionService.class, "mEmergencyConnection",
+ mTestConnectionService, c);
} else {
doReturn(CompletableFuture.completedFuture(domain))
.when(mNormalCallDomainSelectionConnection).reselectDomain(any());
@@ -3529,7 +3895,6 @@
doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
- TestTelephonyConnection c = new TestTelephonyConnection();
c.setTelecomCallId(TELECOM_CALL_ID1);
c.setMockPhone(mockPhone);
c.setAddress(TEST_ADDRESS, TelecomManager.PRESENTATION_ALLOWED);
diff --git a/tests/src/com/android/services/telephony/domainselection/CarrierConfigHelperTest.java b/tests/src/com/android/services/telephony/domainselection/CarrierConfigHelperTest.java
deleted file mode 100644
index 5d4fe17..0000000
--- a/tests/src/com/android/services/telephony/domainselection/CarrierConfigHelperTest.java
+++ /dev/null
@@ -1,277 +0,0 @@
-/*
- * 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.AccessNetworkConstants.AccessNetworkType.EUTRAN;
-import static android.telephony.AccessNetworkConstants.AccessNetworkType.NGRAN;
-import static android.telephony.CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL;
-import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY;
-
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.assertNotNull;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.content.res.Resources;
-import android.os.HandlerThread;
-import android.os.Looper;
-import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
-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.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.concurrent.Executor;
-
-/**
- * Unit tests for CarrierConfigHelper
- */
-public class CarrierConfigHelperTest {
- private static final String TAG = "CarrierConfigHelperTest";
-
- private static final int SLOT_0 = 0;
- private static final int SLOT_1 = 1;
- private static final int SUB_1 = 1;
- private static final int TEST_SIM_CARRIER_ID = 1911;
-
- @Mock private Context mContext;
- @Mock private SharedPreferences mSharedPreferences;
- @Mock private SharedPreferences.Editor mEditor;
- @Mock private Resources mResources;
-
- private HandlerThread mHandlerThread;
- private TestableLooper mLooper;
- private CarrierConfigHelper mCarrierConfigHelper;
- private CarrierConfigManager mCarrierConfigManager;
- private TelephonyManager mTelephonyManager;
-
- @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 "";
- }
-
- @Override
- public Resources getResources() {
- return mResources;
- }
- };
-
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
-
- mHandlerThread = new HandlerThread("CarrierConfigHelperTest");
- mHandlerThread.start();
-
- try {
- mLooper = new TestableLooper(mHandlerThread.getLooper());
- } catch (Exception e) {
- logd("Unable to create looper from handler.");
- }
-
- doReturn(mEditor).when(mSharedPreferences).edit();
-
- mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
- mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
- doReturn(2).when(mTelephonyManager).getActiveModemCount();
- doReturn(TelephonyManager.SIM_STATE_READY)
- .when(mTelephonyManager).getSimState(anyInt());
-
- doReturn(new int[] { TEST_SIM_CARRIER_ID }).when(mResources).getIntArray(anyInt());
-
- mCarrierConfigHelper = new CarrierConfigHelper(mContext, mHandlerThread.getLooper(),
- mSharedPreferences);
- }
-
- @After
- public void tearDown() throws Exception {
- if (mCarrierConfigHelper != null) {
- mCarrierConfigHelper.destroy();
- mCarrierConfigHelper = null;
- }
-
- if (mLooper != null) {
- mLooper.destroy();
- mLooper = null;
- }
- }
-
- @Test
- public void testInit() throws Exception {
- ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
- ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
- ArgumentCaptor<Executor> executorCaptor = ArgumentCaptor.forClass(Executor.class);
-
- verify(mCarrierConfigManager).registerCarrierConfigChangeListener(executorCaptor.capture(),
- callbackCaptor.capture());
- assertNotNull(executorCaptor.getValue());
- assertNotNull(callbackCaptor.getValue());
- assertFalse(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_0));
- }
-
- @Test
- public void testCarrierConfigNotApplied() throws Exception {
- ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
- ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
-
- verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
- callbackCaptor.capture());
-
- CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
-
- assertNotNull(callback);
-
- // NR is included but carrier config is not applied.
- PersistableBundle b = getPersistableBundle(new int[] { EUTRAN, NGRAN }, false);
- doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
- callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
-
- assertFalse(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_0));
- }
-
- @Test
- public void testCarrierConfigApplied() throws Exception {
- ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
- ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
-
- verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
- callbackCaptor.capture());
-
- CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
-
- assertNotNull(callback);
-
- // NR is included and carrier config is applied.
- PersistableBundle b = getPersistableBundle(new int[] { EUTRAN, NGRAN }, true);
- doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
- callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
-
- assertTrue(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_0));
- assertFalse(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_1));
-
- verify(mEditor).putBoolean(eq(CarrierConfigHelper.KEY_VONR_EMERGENCY_SUPPORT + SLOT_0),
- eq(true));
-
- // NR is not included and carrier config is applied.
- b = getPersistableBundle(new int[] { EUTRAN }, true);
- doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
- callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
-
- assertFalse(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_0));
-
- verify(mEditor).putBoolean(eq(CarrierConfigHelper.KEY_VONR_EMERGENCY_SUPPORT + SLOT_0),
- eq(false));
- }
-
- @Test
- public void testCarrierConfigInvalidSubId() throws Exception {
- ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
- ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
-
- verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
- callbackCaptor.capture());
-
- CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
-
- assertNotNull(callback);
-
- // NR is included and carrier config is applied.
- PersistableBundle b = getPersistableBundle(new int[] { EUTRAN, NGRAN }, true);
- doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
-
- // Invalid subscription
- callback.onCarrierConfigChanged(SLOT_0, SubscriptionManager.INVALID_SUBSCRIPTION_ID, 0, 0);
-
- assertFalse(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_0));
- }
-
- @Test
- public void testRestoreFromSharedPreferences() throws Exception {
- doReturn(true).when(mSharedPreferences).getBoolean(anyString(), anyBoolean());
- mCarrierConfigHelper = new CarrierConfigHelper(mContext, mHandlerThread.getLooper(),
- mSharedPreferences);
-
- assertTrue(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_0));
- }
-
- @Test
- public void testCarrierIgnoreNrWhenSimRemoved() throws Exception {
- ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
- ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
-
- verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
- callbackCaptor.capture());
-
- CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
-
- assertNotNull(callback);
-
- // NR is included and carrier config for TEST SIM is applied.
- PersistableBundle b = getPersistableBundle(new int[] { EUTRAN, NGRAN }, true);
- doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
- callback.onCarrierConfigChanged(SLOT_0, SUB_1, TEST_SIM_CARRIER_ID, 0);
-
- // NR is ignored.
- assertFalse(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_0));
- assertFalse(mCarrierConfigHelper.isVoNrEmergencySupported(SLOT_1));
- }
-
- private static PersistableBundle getPersistableBundle(int[] imsRats, boolean applied) {
- PersistableBundle bundle = new PersistableBundle();
- bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY, imsRats);
- bundle.putBoolean(KEY_CARRIER_CONFIG_APPLIED_BOOL, applied);
- return bundle;
- }
-
- private static void logd(String str) {
- Log.d(TAG, str);
- }
-}
diff --git a/tests/src/com/android/services/telephony/domainselection/DataConnectionStateHelperTest.java b/tests/src/com/android/services/telephony/domainselection/DataConnectionStateHelperTest.java
new file mode 100644
index 0000000..8d950c2
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/DataConnectionStateHelperTest.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2024 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.TRANSPORT_TYPE_WWAN;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.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.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.LinkProperties;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PreciseDataConnectionState;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
+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.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Unit tests for DataConnectionStateHelper
+ */
+public class DataConnectionStateHelperTest {
+ private static final String TAG = "DataConnectionStateHelperTest";
+
+ private static final int SLOT_0 = 0;
+ private static final int SLOT_1 = 1;
+ private static final int SUB_1 = 1;
+ private static final int SUB_2 = 2;
+
+ @Mock private TelephonyManager mTm1;
+ @Mock private TelephonyManager mTm2;
+ @Mock private EmergencyCallDomainSelector mDomainSelector;
+
+ private Context mContext;
+ private HandlerThread mHandlerThread;
+ private TestableLooper mLooper;
+ private DataConnectionStateHelper mEpdnHelper;
+ private CarrierConfigManager mCarrierConfigManager;
+ private TelephonyManager mTelephonyManager;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ mContext = new TestContext() {
+ private Intent mIntent;
+
+ @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 "";
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ return mIntent;
+ }
+
+ @Override
+ public void sendStickyBroadcast(Intent intent) {
+ mIntent = intent;
+ }
+ };
+
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+
+ mHandlerThread = new HandlerThread("DataConnectionStateHelperTest");
+ mHandlerThread.start();
+
+ try {
+ mLooper = new TestableLooper(mHandlerThread.getLooper());
+ } catch (Exception e) {
+ logd("Unable to create looper from handler.");
+ }
+
+ mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+ mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+ doReturn(mTm1).when(mTelephonyManager).createForSubscriptionId(eq(SUB_1));
+ doReturn(mTm2).when(mTelephonyManager).createForSubscriptionId(eq(SUB_2));
+
+ mEpdnHelper = new DataConnectionStateHelper(mContext, mHandlerThread.getLooper());
+ mEpdnHelper.setEmergencyCallDomainSelector(mDomainSelector);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mEpdnHelper != null) {
+ mEpdnHelper.destroy();
+ mEpdnHelper = null;
+ }
+
+ if (mLooper != null) {
+ mLooper.destroy();
+ mLooper = null;
+ }
+ }
+
+ @Test
+ public void testInit() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+ ArgumentCaptor<Executor> executorCaptor = ArgumentCaptor.forClass(Executor.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(executorCaptor.capture(),
+ callbackCaptor.capture());
+ assertNotNull(executorCaptor.getValue());
+ assertNotNull(callbackCaptor.getValue());
+ }
+
+ @Test
+ public void testCarrierConfigChanged() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
+ callbackCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+
+ verify(mTelephonyManager).createForSubscriptionId(eq(SUB_1));
+
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor1 =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+
+ // TelephonyCallback for SUB_1 registered
+ verify(mTm1).registerTelephonyCallback(any(), telephonyCallbackCaptor1.capture());
+
+ assertNotNull(telephonyCallbackCaptor1.getValue());
+
+ callback.onCarrierConfigChanged(SLOT_1, SUB_2, 0, 0);
+
+ verify(mTelephonyManager).createForSubscriptionId(eq(SUB_2));
+
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor2 =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+
+ // TelephonyCallback for SUB_2 registered
+ verify(mTm2).registerTelephonyCallback(any(), telephonyCallbackCaptor2.capture());
+
+ assertNotNull(telephonyCallbackCaptor2.getValue());
+
+ verify(mTm1, never()).unregisterTelephonyCallback(any());
+ verify(mTm2, never()).unregisterTelephonyCallback(any());
+ }
+
+ @Test
+ public void testSubscriptionChangedOnTheSameSlot() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
+ callbackCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+
+ verify(mTelephonyManager).createForSubscriptionId(eq(SUB_1));
+
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor1 =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+
+ // TelephonyCallback for SUB_1 registered
+ verify(mTm1).registerTelephonyCallback(any(), telephonyCallbackCaptor1.capture());
+
+ TelephonyCallback telephonyCallback1 = telephonyCallbackCaptor1.getValue();
+
+ assertNotNull(telephonyCallback1);
+
+ // Subscription changed
+ callback.onCarrierConfigChanged(SLOT_0, SUB_2, 0, 0);
+
+ // TelephonyCallback for SUB_1 unregistered
+ verify(mTelephonyManager).unregisterTelephonyCallback(eq(telephonyCallback1));
+
+ verify(mTelephonyManager).createForSubscriptionId(eq(SUB_2));
+
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor2 =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+
+ // TelephonyCallback for SUB_2 registered
+ verify(mTm2).registerTelephonyCallback(any(), telephonyCallbackCaptor2.capture());
+
+ TelephonyCallback telephonyCallback2 = telephonyCallbackCaptor2.getValue();
+
+ assertNotNull(telephonyCallback2);
+ }
+
+ @Test
+ public void testDataConnectionStateChanged() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
+ callbackCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+
+ verify(mTelephonyManager).createForSubscriptionId(eq(SUB_1));
+
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor1 =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+
+ // TelephonyCallback for SUB_1 registered
+ verify(mTm1).registerTelephonyCallback(any(), telephonyCallbackCaptor1.capture());
+
+ TelephonyCallback cb1 = telephonyCallbackCaptor1.getValue();
+
+ assertNotNull(cb1);
+ assertTrue(cb1 instanceof TelephonyCallback.PreciseDataConnectionStateListener);
+
+ callback.onCarrierConfigChanged(SLOT_1, SUB_2, 0, 0);
+
+ verify(mTelephonyManager).createForSubscriptionId(eq(SUB_2));
+
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor2 =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+
+ // TelephonyCallback for SUB_2 registered
+ verify(mTm2).registerTelephonyCallback(any(), telephonyCallbackCaptor2.capture());
+
+ TelephonyCallback cb2 = telephonyCallbackCaptor2.getValue();
+
+ assertNotNull(cb2);
+ assertTrue(cb2 instanceof TelephonyCallback.PreciseDataConnectionStateListener);
+
+ TelephonyCallback.PreciseDataConnectionStateListener listener1 =
+ (TelephonyCallback.PreciseDataConnectionStateListener) cb1;
+ TelephonyCallback.PreciseDataConnectionStateListener listener2 =
+ (TelephonyCallback.PreciseDataConnectionStateListener) cb2;
+
+ PreciseDataConnectionState state = getPreciseDataConnectionState(
+ ApnSetting.TYPE_DEFAULT, TelephonyManager.DATA_CONNECTED);
+ listener1.onPreciseDataConnectionStateChanged(state);
+ listener2.onPreciseDataConnectionStateChanged(state);
+
+ verify(mDomainSelector, never()).notifyDataConnectionStateChange(anyInt(), anyInt());
+ verify(mDomainSelector, never()).notifyDataConnectionStateChange(anyInt(), anyInt());
+
+ state = getPreciseDataConnectionState(
+ ApnSetting.TYPE_EMERGENCY, TelephonyManager.DATA_CONNECTED);
+ listener1.onPreciseDataConnectionStateChanged(state);
+ listener2.onPreciseDataConnectionStateChanged(state);
+
+ verify(mDomainSelector, times(1)).notifyDataConnectionStateChange(
+ eq(SLOT_0), eq(TelephonyManager.DATA_CONNECTED));
+ verify(mDomainSelector, times(1)).notifyDataConnectionStateChange(
+ eq(SLOT_1), eq(TelephonyManager.DATA_CONNECTED));
+
+ state = getPreciseDataConnectionState(
+ ApnSetting.TYPE_EMERGENCY, TelephonyManager.DATA_DISCONNECTING);
+ listener1.onPreciseDataConnectionStateChanged(state);
+ listener2.onPreciseDataConnectionStateChanged(state);
+
+ verify(mDomainSelector, times(1)).notifyDataConnectionStateChange(
+ eq(SLOT_0), eq(TelephonyManager.DATA_DISCONNECTING));
+ verify(mDomainSelector, times(1)).notifyDataConnectionStateChange(
+ eq(SLOT_1), eq(TelephonyManager.DATA_DISCONNECTING));
+
+ state = getPreciseDataConnectionState(
+ ApnSetting.TYPE_EMERGENCY, TelephonyManager.DATA_DISCONNECTED);
+ listener1.onPreciseDataConnectionStateChanged(state);
+ listener2.onPreciseDataConnectionStateChanged(state);
+
+ verify(mDomainSelector, times(1)).notifyDataConnectionStateChange(
+ eq(SLOT_0), eq(TelephonyManager.DATA_DISCONNECTED));
+ verify(mDomainSelector, times(1)).notifyDataConnectionStateChange(
+ eq(SLOT_1), eq(TelephonyManager.DATA_DISCONNECTED));
+ }
+
+ @Test
+ public void testEmergencyCallbackModeEnter() throws Exception {
+ // Enter ECBM on slot 1
+ mContext.sendStickyBroadcast(getIntent(true, SLOT_1));
+
+ assertFalse(mEpdnHelper.isInEmergencyCallbackMode(SLOT_0));
+ assertTrue(mEpdnHelper.isInEmergencyCallbackMode(SLOT_1));
+ }
+
+ @Test
+ public void testEmergencyCallbackModeExit() throws Exception {
+ // Exit ECBM
+ mContext.sendStickyBroadcast(getIntent(false, SLOT_0));
+
+ assertFalse(mEpdnHelper.isInEmergencyCallbackMode(SLOT_0));
+ }
+
+ private static Intent getIntent(boolean inEcm, int slotIndex) {
+ Intent intent = new Intent(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
+ intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, inEcm);
+ intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, slotIndex);
+ return intent;
+ }
+
+ private static PreciseDataConnectionState getPreciseDataConnectionState(
+ int apnType, int state) {
+ return new PreciseDataConnectionState.Builder()
+ .setTransportType(TRANSPORT_TYPE_WWAN)
+ .setId(1)
+ .setState(state)
+ .setNetworkType(TelephonyManager.NETWORK_TYPE_LTE)
+ .setApnSetting(new ApnSetting.Builder()
+ .setApnTypeBitmask(apnType)
+ .setApnName("default")
+ .setEntryName("default")
+ .build())
+ .setLinkProperties(new LinkProperties())
+ .setFailCause(0)
+ .build();
+ }
+
+ 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
index 74c3311..872238c 100644
--- a/tests/src/com/android/services/telephony/domainselection/DomainSelectorBaseTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/DomainSelectorBaseTest.java
@@ -26,8 +26,8 @@
import android.os.Looper;
import android.telephony.DomainSelectionService.SelectionAttributes;
import android.telephony.TransportSelectorCallback;
-import android.test.suitebuilder.annotation.SmallTest;
+import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.TestContext;
@@ -52,11 +52,6 @@
}
@Override
- public void cancelSelection() {
- // No operations.
- }
-
- @Override
public void reselectDomain(@NonNull SelectionAttributes attr) {
// No operations.
}
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
index eab40f9..fab7256 100644
--- a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
@@ -16,6 +16,8 @@
package com.android.services.telephony.domainselection;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
+import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN;
import static android.telephony.AccessNetworkConstants.AccessNetworkType.GERAN;
import static android.telephony.AccessNetworkConstants.AccessNetworkType.NGRAN;
@@ -37,9 +39,11 @@
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_IMS_REASONINFO_CODE_TO_RETRY_EMERGENCY_INT_ARRAY;
import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_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.KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_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;
@@ -51,11 +55,17 @@
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_ROAMING;
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN;
import static android.telephony.PreciseDisconnectCause.SERVICE_OPTION_NOT_AVAILABLE;
+import static android.telephony.TelephonyManager.DATA_CONNECTED;
+import static android.telephony.TelephonyManager.DATA_DISCONNECTED;
+import static android.telephony.TelephonyManager.DATA_DISCONNECTING;
+import static android.telephony.TelephonyManager.SIM_ACTIVATION_STATE_DEACTIVATED;
import static com.android.services.telephony.domainselection.EmergencyCallDomainSelector.MSG_MAX_CELLULAR_TIMEOUT;
import static com.android.services.telephony.domainselection.EmergencyCallDomainSelector.MSG_NETWORK_SCAN_TIMEOUT;
+import static com.android.services.telephony.domainselection.EmergencyCallDomainSelector.MSG_WAIT_DISCONNECTION_TIMEOUT;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -65,10 +75,12 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyVararg;
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.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -79,6 +91,8 @@
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
+import android.net.Uri;
+import android.os.CancellationSignal;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IPowerManager;
@@ -86,6 +100,7 @@
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.PowerManager;
+import android.telecom.PhoneAccount;
import android.telephony.AccessNetworkConstants;
import android.telephony.BarringInfo;
import android.telephony.CarrierConfigManager;
@@ -93,7 +108,7 @@
import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.DomainSelectionService.SelectionAttributes;
-import android.telephony.EmergencyRegResult;
+import android.telephony.EmergencyRegistrationResult;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PreciseDisconnectCause;
import android.telephony.SubscriptionManager;
@@ -102,17 +117,20 @@
import android.telephony.WwanSelectorCallback;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
+import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ProvisioningManager;
-import android.test.suitebuilder.annotation.SmallTest;
import android.testing.TestableLooper;
import android.util.Log;
import android.util.SparseArray;
+import androidx.test.filters.SmallTest;
+
import com.android.TestContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
@@ -130,6 +148,7 @@
private static final int SLOT_0 = 0;
private static final int SLOT_0_SUB_ID = 1;
+ private static final Uri TEST_URI = Uri.fromParts(PhoneAccount.SCHEME_TEL, "911", null);
@Mock private CarrierConfigManager mCarrierConfigManager;
@Mock private ConnectivityManager mConnectivityManager;
@@ -141,7 +160,7 @@
@Mock private DomainSelectorBase.DestroyListener mDestroyListener;
@Mock private ProvisioningManager mProvisioningManager;
@Mock private CrossSimRedialingController mCsrdCtrl;
- @Mock private CarrierConfigHelper mCarrierConfigHelper;
+ @Mock private DataConnectionStateHelper mEpdnHelper;
@Mock private Resources mResources;
private Context mContext;
@@ -153,7 +172,7 @@
private @AccessNetworkConstants.RadioAccessNetworkType List<Integer> mAccessNetwork;
private PowerManager mPowerManager;
private ConnectivityManager.NetworkCallback mNetworkCallback;
- private Consumer<EmergencyRegResult> mResultConsumer;
+ private Consumer<EmergencyRegistrationResult> mResultConsumer;
@Before
public void setUp() throws Exception {
@@ -220,7 +239,7 @@
when(mTelephonyManager.getActiveModemCount()).thenReturn(1);
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
- when(mCarrierConfigManager.getConfigForSubId(anyInt()))
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg()))
.thenReturn(getDefaultPersistableBundle());
mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
@@ -244,7 +263,6 @@
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 {
@@ -259,13 +277,16 @@
@Override
public Void answer(InvocationOnMock invocation) throws Throwable {
mAccessNetwork = (List<Integer>) invocation.getArguments()[0];
- mResultConsumer = (Consumer<EmergencyRegResult>) invocation.getArguments()[3];
+ mResultConsumer =
+ (Consumer<EmergencyRegistrationResult>) invocation.getArguments()[4];
return null;
}
}).when(mWwanSelectorCallback).onRequestEmergencyNetworkScan(
- any(), anyInt(), any(), any());
+ any(), anyInt(), anyBoolean(), any(), any());
when(mResources.getStringArray(anyInt())).thenReturn(null);
+
+ doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
}
@After
@@ -287,8 +308,70 @@
createSelector(SLOT_0_SUB_ID);
verify(mWwanSelectorCallback, times(0)).onRequestEmergencyNetworkScan(
- any(), anyInt(), any(), any());
+ any(), anyInt(), anyBoolean(), any(), any());
verify(mWwanSelectorCallback, times(0)).onDomainSelected(anyInt(), eq(true));
+ verify(mEpdnHelper).setEmergencyCallDomainSelector(eq(mDomainSelector));
+ }
+
+ @Test
+ public void testDestroyed() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+
+ EmergencyRegistrationResult 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();
+
+ mDomainSelector.destroy();
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(Integer.MAX_VALUE));
+ unsolBarringInfoChanged(false);
+
+ verify(mTransportSelectorCallback, never()).onWwanSelected(any());
+ verify(mEpdnHelper).setEmergencyCallDomainSelector(eq(null));
+ }
+
+ @Test
+ public void testDomainPreferenceConfigurationError() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_NON_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ verifyScanCsPreferred();
+ }
+
+ @Test
+ public void testNullEmergencyRegistrationResult() throws Exception {
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, null);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
}
@Test
@@ -296,7 +379,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -321,12 +405,13 @@
CarrierConfigManager.ImsEmergency.DOMAIN_CS
};
bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -347,7 +432,7 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(
+ EmergencyRegistrationResult 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);
@@ -360,7 +445,7 @@
verify(mTransportSelectorCallback, times(1)).onWwanSelected(any());
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), anyInt(), any(), any());
+ any(), anyInt(), anyBoolean(), any(), any());
}
@Test
@@ -373,7 +458,7 @@
doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
doReturn(new String[] {"jp"}).when(mResources).getStringArray(anyInt());
- EmergencyRegResult regResult = getEmergencyRegResult(
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(
UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "", "jp");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
@@ -392,7 +477,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -409,7 +495,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -426,7 +513,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -449,7 +537,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -468,9 +557,10 @@
//Extended service request failed
SelectionAttributes.Builder builder =
new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setCsDisconnectCause(SERVICE_OPTION_NOT_AVAILABLE)
.setEmergency(true)
- .setEmergencyRegResult(regResult);
+ .setEmergencyRegistrationResult(regResult);
attr = builder.build();
mDomainSelector.reselectDomain(attr);
processAllMessages();
@@ -479,11 +569,143 @@
}
@Test
+ public void testDefaultCombinedImsRegisteredSelectPsThenExtendedServiceRequestFailIsoMatch()
+ throws Exception {
+ doReturn(new String[] {"us"}).when(mResources).getStringArray(anyInt());
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "", "us");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+
+ //Extended service request failed
+ SelectionAttributes.Builder builder =
+ new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setCsDisconnectCause(SERVICE_OPTION_NOT_AVAILABLE)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult);
+ attr = builder.build();
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyScanCsPreferred();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredSelectPsThenExtendedServiceRequestFailIsoNotMatch()
+ throws Exception {
+ doReturn(new String[] {"us"}).when(mResources).getStringArray(anyInt());
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "", "zz");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+
+ //Extended service request failed
+ SelectionAttributes.Builder builder =
+ new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setCsDisconnectCause(SERVICE_OPTION_NOT_AVAILABLE)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult);
+ attr = builder.build();
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultCombinedImsRegisteredSelectPsThenNotExtendedServiceRequestFails()
+ throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ SelectionAttributes.Builder builder =
+ new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult);
+ attr = builder.build();
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultCombinedImsNotRegisteredDeactivatedSimSelectPs() throws Exception {
+ doReturn(SIM_ACTIVATION_STATE_DEACTIVATED).when(mTelephonyManager).getDataActivationState();
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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 testDefaultCombinedImsNotRegisteredSelectCs() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -496,16 +718,69 @@
}
@Test
- public void testNoCsCombinedImsNotRegisteredSelectPs() throws Exception {
+ public void testAirplaneDefaultCombinedImsNotRegisteredSelectPs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = new SelectionAttributes.Builder(
+ SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult)
+ .setExitedFromAirplaneMode(true)
+ .build();
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testAirplaneRequiresRegCombinedImsNotRegisteredSelectPs() 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);
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = new SelectionAttributes.Builder(
+ SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult)
+ .setExitedFromAirplaneMode(true)
+ .build();
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+ }
+
+ @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(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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);
@@ -522,7 +797,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -539,7 +815,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -556,7 +833,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -573,7 +851,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -590,7 +869,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -607,7 +887,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -624,7 +905,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -641,7 +923,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -658,7 +941,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -675,7 +959,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -692,7 +977,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -709,7 +995,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -726,7 +1013,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult 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);
@@ -743,7 +1031,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_CS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -756,11 +1045,96 @@
}
@Test
+ public void testNotSupportPsEmergency() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS,
+ false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ assertEquals(2, mAccessNetwork.size());
+ assertEquals(UTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(GERAN, (int) mAccessNetwork.get(1));
+ }
+
+ @Test
+ public void testNotSupportPsCombinedImsRegisteredSelectCs() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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 testNotSupportCsCombinedImsNotRegisteredSelectPs() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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 testDefaultEpsImsRegisteredBarredScanPsPreferred() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -777,7 +1151,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -794,7 +1169,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -811,7 +1187,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -828,7 +1205,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -845,7 +1223,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -862,7 +1241,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -879,7 +1259,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -896,7 +1277,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
false, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -913,7 +1295,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
false, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -930,7 +1313,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
false, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -947,7 +1331,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
false, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -964,7 +1349,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
false, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -981,7 +1367,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
false, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -998,7 +1385,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
false, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1015,7 +1403,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
false, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1032,7 +1421,7 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(
+ EmergencyRegistrationResult 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);
@@ -1047,12 +1436,13 @@
public void testVoLteOnEpsImsNotRegisteredSelectPs() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1069,7 +1459,7 @@
public void testVoLteOffEpsImsNotRegisteredScanCsPreferred() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_VOLTE_ENABLED_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
// Disable VoLTE.
when(mMmTelManager.isAdvancedCallingSettingEnabled()).thenReturn(false);
@@ -1077,7 +1467,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1094,12 +1485,13 @@
public void testRequiresRegEpsImsNotRegisteredScanCsPreferred() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1112,15 +1504,64 @@
}
@Test
+ public void testRequiresRegEpsImsNotRegisteredDeactivatedSimSelectPs() throws Exception {
+ doReturn(SIM_ACTIVATION_STATE_DEACTIVATED).when(mTelephonyManager).getDataActivationState();
+
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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 testRequiresRegEpsImsNotRegisteredEmcNotSupportedScanCsPreferred()
+ throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ 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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ mResultConsumer = null;
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1141,6 +1582,14 @@
mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_NETWORK_SCAN_TIMEOUT));
verify(mTransportSelectorCallback, times(1)).onWlanSelected(eq(true));
+
+ assertNotNull(mResultConsumer);
+
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ // Ignore the stale result
+ verify(mWwanSelectorCallback, never()).onDomainSelected(anyInt(), anyBoolean());
}
@Test
@@ -1149,12 +1598,13 @@
TelephonyManager.SIM_STATE_PIN_REQUIRED);
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1173,12 +1623,13 @@
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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1212,12 +1663,13 @@
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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1250,7 +1702,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1283,7 +1736,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_PS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1321,7 +1775,8 @@
doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
doReturn(new String[] {"jp"}).when(mResources).getStringArray(anyInt());
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ EmergencyRegistrationResult 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);
@@ -1335,6 +1790,37 @@
}
@Test
+ public void testDualSimInvalidSubscriptionAfterScan() 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();
+ doReturn(new String[] {"jp"}).when(mResources).getStringArray(anyInt());
+
+ EmergencyRegistrationResult 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();
+
+ assertNotNull(mResultConsumer);
+
+ regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "", "jp");
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(1))
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
+ }
+
+ @Test
public void testDualSimInvalidSubscriptionButNoOtherSlot() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -1344,7 +1830,8 @@
doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
doReturn(new String[] {"jp"}).when(mResources).getStringArray(anyInt());
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ EmergencyRegistrationResult 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);
@@ -1353,16 +1840,64 @@
bindImsServiceUnregistered();
processAllMessages();
- verify(mTransportSelectorCallback, times(0))
- .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
- verifyScanPsPreferred();
+ verify(mTransportSelectorCallback, times(1))
+ .onSelectionTerminated(eq(DisconnectCause.ICC_ERROR));
+ }
+
+ @Test
+ public void testDualSimNormalServiceOnTheOtherSubscription() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(2).when(mTelephonyManager).getActiveModemCount();
+ doReturn(true).when(mCsrdCtrl).isThereOtherSlotInService();
+ doReturn(new String[] {"in"}).when(mResources).getStringArray(anyInt());
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "", "in");
+ 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_TEMP_FAILURE));
}
@Test
public void testEutranWithCsDomainOnly() throws Exception {
setupForHandleScanResult();
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
+ DOMAIN_CS, false, false, 0, 0, "", "");
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testEutranWithPsDomainOnly() throws Exception {
+ setupForHandleScanResult();
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_HOME,
+ DOMAIN_PS, false, false, 0, 0, "", "");
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testUtran() throws Exception {
+ setupForHandleScanResult();
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
DOMAIN_CS, false, false, 0, 0, "", "");
mResultConsumer.accept(regResult);
processAllMessages();
@@ -1374,13 +1909,14 @@
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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
mResultConsumer = null;
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(UNKNOWN, REGISTRATION_STATE_UNKNOWN,
+ EmergencyRegistrationResult 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);
@@ -1390,28 +1926,79 @@
processAllMessages();
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), any(), any());
+ any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), eq(false), any(), any());
assertNotNull(mResultConsumer);
mResultConsumer.accept(regResult);
processAllMessages();
verify(mWwanSelectorCallback, times(2)).onRequestEmergencyNetworkScan(
- any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), any(), any());
+ any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), eq(false), any(), any());
}
@Test
- public void testFullServiceThenLimtedService() throws Exception {
+ public void testFullServiceInDomesticRoaming() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_FULL_SERVICE);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn("us").when(mTelephonyManager).getSimCountryIso();
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_ROAMING,
+ 0, true, false, 0, 0, "", "", "us");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onRequestEmergencyNetworkScan(
+ any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE),
+ anyBoolean(), any(), any());
+ }
+
+ @Test
+ public void testFullServiceInInterNationalRoaming() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_FULL_SERVICE);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn("us").when(mTelephonyManager).getSimCountryIso();
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_ROAMING,
+ 0, true, false, 0, 0, "", "", "zz");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onRequestEmergencyNetworkScan(
+ any(), eq(DomainSelectionService.SCAN_TYPE_NO_PREFERENCE),
+ anyBoolean(), any(), any());
+ }
+
+ @Test
+ public void testFullServiceThenLimitedService() 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);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
mResultConsumer = null;
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(UNKNOWN, REGISTRATION_STATE_UNKNOWN,
+ EmergencyRegistrationResult 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);
@@ -1421,14 +2008,15 @@
processAllMessages();
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), any(), any());
+ any(), eq(DomainSelectionService.SCAN_TYPE_FULL_SERVICE), eq(false), any(), any());
assertNotNull(mResultConsumer);
mResultConsumer.accept(regResult);
processAllMessages();
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), eq(DomainSelectionService.SCAN_TYPE_LIMITED_SERVICE), any(), any());
+ any(), eq(DomainSelectionService.SCAN_TYPE_LIMITED_SERVICE),
+ eq(false), any(), any());
}
@Test
@@ -1680,12 +2268,43 @@
}
@Test
+ public void testScanLimitedOnlyAfterVoLteFailure() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_SCAN_LIMITED_SERVICE_AFTER_VOLTE_FAILURE_BOOL,
+ true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onDomainSelected(eq(DOMAIN_PS), anyBoolean());
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback).onRequestEmergencyNetworkScan(
+ any(), eq(DomainSelectionService.SCAN_TYPE_LIMITED_SERVICE),
+ anyBoolean(), any(), any());
+ }
+
+ @Test
public void testStartCrossStackTimer() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
doReturn(2).when(mTelephonyManager).getActiveModemCount();
- EmergencyRegResult regResult = getEmergencyRegResult(
+ EmergencyRegistrationResult 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);
@@ -1699,16 +2318,6 @@
}
@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);
@@ -1722,8 +2331,10 @@
public void testCrossStackTimerTempFailure() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
+ doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
- EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_CS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1735,8 +2346,9 @@
verifyCsDialed();
attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setEmergency(true)
- .setEmergencyRegResult(regResult)
+ .setEmergencyRegistrationResult(regResult)
.setCsDisconnectCause(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE)
.build();
@@ -1744,14 +2356,18 @@
processAllMessages();
verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE));
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
}
@Test
- public void testCrossStackTimerPermFailure() throws Exception {
+ public void testCrossStackTimerTempFailureNoValidSubscription() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
+ doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
- EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_CS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1763,8 +2379,42 @@
verifyCsDialed();
attr = new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setEmergency(true)
- .setEmergencyRegResult(regResult)
+ .setEmergencyRegistrationResult(regResult)
+ .setCsDisconnectCause(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE)
+ .build();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE));
+ verify(mTransportSelectorCallback, never())
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
+ }
+
+ @Test
+ public void testCrossStackTimerPermFailure() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(true).when(mCsrdCtrl).isThereOtherSlot();
+
+ EmergencyRegistrationResult 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)
+ .setAddress(TEST_URI)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult)
.setCsDisconnectCause(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE)
.build();
@@ -1772,6 +2422,41 @@
processAllMessages();
verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE));
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
+ }
+
+ @Test
+ public void testCrossStackTimerPermFailureNoValidSubscription() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
+
+ EmergencyRegistrationResult 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)
+ .setAddress(TEST_URI)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult)
+ .setCsDisconnectCause(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE)
+ .build();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.EMERGENCY_PERM_FAILURE));
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
}
@Test
@@ -1779,20 +2464,31 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(
+ EmergencyRegistrationResult 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();
- verifyScanPsPreferred();
+ ArgumentCaptor<CancellationSignal> cancelCaptor =
+ ArgumentCaptor.forClass(CancellationSignal.class);
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), eq(DomainSelectionService.SCAN_TYPE_NO_PREFERENCE),
+ anyBoolean(), cancelCaptor.capture(), any());
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
mDomainSelector.notifyCrossStackTimerExpired();
verify(mTransportSelectorCallback)
.onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
+
+ CancellationSignal cancelSignal = cancelCaptor.getValue();
+ assertNotNull(cancelSignal);
+ assertFalse(cancelSignal.isCanceled());
}
@Test
@@ -1800,7 +2496,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_CS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1828,7 +2525,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 20);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -1849,13 +2546,35 @@
}
@Test
+ public void testMaxCellularTimeoutWifiNotAvailable() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
+ bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 20);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ setupForHandleScanResult();
+
+ assertTrue(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+ assertTrue(mDomainSelector.hasMessages(MSG_MAX_CELLULAR_TIMEOUT));
+
+ verify(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+
+ // Max cellular timer expired
+ mDomainSelector.removeMessages(MSG_MAX_CELLULAR_TIMEOUT);
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_MAX_CELLULAR_TIMEOUT));
+
+ assertTrue(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+ verify(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+ }
+
+ @Test
public void testSimLockNoMaxCellularTimeout() throws Exception {
when(mTelephonyManager.getSimState(anyInt())).thenReturn(
TelephonyManager.SIM_STATE_PIN_REQUIRED);
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 20);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -1868,7 +2587,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 20);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -1893,12 +2612,13 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 5);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_CS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -1915,6 +2635,8 @@
mDomainSelector.reselectDomain(attr);
processAllMessages();
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
assertTrue(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
assertTrue(mDomainSelector.hasMessages(MSG_MAX_CELLULAR_TIMEOUT));
@@ -1929,10 +2651,92 @@
mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_MAX_CELLULAR_TIMEOUT));
processAllMessages();
+ assertFalse(mDomainSelector.hasMessages(MSG_MAX_CELLULAR_TIMEOUT));
+ verify(mTransportSelectorCallback, times(1)).onWlanSelected(anyBoolean());
+
mDomainSelector.reselectDomain(attr);
processAllMessages();
+ verify(mWwanSelectorCallback, times(2)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ }
+
+ @Test
+ public void testMaxCellularTimeoutWhileDialingOnCellularWhileDialing() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
+ bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 5);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ assertFalse(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
assertFalse(mDomainSelector.hasMessages(MSG_MAX_CELLULAR_TIMEOUT));
+
+ mResultConsumer = null;
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ assertTrue(mDomainSelector.hasMessages(MSG_NETWORK_SCAN_TIMEOUT));
+ assertTrue(mDomainSelector.hasMessages(MSG_MAX_CELLULAR_TIMEOUT));
+
+ assertNotNull(mResultConsumer);
+
+ // Scan result received and redialing on cellular
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ // Wi-Fi is connected.
+ mNetworkCallback.onAvailable(null);
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // Max cellular timer expired
+ mDomainSelector.removeMessages(MSG_MAX_CELLULAR_TIMEOUT);
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(MSG_MAX_CELLULAR_TIMEOUT));
+ processAllMessages();
+
+ assertFalse(mDomainSelector.hasMessages(MSG_MAX_CELLULAR_TIMEOUT));
+
+ // Waiting for reselectDomain since there is a dialing on going.
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+
+ // Wi-Fi is disconnected.
+ mNetworkCallback.onUnavailable();
+ processAllMessages();
+
+ mResultConsumer = null;
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(0)).onWlanSelected(anyBoolean());
+ verify(mWwanSelectorCallback, times(2)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+
+ // Wi-Fi is re-connected.
+ mNetworkCallback.onAvailable(null);
+ processAllMessages();
+
+ mResultConsumer = null;
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
verify(mTransportSelectorCallback, times(1)).onWlanSelected(anyBoolean());
}
@@ -1941,7 +2745,7 @@
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 20);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -1967,7 +2771,7 @@
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
bundle.putInt(KEY_MAXIMUM_CELLULAR_SEARCH_TIMER_SEC_INT, 20);
bundle.putInt(KEY_MAXIMUM_NUMBER_OF_EMERGENCY_TRIES_OVER_VOWIFI_INT, 2);
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
setupForHandleScanResult();
@@ -1986,7 +2790,8 @@
verify(mTransportSelectorCallback, times(1)).onWlanSelected(anyBoolean());
assertFalse(mDomainSelector.hasMessages(MSG_MAX_CELLULAR_TIMEOUT));
- EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_HOME,
NetworkRegistrationInfo.DOMAIN_CS,
true, true, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
@@ -2004,34 +2809,6 @@
}
@Test
- public void testSimLockScanPsPreferredWithNr() throws Exception {
- createSelector(SLOT_0_SUB_ID);
- unsolBarringInfoChanged(false);
-
- // The last valid subscription supported NR.
- doReturn(true).when(mCarrierConfigHelper).isVoNrEmergencySupported(eq(SLOT_0));
- when(mTelephonyManager.getSimState(anyInt())).thenReturn(
- TelephonyManager.SIM_STATE_PIN_REQUIRED);
-
- 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(), anyInt(), any(), any());
- assertEquals(4, mAccessNetwork.size());
- assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
- assertEquals(NGRAN, (int) mAccessNetwork.get(1));
- assertEquals(UTRAN, (int) mAccessNetwork.get(2));
- assertEquals(GERAN, (int) mAccessNetwork.get(3));
- }
-
- @Test
public void testSimLockScanPsPreferredWithNrAtTheEnd() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -2039,7 +2816,7 @@
when(mTelephonyManager.getSimState(anyInt())).thenReturn(
TelephonyManager.SIM_STATE_PIN_REQUIRED);
- EmergencyRegResult regResult = getEmergencyRegResult(
+ EmergencyRegistrationResult 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);
@@ -2049,7 +2826,7 @@
processAllMessages();
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), anyInt(), any(), any());
+ any(), anyInt(), anyBoolean(), any(), any());
assertEquals(4, mAccessNetwork.size());
assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
assertEquals(UTRAN, (int) mAccessNetwork.get(1));
@@ -2062,7 +2839,7 @@
createSelector(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(
UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "");
SelectionAttributes attr = getSelectionAttributes(SLOT_0,
SubscriptionManager.INVALID_SUBSCRIPTION_ID, regResult);
@@ -2073,7 +2850,7 @@
processAllMessages();
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), anyInt(), any(), any());
+ any(), anyInt(), anyBoolean(), any(), any());
assertEquals(4, mAccessNetwork.size());
assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
assertEquals(UTRAN, (int) mAccessNetwork.get(1));
@@ -2082,17 +2859,566 @@
}
@Test
- public void testInvalidSubscriptionScanPsPreferredWithNr() throws Exception {
- createSelector(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ public void testDefaultLimitedServiceEutran() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- // The last valid subscription supported NR.
- doReturn(true).when(mCarrierConfigHelper).isVoNrEmergencySupported(eq(SLOT_0));
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
- EmergencyRegResult regResult = getEmergencyRegResult(
- UNKNOWN, REGISTRATION_STATE_UNKNOWN, 0, false, false, 0, 0, "", "");
- SelectionAttributes attr = getSelectionAttributes(SLOT_0,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID, regResult);
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyScanCsPreferred();
+ }
+
+ @Test
+ public void testDefaultLimitedServiceEutranFail() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+
+ attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, false, regResult,
+ new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, 0, null));
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testDefaultLimitedServiceScanTypeFullService() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_FULL_SERVICE);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPreferred(DomainSelectionService.SCAN_TYPE_FULL_SERVICE, EUTRAN);
+ }
+
+ @Test
+ public void testScanLtePreferredAfterNgranFailureSupportEmf() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[] { NGRAN, EUTRAN });
+ bundle.putBoolean(KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(NGRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS, true, false, 1, 1, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ // Verify not waiting for the disconnection in case EMF is supported.
+ assertFalse(mDomainSelector.hasMessages(MSG_WAIT_DISCONNECTION_TIMEOUT));
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ assertEquals(4, mAccessNetwork.size());
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(UTRAN, (int) mAccessNetwork.get(1));
+ assertEquals(GERAN, (int) mAccessNetwork.get(2));
+ assertEquals(NGRAN, (int) mAccessNetwork.get(3));
+ }
+
+ @Test
+ public void testScanLtePreferredAfterNgranFailureNotSupportEmf() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[] { NGRAN, EUTRAN });
+ bundle.putBoolean(KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(NGRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS, true, false, 1, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ // Verify waiting for the disconnection in case EMF is supported.
+ assertTrue(mDomainSelector.hasMessages(MSG_WAIT_DISCONNECTION_TIMEOUT));
+
+ mDomainSelector.removeMessages(MSG_WAIT_DISCONNECTION_TIMEOUT);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, never()).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+
+ mDomainSelector.sendEmptyMessage(MSG_WAIT_DISCONNECTION_TIMEOUT);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ assertEquals(4, mAccessNetwork.size());
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(UTRAN, (int) mAccessNetwork.get(1));
+ assertEquals(GERAN, (int) mAccessNetwork.get(2));
+ assertEquals(NGRAN, (int) mAccessNetwork.get(3));
+ }
+
+ @Test
+ public void testScanLtePreferredAfterNgranFailureRestartWaitingTimer() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[] { NGRAN, EUTRAN });
+ bundle.putBoolean(KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(NGRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS, true, false, 1, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ assertTrue(mDomainSelector.hasMessages(MSG_WAIT_DISCONNECTION_TIMEOUT));
+
+ mDomainSelector.removeMessages(MSG_WAIT_DISCONNECTION_TIMEOUT);
+
+ assertFalse(mDomainSelector.hasMessages(MSG_WAIT_DISCONNECTION_TIMEOUT));
+
+ mDomainSelector.notifyDataConnectionStateChange(SLOT_0, DATA_DISCONNECTING);
+
+ assertTrue(mDomainSelector.hasMessages(MSG_WAIT_DISCONNECTION_TIMEOUT));
+ }
+
+ @Test
+ public void testScanLtePreferredAfterNgranFailureDataDisconnected() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[] { NGRAN, EUTRAN });
+ bundle.putBoolean(KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(NGRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS, true, false, 1, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ assertTrue(mDomainSelector.hasMessages(MSG_WAIT_DISCONNECTION_TIMEOUT));
+
+ mDomainSelector.removeMessages(MSG_WAIT_DISCONNECTION_TIMEOUT);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, never()).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+
+ mDomainSelector.notifyDataConnectionStateChange(SLOT_0, DATA_DISCONNECTED);
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ assertEquals(4, mAccessNetwork.size());
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(UTRAN, (int) mAccessNetwork.get(1));
+ assertEquals(GERAN, (int) mAccessNetwork.get(2));
+ assertEquals(NGRAN, (int) mAccessNetwork.get(3));
+ }
+
+ @Test
+ public void testDefaultAfterNgranFailureNotSupportEmf() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[] { NGRAN, EUTRAN });
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(NGRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS, true, false, 1, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ // Verify not waiting for the disconnection
+ // in case KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL is false.
+ assertFalse(mDomainSelector.hasMessages(MSG_WAIT_DISCONNECTION_TIMEOUT));
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ assertEquals(4, mAccessNetwork.size());
+ assertEquals(UTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(GERAN, (int) mAccessNetwork.get(1));
+ assertEquals(NGRAN, (int) mAccessNetwork.get(2));
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(3));
+ }
+
+ @Test
+ public void testDefaultAfterNgranFailureSupportEmf() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putIntArray(KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY,
+ new int[] { NGRAN, EUTRAN });
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(NGRAN,
+ REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_PS, true, false, 1, 1, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ // Verify not waiting for the disconnection
+ // in case KEY_EMERGENCY_LTE_PREFERRED_AFTER_NR_FAILED_BOOL is false.
+ assertFalse(mDomainSelector.hasMessages(MSG_WAIT_DISCONNECTION_TIMEOUT));
+
+ verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ assertEquals(4, mAccessNetwork.size());
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(UTRAN, (int) mAccessNetwork.get(1));
+ assertEquals(GERAN, (int) mAccessNetwork.get(2));
+ assertEquals(NGRAN, (int) mAccessNetwork.get(3));
+ }
+
+ @Test
+ public void testDefaultLimitedServiceNgran() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(NGRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testTestEmergencyNumberOverCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID,
+ true /*isTestEmergencyNumber*/, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testTestEmergencyNumberOverPs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID,
+ true /*isTestEmergencyNumber*/, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testTestEmergencyNumberScanRequest() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UNKNOWN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID,
+ true /*isTestEmergencyNumber*/, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService(true);
+ processAllMessages();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
+ public void testLimitedServiceDialCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(UTRAN,
+ REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testWhileInEcbmOnWwan() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ doReturn(true).when(mEpdnHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WWAN).when(mEpdnHelper).getTransportType(anyInt());
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ 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());
+
+ EmergencyRegistrationResult 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(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback).onWwanSelected(any());
+ verify(mWwanSelectorCallback).onDomainSelected(eq(DOMAIN_PS), eq(true));
+ }
+
+ @Test
+ public void testWhileInEcbmOnWlanConnected() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ doReturn(true).when(mEpdnHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WLAN).when(mEpdnHelper).getTransportType(anyInt());
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ EmergencyRegistrationResult 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(mTransportSelectorCallback).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback, never()).onWwanSelected(any());
+ }
+
+ @Test
+ public void testWhileInEcbmOnWlanNotConnected() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ doReturn(true).when(mEpdnHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WLAN).when(mEpdnHelper).getTransportType(anyInt());
+
+ EmergencyRegistrationResult 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(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback).onWwanSelected(any());
+ }
+
+ @Test
+ public void testNotInEcbmOnWlanConnected() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ doReturn(false).when(mEpdnHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WLAN).when(mEpdnHelper).getTransportType(anyInt());
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ EmergencyRegistrationResult 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(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback).onWwanSelected(any());
+ }
+
+ @Test
+ public void testNotInEcbmOnWwanConnected() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ doReturn(false).when(mEpdnHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WLAN).when(mEpdnHelper).getTransportType(anyInt());
+ doReturn(DATA_CONNECTED).when(mEpdnHelper).getDataConnectionState(anyInt());
+
+ 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());
+
+ EmergencyRegistrationResult 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(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback).onWwanSelected(any());
+ verify(mWwanSelectorCallback, never()).onDomainSelected(anyInt(), anyBoolean());
+ verify(mWwanSelectorCallback).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ }
+
+ @Test
+ public void testIsInRoaming() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ int[] domainPreference = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_INT_ARRAY, domainPreference);
+ int[] domainPreferenceRoam = new int[] {
+ CarrierConfigManager.ImsEmergency.DOMAIN_PS_3GPP,
+ CarrierConfigManager.ImsEmergency.DOMAIN_CS,
+ };
+ bundle.putIntArray(KEY_EMERGENCY_DOMAIN_PREFERENCE_ROAMING_INT_ARRAY, domainPreferenceRoam);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+ doReturn("").when(mTelephonyManager).getNetworkCountryIso();
+ doReturn("us").when(mTelephonyManager).getSimCountryIso();
+
+ mResultConsumer = null;
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(true);
+
+ EmergencyRegistrationResult 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();
@@ -2100,12 +3426,214 @@
processAllMessages();
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), anyInt(), any(), any());
- assertEquals(4, mAccessNetwork.size());
+ any(), anyInt(), eq(false), any(), any());
+ assertEquals(1, mAccessNetwork.size());
assertEquals(EUTRAN, (int) mAccessNetwork.get(0));
- assertEquals(NGRAN, (int) mAccessNetwork.get(1));
- assertEquals(UTRAN, (int) mAccessNetwork.get(2));
- assertEquals(GERAN, (int) mAccessNetwork.get(3));
+ assertNotNull(mResultConsumer);
+
+ regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ 0, false, false, 0, 0, "", "", "zz");
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mWwanSelectorCallback, times(2)).onRequestEmergencyNetworkScan(
+ any(), anyInt(), eq(false), any(), any());
+ assertEquals(3, mAccessNetwork.size());
+ assertEquals(UTRAN, (int) mAccessNetwork.get(0));
+ assertEquals(GERAN, (int) mAccessNetwork.get(1));
+ assertEquals(EUTRAN, (int) mAccessNetwork.get(2));
+ }
+
+ @Test
+ public void testReselectDomainCauseNoValidSim() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+ doReturn(false).when(mCsrdCtrl).isThereOtherSlot();
+
+ EmergencyRegistrationResult 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)
+ .setAddress(TEST_URI)
+ .setEmergency(true)
+ .setEmergencyRegistrationResult(regResult)
+ .setCsDisconnectCause(PreciseDisconnectCause.NO_VALID_SIM)
+ .build();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mCsrdCtrl).notifyCallFailure(eq(PreciseDisconnectCause.NO_VALID_SIM));
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.NOT_VALID));
+ }
+
+ @Test
+ public void testReceiveSipErrorThenTerminateSelection() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, false, regResult,
+ new ImsReasonInfo(ImsReasonInfo.CODE_SIP_FORBIDDEN, 0, null));
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verify(mTransportSelectorCallback)
+ .onSelectionTerminated(eq(DisconnectCause.NOT_VALID));
+ }
+
+ @Test
+ public void testReceiveSipErrorThenNotTerminateSelection() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putIntArray(KEY_IMS_REASONINFO_CODE_TO_RETRY_EMERGENCY_INT_ARRAY,
+ new int[] { ImsReasonInfo.CODE_SIP_FORBIDDEN });
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, false, regResult,
+ new ImsReasonInfo(ImsReasonInfo.CODE_SIP_FORBIDDEN, 0, null));
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testRetryWithCodeLocalCallCsRetryRequired() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, false, regResult,
+ new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED, 0, null));
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testRetryWithCodeLocalNotRegistered() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, false, regResult,
+ new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, 0, null));
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testRetryWithCodeSipAlternateEemergencyCall() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, false, regResult,
+ new ImsReasonInfo(ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL, 0, null));
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testRetryWithCodeLocalInternalError() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegistrationResult 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();
+
+ attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, false, regResult,
+ new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR, 0, null));
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
}
private void setupForScanListTest(PersistableBundle bundle) throws Exception {
@@ -2113,11 +3641,12 @@
}
private void setupForScanListTest(PersistableBundle bundle, boolean psFailed) throws Exception {
- when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt(), anyVararg())).thenReturn(bundle);
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ EmergencyRegistrationResult regResult = getEmergencyRegResult(EUTRAN,
+ REGISTRATION_STATE_UNKNOWN,
0, false, false, 0, 0, "", "");
if (psFailed) {
regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
@@ -2164,7 +3693,8 @@
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
- EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_UNKNOWN,
+ EmergencyRegistrationResult 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);
@@ -2174,14 +3704,14 @@
processAllMessages();
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), anyInt(), any(), any());
+ any(), anyInt(), anyBoolean(), any(), any());
assertNotNull(mResultConsumer);
}
private void createSelector(int subId) throws Exception {
mDomainSelector = new EmergencyCallDomainSelector(
mContext, SLOT_0, subId, mHandlerThread.getLooper(),
- mImsStateTracker, mDestroyListener, mCsrdCtrl, mCarrierConfigHelper);
+ mImsStateTracker, mDestroyListener, mCsrdCtrl, mEpdnHelper);
mDomainSelector.clearResourceConfiguration();
replaceInstance(DomainSelectorBase.class,
"mWwanSelectorCallback", mDomainSelector, mWwanSelectorCallback);
@@ -2208,7 +3738,7 @@
private void verifyScanPreferred(int scanType, int expectedPreferredAccessNetwork) {
processAllMessages();
verify(mWwanSelectorCallback, times(1)).onRequestEmergencyNetworkScan(
- any(), eq(scanType), any(), any());
+ any(), eq(scanType), anyBoolean(), any(), any());
assertEquals(expectedPreferredAccessNetwork, (int) mAccessNetwork.get(0));
}
@@ -2240,7 +3770,7 @@
mDomainSelector.onImsMmTelCapabilitiesChanged();
}
- private static EmergencyRegResult getEmergencyRegResult(
+ private static EmergencyRegistrationResult getEmergencyRegResult(
@AccessNetworkConstants.RadioAccessNetworkType int accessNetwork,
@NetworkRegistrationInfo.RegistrationState int regState,
@NetworkRegistrationInfo.Domain int domain,
@@ -2250,13 +3780,13 @@
isEmcBearerSupported, emc, emf, mcc, mnc, "");
}
- private static EmergencyRegResult getEmergencyRegResult(
+ private static EmergencyRegistrationResult 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,
+ return new EmergencyRegistrationResult(accessNetwork, regState,
domain, isVopsSupported, isEmcBearerSupported,
emc, emf, mcc, mnc, iso);
}
@@ -2350,12 +3880,26 @@
return bundle;
}
- public static SelectionAttributes getSelectionAttributes(int slotId, int subId,
- EmergencyRegResult regResult) {
+ private static SelectionAttributes getSelectionAttributes(int slotId, int subId,
+ EmergencyRegistrationResult regResult) {
+ return getSelectionAttributes(slotId, subId, false, regResult);
+ }
+
+ private static SelectionAttributes getSelectionAttributes(int slotId, int subId,
+ boolean isTestEmergencyNumber, EmergencyRegistrationResult regResult) {
+ return getSelectionAttributes(slotId, subId, isTestEmergencyNumber, regResult, null);
+ }
+
+ private static SelectionAttributes getSelectionAttributes(int slotId, int subId,
+ boolean isTestEmergencyNumber, EmergencyRegistrationResult regResult,
+ ImsReasonInfo imsReasonInfo) {
SelectionAttributes.Builder builder =
new SelectionAttributes.Builder(slotId, subId, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setEmergency(true)
- .setEmergencyRegResult(regResult);
+ .setTestEmergencyNumber(isTestEmergencyNumber)
+ .setPsDisconnectCause(imsReasonInfo)
+ .setEmergencyRegistrationResult(regResult);
return builder.build();
}
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelectorTest.java
index ed064cb..a900fda 100644
--- a/tests/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencySmsDomainSelectorTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -39,16 +40,17 @@
import android.telephony.CarrierConfigManager;
import android.telephony.DataSpecificRegistrationInfo;
import android.telephony.DomainSelectionService.SelectionAttributes;
+import android.telephony.EmergencyRegistrationResult;
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.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.TestContext;
@@ -92,6 +94,7 @@
private ImsStateTracker.BarringInfoListener mBarringInfoListener;
private ImsStateTracker.ServiceStateListener mServiceStateListener;
private EmergencySmsDomainSelector mDomainSelector;
+ private EmergencyRegistrationResult mEmergencyRegistrationResult;
@Before
public void setUp() throws Exception {
@@ -151,6 +154,7 @@
mLooper = null;
}
+ mEmergencyRegistrationResult = null;
mDomainSelector = null;
mNetworkRegistrationInfo = null;
mVopsSupportInfo = null;
@@ -246,6 +250,26 @@
@Test
@SmallTest
+ public void testIsSmsOverImsAvailableWhenImsRegisteredAndConfigEnabledAndNrAvailable() {
+ setUpImsStateTracker(AccessNetworkType.NGRAN);
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, true, false);
+
+ assertTrue(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenImsRegisteredAndConfigEnabledAndNrNotAvailable() {
+ setUpImsStateTracker(AccessNetworkType.NGRAN);
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, false, false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
public void testIsSmsOverImsAvailableWhenCarrierConfigManagerIsNull() {
setUpImsStateTracker(AccessNetworkType.UNKNOWN);
mCarrierConfigManagerNullTest = true;
@@ -291,7 +315,7 @@
@Test
@SmallTest
- public void testIsSmsOverImsAvailableWhenNoLte() {
+ public void testIsSmsOverImsAvailableWhenNoLteOrNr() {
setUpImsStateTracker(AccessNetworkType.UNKNOWN);
setUpCarrierConfig(true);
mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
@@ -395,6 +419,56 @@
@Test
@SmallTest
+ public void testIsSmsOverImsAvailableWhenNrNotRegisteredOrEmergencyNotEnabled() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, false, false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenNrInServiceAndNoDataSpecificRegistrationInfo() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpNrInService(true, true, false, false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenNrInServiceAndNoVopsSupportInfo() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpNrInService(false, true, false, false);
+
+ assertFalse(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenNrInServiceAndEmergencyServiceSupported() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, true, false);
+
+ assertTrue(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
+ public void testIsSmsOverImsAvailableWhenNrInServiceAndEmergencyServiceFallbackSupported() {
+ setUpImsStateTracker(AccessNetworkType.UNKNOWN);
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, false, true);
+
+ assertTrue(mDomainSelector.isSmsOverImsAvailable());
+ }
+
+ @Test
+ @SmallTest
public void testSelectDomainWhilePreviousRequestInProgress() {
setUpImsStateTracker(AccessNetworkType.EUTRAN);
setUpWwanSelectorCallback();
@@ -675,6 +749,116 @@
eq(true));
}
+ @Test
+ @SmallTest
+ public void testSelectDomainWhileEmergencyNetworkScanInProgress() {
+ setUpImsStateTracker(AccessNetworkType.NGRAN);
+ setUpEmergencyRegResult(AccessNetworkType.NGRAN, NetworkRegistrationInfo.DOMAIN_PS, 1, 0);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, false, true);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ // Call the domain selection before completing the emergency network scan.
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // onRequestEmergencyNetworkScan is invoked only once.
+ verify(mWwanSelectorCallback).onRequestEmergencyNetworkScan(any(), anyInt(),
+ anyBoolean(), any(), any());
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenNrEmergencyServiceSupported() {
+ setUpImsStateTracker(AccessNetworkType.NGRAN);
+ setUpEmergencyRegResult(AccessNetworkType.NGRAN, NetworkRegistrationInfo.DOMAIN_PS, 1, 0);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, true, false);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: PS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(true));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenEmergencyRegistrationResultNgranAndPsDomain() {
+ setUpImsStateTracker(AccessNetworkType.NGRAN);
+ setUpEmergencyRegResult(AccessNetworkType.NGRAN, NetworkRegistrationInfo.DOMAIN_PS, 1, 0);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, false, true);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: PS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(true));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenEmergencyRegistrationResultEutranAndPsDomain() {
+ setUpImsStateTracker(AccessNetworkType.NGRAN);
+ setUpEmergencyRegResult(AccessNetworkType.EUTRAN, NetworkRegistrationInfo.DOMAIN_PS, 0, 0);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, false, true);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: PS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_PS),
+ eq(true));
+ }
+
+ @Test
+ @SmallTest
+ public void testSelectDomainWhenEmergencyRegistrationResultEutranAndCsDomain() {
+ setUpImsStateTracker(AccessNetworkType.NGRAN);
+ setUpEmergencyRegResult(AccessNetworkType.EUTRAN, NetworkRegistrationInfo.DOMAIN_CS, 0, 0);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, 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 testSelectDomainWhenEmergencyRegistrationResultUtranAndCsDomain() {
+ setUpImsStateTracker(AccessNetworkType.NGRAN);
+ setUpEmergencyRegResult(AccessNetworkType.UTRAN, NetworkRegistrationInfo.DOMAIN_CS, 0, 0);
+ setUpWwanSelectorCallback();
+ setUpCarrierConfig(true);
+ setUpNrInService(false, false, false, true);
+ setUpImsStateListener(true, true, true);
+
+ mDomainSelector.selectDomain(mSelectionAttributes, mTransportSelectorCallback);
+ processAllMessages();
+
+ // Expected: CS network
+ verify(mWwanSelectorCallback).onDomainSelected(eq(NetworkRegistrationInfo.DOMAIN_CS),
+ eq(false));
+ }
+
private void setUpCarrierConfig(boolean supported) {
PersistableBundle b = new PersistableBundle();
b.putBoolean(CarrierConfigManager.KEY_SUPPORT_EMERGENCY_SMS_OVER_IMS_BOOL, supported);
@@ -760,6 +944,29 @@
mBarringInfoListener.onBarringInfoUpdated(barringInfo);
}
+ private void setUpNrInService(boolean noDataSpecificRegistrationInfo,
+ boolean noVopsSupportInfo, boolean emergencyServiceSupported,
+ boolean emergencyServiceFallbackSupported) {
+ DataSpecificRegistrationInfo dsri = noDataSpecificRegistrationInfo
+ ? null : new DataSpecificRegistrationInfo(
+ 8, false, false, false, noVopsSupportInfo ? null : mVopsSupportInfo);
+
+ mNetworkRegistrationInfo = new NetworkRegistrationInfo.Builder()
+ .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_NR)
+ .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
+ .setDataSpecificInfo(dsri)
+ .build();
+ when(mServiceState.getNetworkRegistrationInfo(
+ anyInt(), eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)))
+ .thenReturn(mNetworkRegistrationInfo);
+ when(mVopsSupportInfo.isEmergencyServiceSupported()).thenReturn(emergencyServiceSupported);
+ when(mVopsSupportInfo.isEmergencyServiceFallbackSupported())
+ .thenReturn(emergencyServiceFallbackSupported);
+
+ mServiceStateListener.onServiceStateUpdated(mServiceState);
+ mBarringInfoListener.onBarringInfoUpdated(null);
+ }
+
private void setUpImsStateTracker(@RadioAccessNetworkType int accessNetworkType) {
setUpImsStateTracker(accessNetworkType, true, true);
}
@@ -783,6 +990,23 @@
callback.accept(mWwanSelectorCallback);
return null;
}).when(mTransportSelectorCallback).onWwanSelected(any(Consumer.class));
+
+ doAnswer((invocation) -> {
+ Object[] args = invocation.getArguments();
+ final Consumer<EmergencyRegistrationResult> result =
+ (Consumer<EmergencyRegistrationResult>) args[4];
+ result.accept(mEmergencyRegistrationResult);
+ return null;
+ }).when(mWwanSelectorCallback).onRequestEmergencyNetworkScan(
+ any(), anyInt(), anyBoolean(), any(), any());
+ }
+
+ private void setUpEmergencyRegResult(
+ @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork,
+ @NetworkRegistrationInfo.Domain int domain, int nrEs, int nrEsfb) {
+ mEmergencyRegistrationResult = new EmergencyRegistrationResult(accessNetwork,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
+ domain, true, true, nrEs, nrEsfb, "001", "01", "");
}
private void setUpImsStateListener(boolean notifyMmTelFeatureAvailable,
diff --git a/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java b/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java
index 6519835..f9a56a8 100644
--- a/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/ImsStateTrackerTest.java
@@ -47,8 +47,8 @@
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.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.TestContext;
diff --git a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
index 002c7d5..6e438bf 100644
--- a/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/NormalCallDomainSelectorTest.java
@@ -17,7 +17,6 @@
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;
@@ -28,17 +27,19 @@
import android.annotation.NonNull;
import android.content.Context;
+import android.net.Uri;
import android.os.CancellationSignal;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.PersistableBundle;
+import android.telecom.PhoneAccount;
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.EmergencyRegistrationResult;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -69,10 +70,12 @@
public class NormalCallDomainSelectorTest {
private static final String TAG = "NormalCallDomainSelectorTest";
+ private static final int SELECTOR_TYPE_UT = 3;
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 static final Uri TEST_URI = Uri.fromParts(PhoneAccount.SCHEME_TEL, "123456789", null);
private HandlerThread mHandlerThread;
private NormalCallDomainSelector mNormalCallDomainSelector;
@@ -150,13 +153,54 @@
}
@Test
- public void testSelectDomainInputParams() {
+ public void testInitialState() {
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+ }
+
+ @Test
+ public void testDestroyedState() {
+ mNormalCallDomainSelector.destroy();
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.DESTROYED);
+ }
+
+ @Test
+ public void testDestroyedDuringActiveState() {
MockTransportSelectorCallback transportSelectorCallback =
- new MockTransportSelectorCallback();
+ new MockTransportSelectorCallback(mNormalCallDomainSelector);
DomainSelectionService.SelectionAttributes attributes =
new DomainSelectionService.SelectionAttributes.Builder(
SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
+ .setCallId(TEST_CALLID)
+ .setEmergency(false)
+ .setVideoCall(true)
+ .setExitedFromAirplaneMode(false)
+ .build();
+
+ mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.ACTIVE);
+
+ mNormalCallDomainSelector.destroy();
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.DESTROYED);
+ }
+
+ @Test
+ public void testSelectDomainInputParams() {
+ MockTransportSelectorCallback transportSelectorCallback =
+ new MockTransportSelectorCallback(mNormalCallDomainSelector);
+
+ DomainSelectionService.SelectionAttributes attributes =
+ new DomainSelectionService.SelectionAttributes.Builder(
+ SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setCallId(TEST_CALLID)
.setEmergency(false)
.setVideoCall(true)
@@ -164,6 +208,8 @@
.build();
mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.ACTIVE);
// Case 1: null inputs
try {
@@ -172,6 +218,9 @@
fail("Invalid input params not handled." + e.getMessage());
}
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
// Case 2: null TransportSelectorCallback
try {
mNormalCallDomainSelector.selectDomain(attributes, null);
@@ -179,6 +228,9 @@
fail("Invalid params (SelectionAttributes) not handled." + e.getMessage());
}
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
// Case 3: null SelectionAttributes
transportSelectorCallback.mSelectionTerminated = false;
try {
@@ -190,9 +242,13 @@
assertTrue(transportSelectorCallback
.verifyOnSelectionTerminated(DisconnectCause.OUTGOING_FAILURE));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.DESTROYED);
+
// Case 4: Invalid Subscription-id
attributes = new DomainSelectionService.SelectionAttributes.Builder(
SLOT_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setCallId(TEST_CALLID)
.setEmergency(false)
.setVideoCall(true)
@@ -207,10 +263,14 @@
assertTrue(transportSelectorCallback
.verifyOnSelectionTerminated(DisconnectCause.OUTGOING_FAILURE));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.DESTROYED);
+
// Case 5: Invalid SELECTOR_TYPE
attributes =
new DomainSelectionService.SelectionAttributes.Builder(
SLOT_ID, SUB_ID_1, SELECTOR_TYPE_UT)
+ .setAddress(TEST_URI)
.setCallId(TEST_CALLID)
.setEmergency(false)
.setVideoCall(true)
@@ -225,9 +285,13 @@
assertTrue(transportSelectorCallback
.verifyOnSelectionTerminated(DisconnectCause.OUTGOING_FAILURE));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.DESTROYED);
+
// Case 6: Emergency Call
attributes = new DomainSelectionService.SelectionAttributes.Builder(
SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setCallId(TEST_CALLID)
.setEmergency(true)
.setVideoCall(true)
@@ -239,6 +303,9 @@
fail("Invalid params (SelectionAttributes) not handled." + e.getMessage());
}
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.DESTROYED);
+
assertTrue(transportSelectorCallback
.verifyOnSelectionTerminated(DisconnectCause.OUTGOING_FAILURE));
}
@@ -246,30 +313,38 @@
@Test
public void testOutOfService() {
MockTransportSelectorCallback transportSelectorCallback =
- new MockTransportSelectorCallback();
+ new MockTransportSelectorCallback(mNormalCallDomainSelector);
DomainSelectionService.SelectionAttributes attributes =
new DomainSelectionService.SelectionAttributes.Builder(
SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.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));
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.DESTROYED);
}
@Test
public void testDomainSelection() {
MockTransportSelectorCallback transportSelectorCallback =
- new MockTransportSelectorCallback();
+ new MockTransportSelectorCallback(mNormalCallDomainSelector);
DomainSelectionService.SelectionAttributes attributes =
new DomainSelectionService.SelectionAttributes.Builder(
SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setCallId(TEST_CALLID)
.setEmergency(false)
.setVideoCall(false)
@@ -280,32 +355,49 @@
ServiceState serviceState = new ServiceState();
serviceState.setState(ServiceState.STATE_IN_SERVICE);
initialize(serviceState, true, true, true, true);
+
mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+
assertTrue(transportSelectorCallback.verifyOnWlanSelected());
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
// 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));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
// 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)
+ .setAddress(TEST_URI)
.setCallId(TEST_CALLID)
.setEmergency(false)
.setVideoCall(false)
.setExitedFromAirplaneMode(false)
.setPsDisconnectCause(imsReasonInfo)
.build();
+
mNormalCallDomainSelector.reselectDomain(attributes);
+
assertTrue(transportSelectorCallback
.verifyOnDomainSelected(NetworkRegistrationInfo.DOMAIN_CS));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
// Case 4: CS call
NetworkRegistrationInfo nwRegistrationInfo = new NetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
@@ -313,28 +405,40 @@
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));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
//Case 5: Backup calling
serviceState.setStateOutOfService();
initialize(serviceState, true, true, true, true);
+
mNormalCallDomainSelector.selectDomain(attributes, transportSelectorCallback);
+
assertTrue(transportSelectorCallback.verifyOnWlanSelected());
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.ACTIVE);
}
@Test
public void testWPSCallDomainSelection() {
MockTransportSelectorCallback transportSelectorCallback =
- new MockTransportSelectorCallback();
+ new MockTransportSelectorCallback(mNormalCallDomainSelector);
DomainSelectionService.SelectionAttributes attributes =
new DomainSelectionService.SelectionAttributes.Builder(
SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
- .setNumber("*272121")
+ .setAddress(Uri.fromParts(PhoneAccount.SCHEME_TEL, "*272121", null))
.setCallId(TEST_CALLID)
.setEmergency(false)
.setVideoCall(false)
@@ -346,38 +450,57 @@
config.putBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL, false);
doReturn(config).when(mMockCarrierConfigMgr).getConfigForSubId(SUB_ID_1,
new String[]{CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL});
+
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));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
//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());
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
//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));
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
}
@Test
public void testTtyCallDomainSelection() {
MockTransportSelectorCallback transportSelectorCallback =
- new MockTransportSelectorCallback();
+ new MockTransportSelectorCallback(mNormalCallDomainSelector);
DomainSelectionService.SelectionAttributes attributes =
new DomainSelectionService.SelectionAttributes.Builder(
SLOT_ID, SUB_ID_1, SELECTOR_TYPE_CALLING)
+ .setAddress(TEST_URI)
.setCallId(TEST_CALLID)
.setEmergency(false)
.setVideoCall(false)
@@ -390,29 +513,48 @@
config.putBoolean(CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL, false);
doReturn(config).when(mMockCarrierConfigMgr).getConfigForSubId(SUB_ID_1,
new String[]{CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL});
+
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));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
//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));
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
//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));
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
}
+
+
static class MockTransportSelectorCallback implements TransportSelectorCallback,
WwanSelectorCallback {
public boolean mCreated;
@@ -422,11 +564,20 @@
public boolean mDomainSelected;
int mCauseCode;
int mSelectedDomain;
+ NormalCallDomainSelector mNormalCallDomainSelector;
+
+ MockTransportSelectorCallback(NormalCallDomainSelector normalCallDomainSelector) {
+ mNormalCallDomainSelector = normalCallDomainSelector;
+ }
@Override
public synchronized void onCreated(DomainSelector selector) {
Log.d(TAG, "onCreated");
mCreated = true;
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
notifyAll();
}
@@ -441,6 +592,10 @@
public synchronized void onWlanSelected(boolean useEmergencyPdn) {
Log.d(TAG, "onWlanSelected");
mWlanSelected = true;
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
notifyAll();
}
@@ -451,18 +606,14 @@
}
@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);
});
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
}
public boolean verifyOnWwanSelected() {
@@ -475,6 +626,10 @@
Log.i(TAG, "onSelectionTerminated - called");
mCauseCode = cause;
mSelectionTerminated = true;
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
notifyAll();
}
@@ -499,9 +654,10 @@
@Override
public void onRequestEmergencyNetworkScan(@NonNull List<Integer> preferredNetworks,
- int scanType,
- @NonNull CancellationSignal signal,
- @NonNull Consumer<EmergencyRegResult> consumer) {
+ int scanType,
+ boolean resetScan,
+ @NonNull CancellationSignal signal,
+ @NonNull Consumer<EmergencyRegistrationResult> consumer) {
Log.i(TAG, "onRequestEmergencyNetworkScan - called");
}
@@ -511,6 +667,10 @@
Log.i(TAG, "onDomainSelected - called");
mSelectedDomain = domain;
mDomainSelected = true;
+
+ assertEquals(mNormalCallDomainSelector.getSelectorState(),
+ NormalCallDomainSelector.SelectorState.INACTIVE);
+
notifyAll();
}
diff --git a/tests/src/com/android/services/telephony/domainselection/SmsDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/SmsDomainSelectorTest.java
index 8f78a58..fc577c4 100644
--- a/tests/src/com/android/services/telephony/domainselection/SmsDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/SmsDomainSelectorTest.java
@@ -37,9 +37,9 @@
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.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.TestContext;
@@ -190,21 +190,6 @@
@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);
diff --git a/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java b/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java
index f4d2732..7031bf3 100644
--- a/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java
@@ -27,6 +27,7 @@
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
@@ -39,9 +40,9 @@
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.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.TestContext;
@@ -81,11 +82,10 @@
@NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
@NonNull DomainSelectorBase.DestroyListener listener,
@NonNull CrossSimRedialingController crossSimRedialingController,
- @NonNull CarrierConfigHelper carrierConfigHelper) {
+ @NonNull DataConnectionStateHelper dataConnectionStateHelper) {
switch (selectorType) {
case DomainSelectionService.SELECTOR_TYPE_CALLING: // fallthrough
- case DomainSelectionService.SELECTOR_TYPE_SMS: // fallthrough
- case DomainSelectionService.SELECTOR_TYPE_UT:
+ case DomainSelectionService.SELECTOR_TYPE_SMS:
mDomainSelectorDestroyListener = listener;
if (subId == SUB_1) {
return mDomainSelectorBase1;
@@ -97,6 +97,26 @@
}
}
};
+ private static class TestTelephonyDomainSelectionService
+ extends TelephonyDomainSelectionService {
+ private final Context mContext;
+
+ TestTelephonyDomainSelectionService(Context context,
+ @NonNull ImsStateTrackerFactory imsStateTrackerFactory,
+ @NonNull DomainSelectorFactory domainSelectorFactory,
+ @Nullable DataConnectionStateHelper dataConnectionStateHelper) {
+ super(imsStateTrackerFactory, domainSelectorFactory,
+ dataConnectionStateHelper);
+ mContext = context;
+ }
+
+ @Override
+ public void onCreate() {
+ // attach test context.
+ attachBaseContext(mContext);
+ super.onCreate();
+ }
+ }
private static final int SLOT_0 = 0;
private static final int SUB_1 = 1;
private static final int SUB_2 = 2;
@@ -110,7 +130,7 @@
@Mock private TransportSelectorCallback mSelectorCallback1;
@Mock private TransportSelectorCallback mSelectorCallback2;
@Mock private ImsStateTracker mImsStateTracker;
- @Mock private CarrierConfigHelper mCarrierConfigHelper;
+ @Mock private DataConnectionStateHelper mDataConnectionStateHelper;
private final ServiceState mServiceState = new ServiceState();
private final BarringInfo mBarringInfo = new BarringInfo();
@@ -131,8 +151,10 @@
}
mContext = new TestContext();
- mDomainSelectionService = new TelephonyDomainSelectionService(mContext,
- mImsStateTrackerFactory, mDomainSelectorFactory, mCarrierConfigHelper);
+ mDomainSelectionService = new TestTelephonyDomainSelectionService(mContext,
+ mImsStateTrackerFactory, mDomainSelectorFactory,
+ mDataConnectionStateHelper);
+ mDomainSelectionService.onCreate();
mServiceHandler = new Handler(mDomainSelectionService.getLooper());
mTestableLooper = new TestableLooper(mDomainSelectionService.getLooper());
@@ -184,9 +206,7 @@
.setCallId(CALL_ID)
.setEmergency(true)
.build();
- mServiceHandler.post(() -> {
- mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
- });
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
processAllMessages();
verify(mImsStateTracker).start(eq(SUB_1));
@@ -203,9 +223,7 @@
.setCallId(CALL_ID)
.setEmergency(true)
.build();
- mServiceHandler.post(() -> {
- mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
- });
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
processAllMessages();
verify(mImsStateTracker, never()).start(anyInt());
@@ -222,9 +240,7 @@
.setCallId(CALL_ID)
.setEmergency(true)
.build();
- mServiceHandler.post(() -> {
- mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
- });
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
processAllMessages();
verify(mImsStateTracker).start(eq(SUB_1));
@@ -240,9 +256,7 @@
.setCallId(CALL_ID)
.setEmergency(true)
.build();
- mServiceHandler.post(() -> {
- mDomainSelectionService.onDomainSelection(attr2, mSelectorCallback2);
- });
+ mDomainSelectionService.onDomainSelection(attr2, mSelectorCallback2);
processAllMessages();
verify(mImsStateTracker).start(eq(SUB_2));
@@ -259,9 +273,7 @@
.setCallId(CALL_ID)
.setEmergency(true)
.build();
- mServiceHandler.post(() -> {
- mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
- });
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
processAllMessages();
verify(mImsStateTracker).start(eq(SUB_1));
@@ -274,9 +286,7 @@
.setCallId(CALL_ID)
.setEmergency(true)
.build();
- mServiceHandler.post(() -> {
- mDomainSelectionService.onDomainSelection(attr2, mSelectorCallback2);
- });
+ mDomainSelectionService.onDomainSelection(attr2, mSelectorCallback2);
processAllMessages();
verify(mImsStateTracker).start(eq(SUB_2));
@@ -309,9 +319,7 @@
.setCallId(CALL_ID)
.setEmergency(true)
.build();
- mServiceHandler.post(() -> {
- mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
- });
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
processAllMessages();
mDomainSelectionService.onDestroy();
diff --git a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
index d575d77..4cabf95 100644
--- a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
+++ b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
@@ -39,6 +39,7 @@
import com.android.ims.FeatureConnector;
import com.android.ims.RcsFeatureManager;
import com.android.internal.telephony.ISub;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
import org.junit.Before;
@@ -68,6 +69,8 @@
@Mock
private TelephonyManager mTelephonyManager;
+ @Mock FeatureFlags mFeatureFlags;
+
private RcsFeatureController mFeatureControllerSlot0;
private RcsFeatureController mFeatureControllerSlot1;
@@ -91,9 +94,9 @@
doReturn(mFeatureControllerSlot1).when(mFeatureFactory).createController(any(), eq(1),
anyInt());
doReturn(mMockUceSlot0).when(mFeatureFactory).createUceControllerManager(any(), eq(0),
- anyInt());
+ anyInt(), any());
doReturn(mMockUceSlot1).when(mFeatureFactory).createUceControllerManager(any(), eq(1),
- anyInt());
+ anyInt(), any());
doReturn(mMockSipTransportSlot0).when(mFeatureFactory).createSipTransportController(any(),
eq(0), anyInt());
doReturn(mMockSipTransportSlot1).when(mFeatureFactory).createSipTransportController(any(),
@@ -363,7 +366,8 @@
}
private TelephonyRcsService createRcsService(int numSlots) {
- TelephonyRcsService service = new TelephonyRcsService(mContext, numSlots, mResourceProxy);
+ TelephonyRcsService service = new TelephonyRcsService(mContext, numSlots, mResourceProxy,
+ mFeatureFlags);
service.setFeatureFactory(mFeatureFactory);
service.initialize();
verify(mContext).registerReceiver(mReceiverCaptor.capture(), any());
diff --git a/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java b/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
index 17decb9..e506931 100644
--- a/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/UceControllerManagerTest.java
@@ -35,6 +35,7 @@
import com.android.TestExecutorService;
import com.android.ims.RcsFeatureManager;
import com.android.ims.rcs.uce.UceController;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
import org.junit.Before;
@@ -52,6 +53,7 @@
@Mock private UceController mUceController;
@Mock private RcsFeatureManager mRcsFeatureManager;
+ @Mock private FeatureFlags mFeatureFlags;
private final ExecutorService mExecutorService = new TestExecutorService();
@@ -260,7 +262,7 @@
private UceControllerManager getUceControllerManager() {
UceControllerManager manager = new UceControllerManager(mContext, mSlotId,
- mExecutorService, mUceController);
+ mExecutorService, mUceController, mFeatureFlags);
return manager;
}
}
diff --git a/utils/satellite/README.md b/utils/satellite/README.md
index e219823..77ee0fb 100644
--- a/utils/satellite/README.md
+++ b/utils/satellite/README.md
@@ -8,7 +8,7 @@
- `src/write` S2 write code used by tools to write the s2 cells into a
binary file. This code is also used by `TeleServiceTests`.
- `src/readonly` S2 read-only code used by the above read-write code and the class
- `S2RangeFileBasedSatelliteLocationLookup`.
+ `S2RangeSatelliteOnDeviceAccessController`.
`tools`
- `src/main` Contains the tools for generating binary satellite s2 file, and tools
@@ -29,7 +29,7 @@
list of S2 cells ID.
- Command: `$satellite_createsats2file --input-file <s2cells.txt> --s2-level <12>
--is-allowed-list <true> --output-file <sats2.dat>`
- - `--input-file` Each line in the file contains a `signed-64bit` number which represents
+ - `--input-file` Each line in the file contains a `unsigned-64bit` number which represents
the ID of a S2 cell.
- `--s2-level` The S2 level of all the cells in the input file.
- `--is-allowed-list` Should be either `trrue` or `false`
@@ -51,7 +51,7 @@
- [(prefix=0b100_11111111, suffix=1000), (prefix=0b100_11111111, suffix=2000))
- [(prefix=0b100_11111111, suffix=2000), (prefix=0b100_11111111, suffix=3000))
- [(prefix=0b101_11111111, suffix=1000), (prefix=0b101_11111111, suffix=2000))
-- Run the test tool: `$satellite_createtestsats2file /tmp/foo.dat`
+- Run the test tool: `satellite_createsats2file_test /tmp/foo.dat`
- This command will generate the binary satellite S2 cell file `/tmp/foo.dat` with
the above S2 ranges.
@@ -59,4 +59,9 @@
- Dump the input binary satellite S2 cell file into human-readable text format.
- Run the tool: `$satellite_dumpsats2file /tmp/foo.dat /tmp/foo`
- `/tmp/foo.dat` Input binary satellite S2 cell file.
- - `/tmp/foo` Output directory which contains the output text files.
\ No newline at end of file
+ - `/tmp/foo` Output directory which contains the output text files.
+
+`satellite_location_lookup`
+- Check if a location is present in the input satellite S2 file.
+- Run the tool: `$satellite_location_lookup --input-file <...> --lat-degrees <...>
+ --lng-degrees <...>`
\ No newline at end of file
diff --git a/utils/satellite/s2storage/src/testutils/java/com/android/telephony/sats2range/testutils/TestUtils.java b/utils/satellite/s2storage/src/testutils/java/com/android/telephony/sats2range/testutils/TestUtils.java
index 4b8a026..3cf2c78 100644
--- a/utils/satellite/s2storage/src/testutils/java/com/android/telephony/sats2range/testutils/TestUtils.java
+++ b/utils/satellite/s2storage/src/testutils/java/com/android/telephony/sats2range/testutils/TestUtils.java
@@ -107,19 +107,22 @@
try (PrintStream printer = new PrintStream(outputFile)) {
// Range 1
for (int suffix = 1000; suffix < 2000; suffix++) {
- printer.println(String.valueOf(fileFormat.createCellId(0b100_11111111, suffix)));
+ printer.println(
+ Long.toUnsignedString(fileFormat.createCellId(0b100_11111111, suffix)));
}
// Range 2
for (int suffix = 2001; suffix < 3000; suffix++) {
- printer.println(String.valueOf(fileFormat.createCellId(0b100_11111111, suffix)));
+ printer.println(
+ Long.toUnsignedString(fileFormat.createCellId(0b100_11111111, suffix)));
}
// Range 3
for (int suffix = 1000; suffix < 2000; suffix++) {
- printer.println(String.valueOf(fileFormat.createCellId(0b101_11111111, suffix)));
+ printer.println(
+ Long.toUnsignedString(fileFormat.createCellId(0b101_11111111, suffix)));
}
- printer.print(String.valueOf(fileFormat.createCellId(0b101_11111111, 2000)));
+ printer.print(Long.toUnsignedString(fileFormat.createCellId(0b101_11111111, 2000)));
printer.close();
}
@@ -130,13 +133,13 @@
File outputFile, SatS2RangeFileFormat fileFormat) throws Exception {
try (PrintStream printer = new PrintStream(outputFile)) {
// Valid line
- printer.println(String.valueOf(fileFormat.createCellId(0b100_11111111, 100)));
+ printer.println(Long.toUnsignedString(fileFormat.createCellId(0b100_11111111, 100)));
// Invalid line
printer.print("Invalid line");
// Another valid line
- printer.println(String.valueOf(fileFormat.createCellId(0b100_11111111, 200)));
+ printer.println(Long.toUnsignedString(fileFormat.createCellId(0b100_11111111, 200)));
printer.close();
}
diff --git a/utils/satellite/tools/Android.bp b/utils/satellite/tools/Android.bp
index 9aacdd9..d48b911 100644
--- a/utils/satellite/tools/Android.bp
+++ b/utils/satellite/tools/Android.bp
@@ -39,6 +39,15 @@
],
}
+// A tool to look up a location in the input binary satellite S2 file.
+java_binary_host {
+ name: "satellite_location_lookup",
+ main_class: "com.android.telephony.tools.sats2.SatS2LocationLookup",
+ static_libs: [
+ "satellite-s2storage-tools",
+ ],
+}
+
// A tool to create a test satellite S2 file.
java_binary_host {
name: "satellite_createsats2file_test",
diff --git a/utils/satellite/tools/src/main/java/com/android/telephony/tools/sats2/SatS2FileCreator.java b/utils/satellite/tools/src/main/java/com/android/telephony/tools/sats2/SatS2FileCreator.java
index b701a7b..bc25d6b 100644
--- a/utils/satellite/tools/src/main/java/com/android/telephony/tools/sats2/SatS2FileCreator.java
+++ b/utils/satellite/tools/src/main/java/com/android/telephony/tools/sats2/SatS2FileCreator.java
@@ -30,18 +30,19 @@
import java.nio.charset.StandardCharsets;
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.Scanner;
+import java.util.Set;
import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
/** A util class for creating a satellite S2 file from the list of S2 cells. */
public final class SatS2FileCreator {
/**
* @param inputFile The input text file containing the list of S2 Cell IDs. Each line in the
- * file contains a number in the range of a signed-64bit number which
+ * file contains a number in the range of an unsigned-64bit number which
* represents the ID of a S2 cell.
* @param s2Level The S2 level of all S2 cells in the input file.
* @param isAllowedList {@code true} means the input file contains an allowed list of S2 cells.
@@ -57,12 +58,12 @@
System.out.println("Number of S2 cells read from file:" + s2Cells.size());
// Convert the input list of S2 Cells into the list of sorted S2CellId
- List<S2CellId> sortedS2CellIds = s2Cells.stream()
- .map(x -> new S2CellId(x))
- .collect(Collectors.toList());
+ System.out.println("Denormalizing S2 Cell IDs to the expected s2 level=" + s2Level);
+ List<S2CellId> sortedS2CellIds = denormalize(s2Cells, s2Level);
// IDs of S2CellId are converted to unsigned long numbers, which will be then used to
// compare S2CellId.
Collections.sort(sortedS2CellIds);
+ System.out.println("Number of S2 cell IDs:" + sortedS2CellIds.size());
// Compress the list of S2CellId into S2 ranges
List<SatS2Range> satS2Ranges = createSatS2Ranges(sortedS2CellIds, s2Level);
@@ -132,25 +133,56 @@
* Read a list of S2 cells from the inputFile.
*
* @param inputFile A file containing the list of S2 cells. Each line in the inputFile contains
- * a long number - the ID of a S2 cell.
+ * an unsigned long number - the ID of a S2 cell.
* @return A list of S2 cells.
*/
private static List<Long> readS2CellsFromFile(String inputFile) throws Exception {
List<Long> s2Cells = new ArrayList();
InputStream inputStream = new FileInputStream(inputFile);
try (Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) {
- while (scanner.hasNextLong()) {
- s2Cells.add(scanner.nextLong());
- }
- if (scanner.hasNextLine()) {
- throw new IllegalStateException("Input s2 cell file has invalid format, "
- + "current line=" + scanner.nextLine());
+ while (scanner.hasNextLine()) {
+ String line = scanner.nextLine();
+ try {
+ s2Cells.add(Long.parseUnsignedLong(line));
+ } catch (Exception ex) {
+ throw new IllegalStateException("Input s2 cell file has invalid format, "
+ + "current line=" + line);
+ }
}
}
return s2Cells;
}
/**
+ * Convert the list of S2 Cell numbers into the list of S2 Cell IDs at the expected level.
+ */
+ private static List<S2CellId> denormalize(List<Long> s2CellNumbers, int s2Level) {
+ Set<S2CellId> result = new HashSet<>();
+ for (long s2CellNumber : s2CellNumbers) {
+ S2CellId s2CellId = new S2CellId(s2CellNumber);
+ if (s2CellId.level() == s2Level) {
+ if (!result.contains(s2CellId)) {
+ result.add(s2CellId);
+ }
+ } else if (s2CellId.level() < s2Level) {
+ S2CellId childEnd = s2CellId.childEnd(s2Level);
+ for (s2CellId = s2CellId.childBegin(s2Level); !s2CellId.equals(childEnd);
+ s2CellId = s2CellId.next()) {
+ if (!result.contains(s2CellId)) {
+ result.add(s2CellId);
+ }
+ }
+ } else {
+ S2CellId parent = s2CellId.parent(s2Level);
+ if (!result.contains(parent)) {
+ result.add(parent);
+ }
+ }
+ }
+ return new ArrayList(result);
+ }
+
+ /**
* Compress the list of sorted S2CellId into S2 ranges.
*
* @param sortedS2CellIds List of S2CellId sorted in ascending order.
diff --git a/utils/satellite/tools/src/main/java/com/android/telephony/tools/sats2/SatS2LocationLookup.java b/utils/satellite/tools/src/main/java/com/android/telephony/tools/sats2/SatS2LocationLookup.java
new file mode 100644
index 0000000..444ff8d
--- /dev/null
+++ b/utils/satellite/tools/src/main/java/com/android/telephony/tools/sats2/SatS2LocationLookup.java
@@ -0,0 +1,77 @@
+/*
+ * 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.telephony.tools.sats2;
+
+import com.android.telephony.sats2range.read.SatS2RangeFileReader;
+
+import com.beust.jcommander.JCommander;
+import com.beust.jcommander.Parameter;
+import com.google.common.geometry.S2CellId;
+import com.google.common.geometry.S2LatLng;
+
+import java.io.File;
+
+/** A util class for checking if a location is in the input satellite S2 file. */
+public final class SatS2LocationLookup {
+ /**
+ * A util method for checking if a location is in the input satellite S2 file.
+ */
+ public static void main(String[] args) throws Exception {
+ Arguments arguments = new Arguments();
+ JCommander.newBuilder()
+ .addObject(arguments)
+ .build()
+ .parse(args);
+
+ try (SatS2RangeFileReader satS2RangeFileReader =
+ SatS2RangeFileReader.open(new File(arguments.inputFile))) {
+ S2CellId s2CellId = getS2CellId(arguments.latDegrees, arguments.lngDegrees,
+ satS2RangeFileReader.getS2Level());
+ System.out.println("s2CellId=" + Long.toUnsignedString(s2CellId.id()));
+ if (satS2RangeFileReader.findEntryByCellId(s2CellId.id()) == null) {
+ System.out.println("The input file does not contain the input location");
+ } else {
+ System.out.println("The input file contains the input location");
+ }
+ }
+ }
+
+ private static S2CellId getS2CellId(double latDegrees, double lngDegrees, int s2Level) {
+ // Create the leaf S2 cell containing the given S2LatLng
+ S2CellId cellId = S2CellId.fromLatLng(S2LatLng.fromDegrees(latDegrees, lngDegrees));
+
+ // Return the S2 cell at the expected S2 level
+ return cellId.parent(s2Level);
+ }
+
+ private static class Arguments {
+ @Parameter(names = "--input-file",
+ description = "sat s2 file",
+ required = true)
+ public String inputFile;
+
+ @Parameter(names = "--lat-degrees",
+ description = "lat degress of the location",
+ required = true)
+ public double latDegrees;
+
+ @Parameter(names = "--lng-degrees",
+ description = "lng degress of the location",
+ required = true)
+ public double lngDegrees;
+ }
+}