[automerger skipped] Merge Android 24Q1 Release (ab/11220357) am: c2d869b24e -s ours
am skip reason: Merged-In I6b2e963351a5c428c23986ff92a997221a95919c with SHA-1 ec14422c9b is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/services/Telephony/+/25973728
Change-Id: Idc300e8a14d8b35e105456d148d846b367c80716
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index ffd2292..a943299 100644
--- a/Android.bp
+++ b/Android.bp
@@ -95,18 +95,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..b2548f1 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,8 @@
<!-- 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 bind the domain selection service. -->
+ <uses-permission android:name="android.permission.BIND_DOMAIN_SELECTION_SERVICE" />
<application android:name="PhoneApp"
android:persistent="true"
@@ -626,5 +627,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/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/values-da/strings.xml b/res/values-da/strings.xml
index 58f2670..801eb12 100644
--- a/res/values-da/strings.xml
+++ b/res/values-da/strings.xml
@@ -862,7 +862,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-fa/strings.xml b/res/values-fa/strings.xml
index c52cb86..76ae668 100644
--- a/res/values-fa/strings.xml
+++ b/res/values-fa/strings.xml
@@ -661,7 +661,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>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
index 85a5a93..8b3f378 100644
--- a/res/values-fr/strings.xml
+++ b/res/values-fr/strings.xml
@@ -595,7 +595,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>
diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml
index 4f8e559..febd572 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>
diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml
index fe39ede..011b30b 100644
--- a/res/values-kn/strings.xml
+++ b/res/values-kn/strings.xml
@@ -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>
@@ -598,7 +598,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>
diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml
index 0ab1b47..2c68ef1 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>
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 8576e1f..b4c7573 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -675,7 +675,7 @@
<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_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>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 5eea570..fd8e728 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>
@@ -674,8 +674,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>
diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml
index 1f86b13..975cdc7 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>
diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml
index 2cbcafa..9e1f6fe 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>
@@ -543,7 +543,7 @@
<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_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_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>
@@ -568,8 +568,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 +692,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 +716,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 +802,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>
diff --git a/res/values/config.xml b/res/values/config.xml
index dcfa364..7cd4e18 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -337,7 +337,8 @@
<item>de</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>
+ <!-- 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/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 3eafb24..ef71016 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;
@@ -66,6 +69,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;
@@ -685,12 +689,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 +728,8 @@
TelephonyManager.from(context).registerCarrierPrivilegesCallback(phoneId,
new HandlerExecutor(mHandler), mCarrierServiceChangeCallbacks[phoneId]);
}
+ mFeatureFlags = featureFlags;
+ mPackageManager = context.getPackageManager();
logd("CarrierConfigLoader has started");
PhoneConfigurationManager.registerForMultiSimConfigChange(
@@ -733,10 +744,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 +1335,8 @@
return new PersistableBundle();
}
+ enforceTelephonyFeatureWithException(callingPackage, "getConfigForSubIdWithFeature");
+
int phoneId = SubscriptionManager.getPhoneId(subscriptionId);
PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig();
if (SubscriptionManager.isValidPhoneId(phoneId)) {
@@ -1367,6 +1381,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 +1433,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);
@@ -1468,6 +1488,9 @@
"Invalid phoneId " + phoneId + " for subId " + subscriptionId);
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "notifyConfigChangedForSubId");
+
logdWithLocalLog("Notified carrier config changed. phoneId=" + phoneId
+ ", subId=" + subscriptionId);
@@ -1488,6 +1511,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 +1535,10 @@
@NonNull
public String getDefaultCarrierServicePackageName() {
getDefaultCarrierServicePackageName_enforcePermission();
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ "getDefaultCarrierServicePackageName");
+
return mPlatformCarrierConfigPackage;
}
@@ -1819,6 +1849,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/DiagnosticDataCollector.java b/src/com/android/phone/DiagnosticDataCollector.java
index e997270..bdd9ce9 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;
@@ -84,7 +83,7 @@
persistTelecomState(dc, tag);
}
if (edp.isLogcatCollectionEnabled()) {
- persistLogcat(dc, tag, edp.getLogcatStartTime());
+ persistLogcat(dc, tag, edp.getLogcatCollectionStartTimeMillis());
}
}
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/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index f93b1e5..7fba651 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -83,7 +83,6 @@
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;
@@ -166,7 +165,6 @@
public ImsStateCallbackController mImsStateCallbackController;
public ImsProvisioningController mImsProvisioningController;
CarrierConfigLoader configLoader;
- TelephonyDomainSelectionService mDomainSelectionService;
private Phone phoneInEcm;
@@ -496,8 +494,9 @@
// 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();
@@ -506,8 +505,7 @@
// 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,9 +574,9 @@
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 =
@@ -994,6 +992,11 @@
}
ServiceState serviceState = phone.getServiceState();
+ if (serviceState == null) {
+ Log.e(LOG_TAG, "updateDataRoamingStatus: serviceState is null");
+ return;
+ }
+
String roamingNumeric = serviceState.getOperatorNumeric();
String roamingNumericReason = "RoamingNumeric=" + roamingNumeric;
String callingReason = "CallingReason=" + reason;
@@ -1385,9 +1388,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..43011e8 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -16,10 +16,16 @@
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_SUCCESS;
import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_GSM;
@@ -150,8 +156,8 @@
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.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.NtnSignalStrengthCallback;
@@ -207,6 +213,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 +247,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;
@@ -403,28 +412,31 @@
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 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 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_";
@@ -2460,9 +2472,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 +2573,9 @@
}
public void dial(String number) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "dial");
+
dialForSubscriber(getPreferredVoiceSubscription(), number);
}
@@ -2599,6 +2621,9 @@
return;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "call");
+
final long identity = Binder.clearCallingIdentity();
try {
String url = createTelUrl(number);
@@ -2642,6 +2667,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 +2685,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 +2893,9 @@
return false;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "isRadioOnWithFeature");
+
final long identity = Binder.clearCallingIdentity();
try {
return isRadioOnForSubscriber(subId);
@@ -2890,6 +2925,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 +2963,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 +2988,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 +3072,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 +3105,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 +3135,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 +3163,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 +3187,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 +3208,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 +3231,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 +3249,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 +3299,10 @@
+ "targeting API level 31+.");
}
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getCallStateForSubscription");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -3247,6 +3320,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 +3344,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 +3384,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 +3400,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 +3473,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 +3529,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 +3600,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 +3640,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_GSM, "getImeiForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
return phone.getImei();
@@ -3562,6 +3658,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 +3677,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 +3714,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CDMA, "getMeidForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
return phone.getMeid();
@@ -3621,6 +3727,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 +3759,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY, "getDeviceSoftwareVersionForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
return phone.getDeviceSvn();
@@ -3660,6 +3772,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 +3786,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 +3800,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 +3815,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 +3837,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 +3961,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 +3995,10 @@
return -1;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CDMA,
+ "getCdmaEriIconIndexForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -3948,6 +4084,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 +4109,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 +4141,9 @@
+ ", configured package: " + authorizedPackage);
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "requestNumberVerification");
+
if (range == null) {
throw new NullPointerException("Range must be non-null");
}
@@ -4013,6 +4158,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 +4177,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 +4199,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 +4224,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getVisualVoicemailPackageName");
+
final long identity = Binder.clearCallingIdentity();
try {
return RemoteVvmTaskManager.getRemotePackage(mApp, subId).getPackageName();
@@ -4083,6 +4240,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 +4256,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 +4302,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 +4319,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 +4343,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 +4366,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 +4389,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 +4435,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 +4462,9 @@
getDefaultSubscription(), "sendDialerSpecialCode");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "sendDialerSpecialCode");
+
final long identity = Binder.clearCallingIdentity();
try {
defaultPhone.sendDialerSpecialCode(inputCode);
@@ -4293,6 +4478,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 +4496,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 +4584,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 +4794,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 +4817,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 +4884,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isAdvancedCallingSettingEnabled");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isAdvancedCallingSettingEnabled");
+
final long token = Binder.clearCallingIdentity();
try {
int slotId = getSlotIndexOrException(subId);
@@ -4629,6 +4903,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 +4928,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 +4948,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 +4973,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 +4993,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 +5019,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 +5046,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 +5072,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 +5092,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 +5113,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 +5137,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 +5157,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 +5177,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 +5197,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 +5218,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 +5243,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 +5372,9 @@
boolean isProvisioned) {
checkModifyPhoneStatePermission(subId, "setRcsProvisioningStatusForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setRcsProvisioningStatusForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5054,6 +5395,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getRcsProvisioningStatusForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getRcsProvisioningStatusForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5074,6 +5418,9 @@
boolean isProvisioned) {
checkModifyPhoneStatePermission(subId, "setImsProvisioningStatusForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "setImsProvisioningStatusForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5093,6 +5440,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getProvisioningStatusForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "getImsProvisioningStatusForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5113,6 +5463,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isProvisioningRequiredForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isProvisioningRequiredForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5133,6 +5486,9 @@
TelephonyPermissions.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isProvisioningRequiredForCapability");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ FEATURE_TELEPHONY_IMS, "isRcsProvisioningRequiredForCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5156,6 +5512,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 +5555,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 +5585,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 +5627,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 +5704,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 +5744,9 @@
}
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getDataNetworkTypeForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -5400,6 +5775,9 @@
}
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getVoiceNetworkTypeForSubscriber");
+
final long identity = Binder.clearCallingIdentity();
try {
final Phone phone = getPhone(subId);
@@ -5427,6 +5805,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 +5845,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 +5929,7 @@
@Override
public IccOpenLogicalChannelResponse iccOpenLogicalChannel(
@NonNull IccLogicalChannelRequest request) {
+
Phone phone = getPhoneFromValidIccLogicalChannelRequest(request,
/*message=*/ "iccOpenLogicalChannel");
@@ -5552,6 +5937,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 +5986,9 @@
@Override
public boolean iccCloseLogicalChannel(@NonNull IccLogicalChannelRequest request) {
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "iccCloseLogicalChannel");
+
Phone phone = getPhoneFromValidIccLogicalChannelRequest(request,
/*message=*/"iccCloseLogicalChannel");
@@ -5645,6 +6036,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 +6053,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 +6099,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 +6116,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 +6172,9 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "iccExchangeSimIO");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "iccExchangeSimIO");
+
final long identity = Binder.clearCallingIdentity();
try {
if (DBG) {
@@ -5809,6 +6220,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getForbiddenPlmns");
+
final long identity = Binder.clearCallingIdentity();
try {
if (appType != TelephonyManager.APPTYPE_USIM
@@ -5845,6 +6259,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 +6291,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 +6399,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 +6428,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 +6451,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 +6733,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 +6766,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 +6799,9 @@
.enforceCallingOrSelfReadPrecisePhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "getManualNetworkSelectionPlmn");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getManualNetworkSelectionPlmn");
+
final long identity = Binder.clearCallingIdentity();
try {
if (!isActiveSubscription(subId)) {
@@ -6426,6 +6864,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 +6920,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 +6957,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 +7012,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 +7112,10 @@
}
}
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "requestNetworkScan");
+
int callingUid = Binder.getCallingUid();
int callingPid = Binder.getCallingPid();
final long identity = Binder.clearCallingIdentity();
@@ -6733,6 +7191,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 +7218,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 +7315,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 +7364,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 +7470,9 @@
enforceReadPrivilegedPermission(functionName);
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isDataEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
int phoneId = SubscriptionManager.getPhoneId(subId);
@@ -7043,6 +7519,8 @@
}
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isDataEnabledForReason");
final long identity = Binder.clearCallingIdentity();
try {
@@ -7071,6 +7549,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 +7559,10 @@
@Override
public int getCarrierPrivilegeStatusForUid(int subId, int uid) {
enforceReadPrivilegedPermission("getCarrierPrivilegeStatusForUid");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getCarrierPrivilegeStatusForUid");
+
return getCarrierPrivilegeStatusForUidWithPermission(subId, uid);
}
@@ -7098,6 +7583,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 +7606,11 @@
@Override
public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
enforceReadPrivilegedPermission("checkCarrierPrivilegesForPackageAnyPhone");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "checkCarrierPrivilegesForPackageAnyPhone");
+
return checkCarrierPrivilegesForPackageAnyPhoneWithPermission(pkgName);
}
@@ -7145,6 +7639,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 +7672,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 +7693,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 +7725,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 +7751,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 +7776,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 +7836,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getLine1NumberForDisplay");
+
final long identity = Binder.clearCallingIdentity();
try {
String iccId = getIccId(subId);
@@ -7445,6 +7966,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 +8014,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 +8063,9 @@
throw e;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getRadioAccessFamily");
+
final long identity = Binder.clearCallingIdentity();
try {
raf = ProxyController.getInstance().getRadioAccessFamily(phoneId);
@@ -7556,6 +8086,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 +8176,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 +8196,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 +8224,9 @@
return false;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "canChangeDtmfToneLength");
+
final long identity = Binder.clearCallingIdentity();
try {
CarrierConfigManager configManager =
@@ -7702,6 +8245,9 @@
return false;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY, "isWorldPhone");
+
final long identity = Binder.clearCallingIdentity();
try {
CarrierConfigManager configManager =
@@ -7721,6 +8267,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 +8286,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 +8298,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 +8315,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 +8410,10 @@
subscriptionId,
"getPhoneAccountHandleForSubscriptionId, " + "subscriptionId: "
+ subscriptionId);
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CALLING, "getPhoneAccountHandleForSubscriptionId");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subscriptionId);
@@ -7918,6 +8481,10 @@
@Override
public void factoryReset(int subId, String callingPackage) {
enforceSettingsPermission();
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY, "factoryReset");
+
if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
return;
}
@@ -7990,6 +8557,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 +8643,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 +8791,9 @@
return null;
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "getServiceStateForSubscriber");
+
boolean hasFinePermission = false;
boolean hasCoarsePermission = false;
if (!renounceFineLocationAccess) {
@@ -8295,6 +8873,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 +8912,9 @@
"setVoicemailRingtoneUri");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setVoicemailRingtoneUri");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
@@ -8352,6 +8936,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 +8975,9 @@
"setVoicemailVibrationEnabled");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_CALLING, "setVoicemailVibrationEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(phoneAccountHandle);
@@ -8464,6 +9054,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 +9115,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 +9168,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 +9198,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,6 +9232,10 @@
@Override
public void getCarrierRestrictionStatus(IIntegerConsumer callback, String packageName) {
enforceReadPermission("getCarrierRestrictionStatus");
+
+ enforceTelephonyFeatureWithException(packageName,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "getCarrierRestrictionStatus");
+
int carrierId = validateCallerAndGetCarrierId(packageName);
if (carrierId == CarrierAllowListInfo.INVALID_CARRIER_ID) {
Rlog.e(LOG_TAG, "getCarrierRestrictionStatus: caller is not registered");
@@ -8748,6 +9358,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 +9387,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);
@@ -8840,6 +9459,9 @@
callingPackage, null, null);
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_DATA, "setDataEnabledForReason");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subId);
@@ -8910,6 +9532,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 +9565,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 +9607,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 +9628,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 +9660,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 +9703,9 @@
mApp, subId, functionName);
}
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "isDataRoamingEnabled");
+
boolean isEnabled = false;
final long identity = Binder.clearCallingIdentity();
try {
@@ -9089,6 +9733,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 +9753,9 @@
.enforceCallingOrSelfReadPrivilegedPhoneStatePermissionOrCarrierPrivilege(
mApp, subId, "isManualNetworkSelectionAllowed");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_RADIO_ACCESS, "isManualNetworkSelectionAllowed");
+
boolean isAllowed = true;
final long identity = Binder.clearCallingIdentity();
try {
@@ -9152,6 +9802,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 +9916,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 +10021,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 +10043,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 +10056,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();
@@ -9559,6 +10225,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 +10241,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 +10258,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 +10274,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 +10293,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 +10322,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 +10418,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 +10438,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 +10458,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 +10478,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 +10521,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 +10552,9 @@
throw new SecurityException("Requires READ_PHONE_STATE permission.");
}
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY, "isModemEnabledForSlot");
+
final long identity = Binder.clearCallingIdentity();
try {
try {
@@ -9867,6 +10571,9 @@
public void setMultiSimCarrierRestriction(boolean isMultiSimCarrierRestricted) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_CARRIERLOCK, "setMultiSimCarrierRestriction");
+
final long identity = Binder.clearCallingIdentity();
try {
mTelephonySharedPreferences.edit()
@@ -9886,6 +10593,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 +10647,10 @@
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, "switchMultiSimConfig");
}
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION, "switchMultiSimConfig");
+
final long identity = Binder.clearCallingIdentity();
try {
@@ -9954,6 +10668,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 +10708,11 @@
"doesSwitchMultiSimConfigTriggerReboot")) {
return false;
}
+
+ enforceTelephonyFeatureWithException(callingPackage,
+ PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION,
+ "doesSwitchMultiSimConfigTriggerReboot");
+
final long identity = Binder.clearCallingIdentity();
try {
return mPhoneConfigurationManager.isRebootRequiredForModemConfigChange();
@@ -10010,6 +10733,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 +10781,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 +10810,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 +10835,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 +10855,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 +10893,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 +10915,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 +10966,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 +10986,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 +11008,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 +11027,9 @@
boolean enabled) {
enforceModifyPermission();
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_DATA, "setMobileDataPolicyEnabled");
+
final long identity = Binder.clearCallingIdentity();
try {
Phone phone = getPhone(subscriptionId);
@@ -10324,10 +11084,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 +11111,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 +11143,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 +11178,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 +11251,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 +11270,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 +11290,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 +11453,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 +11687,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 +11725,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 +11760,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 +11792,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 +12215,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 +12244,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 +12313,10 @@
@Override
public PhoneCapability getPhoneCapability() {
enforceReadPrivilegedPermission("getPhoneCapability");
+
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY, "getPhoneCapability");
+
final long identity = Binder.clearCallingIdentity();
try {
return mPhoneConfigurationManager.getCurrentPhoneCapability();
@@ -11502,6 +12335,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 +12358,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 +12390,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 +12435,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 +12573,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 +12651,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 +12740,10 @@
boolean updateIfNeeded) {
enforceInteractAcrossUsersPermission("getDefaultRespondViaMessageApplication");
+ enforceTelephonyFeatureWithException(getCurrentPackageName(),
+ PackageManager.FEATURE_TELEPHONY_MESSAGING,
+ "getDefaultRespondViaMessageApplication");
+
Context context = getPhoneFromSubIdOrDefault(subId).getContext();
UserHandle userHandle = null;
@@ -11952,6 +12824,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 +12844,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,11 +12876,15 @@
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);
+ TelephonyManager.EmergencyCallDiagnosticParams.Builder edpBuilder =
+ new TelephonyManager.EmergencyCallDiagnosticParams.Builder();
+ edpBuilder
+ .setTelecomDumpSysCollectionEnabled(enableTelecomDump)
+ .setTelephonyDumpSysCollectionEnabled(enableTelephonyDump);
+ if (enableLogcat) {
+ edpBuilder.setLogcatCollectionStartTimeMillis(logcatStartTimestampMillis);
+ }
+ TelephonyManager.EmergencyCallDiagnosticParams edp = edpBuilder.build();
Log.d(LOG_TAG, "persisting with Params " + edp.toString());
DiagnosticDataCollector ddc = new DiagnosticDataCollector(Runtime.getRuntime(),
Executors.newCachedThreadPool(), db,
@@ -12036,6 +12926,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 +12949,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);
@@ -12110,8 +13008,41 @@
public void requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode,
@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, 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, callback);
+ }
}
/**
@@ -12315,7 +13246,7 @@
*/
@Override
@SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
- @NonNull ISatelliteStateCallback callback) {
+ @NonNull ISatelliteModemStateCallback callback) {
enforceSatelliteCommunicationPermission("registerForSatelliteModemStateChanged");
return mSatelliteController.registerForSatelliteModemStateChanged(subId, callback);
}
@@ -12326,15 +13257,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 +13279,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 +13291,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 +13314,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 +13338,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 +13358,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);
}
@@ -12478,13 +13407,13 @@
*
* @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);
}
@@ -12501,14 +13430,13 @@
*
* @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);
}
@@ -12524,13 +13452,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 +13546,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,17 +13563,17 @@
*
* @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);
}
@@ -12765,6 +13693,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.
@@ -12802,7 +13798,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 +13820,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:
@@ -12881,4 +13920,47 @@
return mCarrierId;
}
}
+
+ /*
+ * 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 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/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 5986a7c..f7a3640d 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -24,6 +24,8 @@
import static java.util.Map.entry;
import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.net.Uri;
import android.os.Binder;
@@ -65,6 +67,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;
@@ -191,6 +194,11 @@
"set-satellite-device-aligned-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";
@@ -388,6 +396,12 @@
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);
}
@@ -795,6 +809,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() {
@@ -3394,6 +3431,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";
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..76032f8 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -16,17 +16,62 @@
package com.android.phone.satellite.accesscontrol;
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import android.annotation.ArrayRes;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+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.SatelliteController;
+import com.android.phone.PhoneGlobals;
+
+import java.io.File;
+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 +79,141 @@
*/
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;
+
+ private static SatelliteAccessController sInstance;
/** Feature flags to control behavior and errors. */
@NonNull private final FeatureFlags mFeatureFlags;
- @Nullable private final SatelliteOnDeviceAccessController mSatelliteOnDeviceAccessController;
+ @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 mInternalSatelliteAllowResultReceiver;
+ @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;
+ private static final String GOOGLE_US_SAN_SAT_S2_FILE_NAME = "google_us_san_sat_s2.dat";
/**
* Create a SatelliteAccessController instance.
*
+ * @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 location-based satellite restriction lookup.
+ * @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();
+ loadOverlayConfigs(context);
+ if (s2CellFile != null) {
+ mSatelliteS2CellFile = s2CellFile;
+ }
+ mInternalSatelliteAllowResultReceiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ handleSatelliteAllowResultFromSatelliteController(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;
default:
logw("SatelliteAccessControllerHandler: unexpected message code: " + msg.what);
@@ -72,23 +224,677 @@
/**
* 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;
+ }
+
+ private 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;
+ }
+
+ 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();
+ }
+
+ 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 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.requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ requestArguments.first, mInternalSatelliteAllowResultReceiver);
+ }
+ }
+
+ 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 handleSatelliteAllowResultFromSatelliteController(
+ int resultCode, Bundle resultData) {
+ logd("handleSatelliteAllowResultFromSatelliteController: resultCode=" + resultCode);
+ synchronized (mLock) {
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
+ boolean isSatelliteAllowed = resultData.getBoolean(
+ KEY_SATELLITE_COMMUNICATION_ALLOWED);
+ if (!isSatelliteAllowed) {
+ logd("Satellite is not allowed by modem");
+ sendSatelliteAllowResultToReceivers(resultCode, resultData);
+ } else {
+ checkSatelliteAccessRestrictionForCurrentLocation();
+ }
+ } else {
+ loge("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist.");
+ sendSatelliteAllowResultToReceivers(resultCode, resultData);
+ }
+ } else if (resultCode == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
+ checkSatelliteAccessRestrictionForCurrentLocation();
+ } 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;
+ }
+
+ /**
+ * @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));
}
/**
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..c856eb5
--- /dev/null
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApi.java
@@ -0,0 +1,71 @@
+/*
+ * 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 {
+ @NonNull
+ private final ServiceEntitlement mServiceEntitlement;
+ private final Context mContext;
+
+ public SatelliteEntitlementApi(@NonNull Context context,
+ @NonNull PersistableBundle carrierConfig, @NonNull int subId) {
+ mContext = context;
+ mServiceEntitlement = new ServiceEntitlement(mContext,
+ getCarrierConfigFromEntitlementServerUrl(carrierConfig), subId);
+ }
+
+ /**
+ * 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);
+ 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());
+ }
+
+ @NonNull
+ private CarrierConfig getCarrierConfigFromEntitlementServerUrl(
+ @NonNull PersistableBundle carrierConfig) {
+ String entitlementServiceUrl = carrierConfig.getString(
+ CarrierConfigManager.ImsServiceEntitlement.KEY_ENTITLEMENT_SERVER_URL_STRING,
+ "");
+ return CarrierConfig.builder().setServerUrl(entitlementServiceUrl).build();
+ }
+}
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..94362a0
--- /dev/null
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementController.java
@@ -0,0 +1,542 @@
+/*
+ * 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());
+ 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);
+ 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) {
+ SatelliteController.getInstance().onSatelliteEntitlementStatusUpdated(subId, enabled,
+ plmnAllowedList, 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..1fe0ecf
--- /dev/null
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponse.java
@@ -0,0 +1,151 @@
+/*
+ * 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.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<>();
+ 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
+ */
+ @VisibleForTesting
+ 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) : "";
+ mPlmnAllowedList.add(new SatelliteNetworkInfo(
+ jsonArray.getJSONObject(i).getString(PLMN_KEY), 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++) {
+ mPlmnBarredList.add(jsonArray.getJSONObject(i).getString(PLMN_KEY));
+ }
+ }
+ } catch (JSONException e) {
+ loge("parsingResponse: failed JSONException", e);
+ } catch (NumberFormatException e) {
+ loge("parsingResponse: failed NumberFormatException", e);
+ }
+ }
+
+ 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..3289232
--- /dev/null
+++ b/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResult.java
@@ -0,0 +1,98 @@
+/*
+ * 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;
+
+ /**
+ * Store the result of the satellite entitlement response.
+ *
+ * @param entitlementStatus The entitlement status.
+ * @param allowedSatelliteNetworkInfoList The allowedSatelliteNetworkInfoList
+ */
+ public SatelliteEntitlementResult(@SatelliteEntitlementStatus int entitlementStatus,
+ List<SatelliteNetworkInfo> allowedSatelliteNetworkInfoList) {
+ mEntitlementStatus = entitlementStatus;
+ mAllowedSatelliteNetworkInfoList = allowedSatelliteNetworkInfoList;
+ }
+
+ /**
+ * 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 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<>());
+ }
+}
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index f6cd0d1..f3158e6 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -104,8 +104,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;
@@ -305,8 +303,6 @@
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,8 +508,6 @@
log("Started onCreate");
- mFeatureFlags = new FeatureFlagsImpl();
-
mQueuedWork = new ThreadPoolExecutor(1, 1, RUNNABLE_TIMEOUT_MS, TimeUnit.MICROSECONDS,
new LinkedBlockingDeque<Runnable>());
mConnectivityManager = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
@@ -1573,11 +1567,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() {
diff --git a/src/com/android/services/telephony/DisconnectCauseUtil.java b/src/com/android/services/telephony/DisconnectCauseUtil.java
index adb07f9..91ecb93 100644
--- a/src/com/android/services/telephony/DisconnectCauseUtil.java
+++ b/src/com/android/services/telephony/DisconnectCauseUtil.java
@@ -31,7 +31,7 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.phone.ImsUtil;
import com.android.phone.PhoneGlobals;
-import com.android.phone.common.R;
+import com.android.phone.R;
public class DisconnectCauseUtil {
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index ea29b77..efa5278 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -64,6 +64,7 @@
import com.android.internal.telephony.ExponentialBackoff;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.phone.PhoneGlobals;
import com.android.phone.PhoneUtils;
@@ -465,6 +466,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;
@@ -804,6 +814,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.
*
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index f96e6bd..9fe73e2 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;
@@ -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.");
diff --git a/src/com/android/services/telephony/TelephonyConnectionService.java b/src/com/android/services/telephony/TelephonyConnectionService.java
index 8ab2723..8a0382a 100644
--- a/src/com/android/services/telephony/TelephonyConnectionService.java
+++ b/src/com/android/services/telephony/TelephonyConnectionService.java
@@ -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;
@@ -641,6 +642,13 @@
}
};
+ private void clearNormalCallDomainSelectionConnection() {
+ if (mDomainSelectionConnection != null) {
+ mDomainSelectionConnection.finishSelection();
+ mDomainSelectionConnection = null;
+ }
+ }
+
/**
* A listener for calls.
*/
@@ -653,17 +661,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;
@@ -1132,6 +1138,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 +1163,7 @@
&& phone.getHalVersion(HAL_SERVICE_VOICE)
.less(RIL.RADIO_HAL_VERSION_1_4);
if (mDomainSelectionResolver.isDomainSelectionSupported()) {
- if (isEmergencyNumber) {
+ if (isEmergencyNumber && phone == phoneForEmergency) {
// Since the domain selection service is enabled,
// dilaing normal routing emergency number only reaches here.
if (!isVoiceInService(phone, imsVoiceCapable)) {
@@ -2226,23 +2233,11 @@
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()));
@@ -2262,6 +2257,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);
@@ -2291,6 +2305,20 @@
.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);
+ mNormalCallConnection.setTelephonyConnectionDisconnected(mDisconnectCauseFactory
+ .toTelecomDisconnectCause(telephonyDisconnectCause,
+ "Connection is null", phone.getPhoneId()));
+ clearNormalCallDomainSelectionConnection();
+ mNormalCallConnection.close();
+ return;
+ }
+
mNormalCallConnection.setOriginalConnection(connection);
mNormalCallConnection.addTelephonyConnectionListener(mNormalCallConnectionListener);
return;
@@ -2314,10 +2342,7 @@
e.getMessage(), phone.getPhoneId()));
mNormalCallConnection.close();
}
- if (mDomainSelectionConnection != null) {
- mDomainSelectionConnection.finishSelection();
- mDomainSelectionConnection = null;
- }
+ clearNormalCallDomainSelectionConnection();
mNormalCallConnection = null;
}
@@ -2558,10 +2583,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());
@@ -2757,10 +2779,7 @@
}
c.removeTelephonyConnectionListener(mTelephonyConnectionListener);
- if (mDomainSelectionConnection != null) {
- mDomainSelectionConnection.finishSelection();
- mDomainSelectionConnection = null;
- }
+ clearNormalCallDomainSelectionConnection();
mNormalCallConnection = null;
Log.d(LOG_TAG, "Reselect call domain not triggered.");
return false;
@@ -3599,6 +3618,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.
@@ -3907,10 +3931,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
@@ -3920,10 +3968,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();
@@ -3948,13 +3997,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);
}
@@ -3964,13 +4016,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()
@@ -4242,6 +4297,10 @@
}
ServiceState serviceState = phone.getServiceState();
+ if (serviceState == null) {
+ return false;
+ }
+
if (!serviceState.isUsingNonTerrestrialNetwork()) {
// Device is not connected to satellite
return false;
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
index 3d6a4d1..074fa64 100644
--- a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -54,6 +54,7 @@
import static android.telephony.PreciseDisconnectCause.EMERGENCY_PERM_FAILURE;
import static android.telephony.PreciseDisconnectCause.EMERGENCY_TEMP_FAILURE;
import static android.telephony.PreciseDisconnectCause.SERVICE_OPTION_NOT_AVAILABLE;
+import static android.telephony.TelephonyManager.DATA_CONNECTED;
import android.annotation.NonNull;
import android.content.Context;
@@ -211,13 +212,15 @@
private final PowerManager.WakeLock mPartialWakeLock;
private final CrossSimRedialingController mCrossSimRedialingController;
private final CarrierConfigHelper mCarrierConfigHelper;
+ private final EmergencyCallbackModeHelper mEcbmHelper;
/** 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 CarrierConfigHelper carrierConfigHelper,
+ @NonNull EmergencyCallbackModeHelper ecbmHelper) {
super(context, slotId, subId, looper, imsStateTracker, destroyListener, TAG);
mImsStateTracker.addBarringInfoListener(this);
@@ -228,6 +231,7 @@
mCrossSimRedialingController = csrController;
mCarrierConfigHelper = carrierConfigHelper;
+ mEcbmHelper = ecbmHelper;
acquireWakeLock();
}
@@ -630,7 +634,8 @@
return;
}
- if (isWifiPreferred()) {
+ if (isWifiPreferred()
+ || isInEmergencyCallbackModeOnWlan()) {
onWlanSelected();
return;
}
@@ -652,12 +657,17 @@
boolean psInService = isPsInService();
if (!csInService && !psInService) {
+ mCsNetworkType = getSelectableCsNetworkType();
mPsNetworkType = getSelectablePsNetworkType(false);
- logi("selectDomain limited service ps=" + accessNetworkTypeToString(mPsNetworkType));
- if (mPsNetworkType == UNKNOWN) {
- requestScan(true);
- } else {
+ logi("selectDomain limited service ps=" + accessNetworkTypeToString(mPsNetworkType)
+ + ", cs=" + accessNetworkTypeToString(mCsNetworkType));
+ // If NGRAN, request scan to trigger emergency registration.
+ if (mPsNetworkType == EUTRAN) {
onWwanNetworkTypeSelected(mPsNetworkType);
+ } else if (mCsNetworkType != UNKNOWN) {
+ onWwanNetworkTypeSelected(mCsNetworkType);
+ } else {
+ requestScan(true);
}
return;
}
@@ -675,7 +685,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()) {
@@ -686,7 +697,8 @@
}
} else if (psAvailable) {
mTryEpsFallback = (mPsNetworkType == NGRAN) && isEpsFallbackAvailable();
- if (!mRequiresImsRegistration || isImsRegisteredWithVoiceCapability()) {
+ if (mSelectionAttributes.isExitedFromAirplaneMode()
+ || !mRequiresImsRegistration || isImsRegisteredWithVoiceCapability()) {
onWwanNetworkTypeSelected(mPsNetworkType);
} else if (isDeactivatedSim()) {
// Deactivated SIM but PS is in service and supports emergency calls.
@@ -701,7 +713,8 @@
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);
@@ -1540,10 +1553,21 @@
}
}
+ private boolean isInEmergencyCallbackModeOnWlan() {
+ return mEcbmHelper.isInEmergencyCallbackMode(getSlotId())
+ && mEcbmHelper.getTransportType(getSlotId()) == TRANSPORT_TYPE_WLAN
+ && mEcbmHelper.getDataConnectionState(getSlotId()) == DATA_CONNECTED;
+ }
+
private void selectDomainForTestEmergencyNumber() {
logi("selectDomainForTestEmergencyNumber");
if (isImsRegisteredWithVoiceCapability()) {
- onWwanNetworkTypeSelected(EUTRAN);
+ if (isImsRegisteredOverWifi()
+ || isImsRegisteredOverCrossSim()) {
+ mTransportSelectorCallback.onWlanSelected(mVoWifiOverEmergencyPdn);
+ } else {
+ onWwanNetworkTypeSelected(EUTRAN);
+ }
} else {
onWwanNetworkTypeSelected(UTRAN);
}
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallbackModeHelper.java b/src/com/android/services/telephony/domainselection/EmergencyCallbackModeHelper.java
new file mode 100644
index 0000000..e42dfe7
--- /dev/null
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallbackModeHelper.java
@@ -0,0 +1,235 @@
+/*
+ * 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.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL;
+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.PersistableBundle;
+import android.os.SystemProperties;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.CarrierConfigManager;
+import android.telephony.PreciseDataConnectionState;
+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 EmergencyCallbackModeHelper extends Handler {
+ private static final String TAG = "EmergencyCallbackModeHelper";
+ 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 int mSubId;
+ private int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ private int mState = TelephonyManager.DATA_UNKNOWN;
+
+ DataConnectionStateListener(Handler handler, TelephonyManager tm, int subId) {
+ mHandler = handler;
+ mTelephonyManager = tm;
+ mSubId = subId;
+ }
+
+ @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();
+ Log.i(TAG, "onPreciseDataConnectionStateChanged ePDN state=" + mState
+ + ", transport=" + mTransportType);
+ }
+
+ public void registerTelephonyCallback() {
+ TelephonyManager tm = mTelephonyManager.createForSubscriptionId(mSubId);
+ tm.registerTelephonyCallback(mHandler::post, this);
+ }
+
+ public void unregisterTelephonyCallback() {
+ 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);
+
+ /**
+ * Creates an instance.
+ *
+ * @param context The Context this is associated with.
+ * @param looper The Looper to run the EmergencyCallbackModeHelper.
+ */
+ public EmergencyCallbackModeHelper(@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) {
+ DataConnectionStateListener listener =
+ mDataConnectionStateListeners.get(Integer.valueOf(slotIndex));
+ if (listener == null) return false;
+
+ 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();
+ }
+
+ @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;
+ }
+
+ PersistableBundle b = mConfigManager.getConfigForSubId(subId,
+ KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL);
+
+ if (b.getBoolean(KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL)) {
+ // ECBM supported
+ DataConnectionStateListener listener =
+ mDataConnectionStateListeners.get(Integer.valueOf(slotIndex));
+
+ // Remove stale listener.
+ if (listener != null && listener.getSubId() != subId) {
+ listener.unregisterTelephonyCallback();
+ listener = null;
+ }
+
+ if (listener == null) {
+ listener = new DataConnectionStateListener(this, mTelephonyManager, subId);
+ listener.registerTelephonyCallback();
+ mDataConnectionStateListeners.put(Integer.valueOf(slotIndex), listener);
+ Log.i(TAG, "onCarrierConfigChanged register callback");
+ }
+ } else {
+ // ECBM not supported
+ DataConnectionStateListener listener =
+ mDataConnectionStateListeners.get(Integer.valueOf(slotIndex));
+ if (listener != null) {
+ listener.unregisterTelephonyCallback();
+ mDataConnectionStateListeners.remove(Integer.valueOf(slotIndex));
+ Log.i(TAG, "onCarrierConfigChanged unregister callback");
+ }
+ }
+ }
+
+ /** 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/NormalCallDomainSelector.java b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
index f85dabe..cd70793 100644
--- a/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/NormalCallDomainSelector.java
@@ -43,6 +43,7 @@
private static final String LOG_TAG = "NCDS";
private boolean mStopDomainSelection = true;
+ private boolean mDestroyed = false;
private ServiceState mServiceState;
private boolean mImsRegStateReceived;
private boolean mMmTelCapabilitiesReceived;
@@ -116,12 +117,16 @@
mImsStateTracker.removeImsStateListener(this);
mSelectionAttributes = null;
mTransportSelectorCallback = null;
+ destroy();
}
@Override
public void destroy() {
- finishSelection();
- super.destroy();
+ logd("destroy");
+ if (!mDestroyed) {
+ mDestroyed = true;
+ super.destroy();
+ }
}
/**
diff --git a/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java b/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java
index 66894f7..fca5966 100644
--- a/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java
+++ b/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionService.java
@@ -74,7 +74,8 @@
@NonNull ImsStateTracker imsStateTracker,
@NonNull DomainSelectorBase.DestroyListener listener,
@NonNull CrossSimRedialingController crossSimRedialingController,
- @NonNull CarrierConfigHelper carrierConfigHelper);
+ @NonNull CarrierConfigHelper carrierConfigHelper,
+ @NonNull EmergencyCallbackModeHelper emergencyCallbackModeHelper);
}
private static final class DefaultDomainSelectorFactory implements DomainSelectorFactory {
@@ -84,7 +85,8 @@
@NonNull ImsStateTracker imsStateTracker,
@NonNull DomainSelectorBase.DestroyListener listener,
@NonNull CrossSimRedialingController crossSimRedialingController,
- @NonNull CarrierConfigHelper carrierConfigHelper) {
+ @NonNull CarrierConfigHelper carrierConfigHelper,
+ @NonNull EmergencyCallbackModeHelper emergencyCallbackModeHelper) {
DomainSelectorBase selector = null;
logi("create-DomainSelector: slotId=" + slotId + ", subId=" + subId
@@ -96,7 +98,7 @@
if (isEmergency) {
selector = new EmergencyCallDomainSelector(context, slotId, subId, looper,
imsStateTracker, listener, crossSimRedialingController,
- carrierConfigHelper);
+ carrierConfigHelper, emergencyCallbackModeHelper);
} else {
selector = new NormalCallDomainSelector(context, slotId, subId, looper,
imsStateTracker, listener);
@@ -192,7 +194,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<>();
@@ -201,19 +203,28 @@
private Handler mServiceHandler;
private CrossSimRedialingController mCrossSimRedialingController;
private CarrierConfigHelper mCarrierConfigHelper;
+ private EmergencyCallbackModeHelper mEmergencyCallbackModeHelper;
- public TelephonyDomainSelectionService(Context context) {
- this(context, ImsStateTracker::new, new DefaultDomainSelectorFactory(), null);
+ /** Default constructor. */
+ public TelephonyDomainSelectionService() {
+ this(ImsStateTracker::new, new DefaultDomainSelectorFactory(), null, null);
}
@VisibleForTesting
- public TelephonyDomainSelectionService(Context context,
+ protected TelephonyDomainSelectionService(
@NonNull ImsStateTrackerFactory imsStateTrackerFactory,
@NonNull DomainSelectorFactory domainSelectorFactory,
- @Nullable CarrierConfigHelper carrierConfigHelper) {
- mContext = context;
+ @Nullable CarrierConfigHelper carrierConfigHelper,
+ @Nullable EmergencyCallbackModeHelper ecbmHelper) {
mImsStateTrackerFactory = imsStateTrackerFactory;
mDomainSelectorFactory = domainSelectorFactory;
+ mCarrierConfigHelper = carrierConfigHelper;
+ }
+
+ @Override
+ public void onCreate() {
+ logd("onCreate");
+ mContext = getApplicationContext();
// Create a worker thread for this domain selection service.
getExecutor();
@@ -231,9 +242,13 @@
loge("Adding OnSubscriptionChangedListener failed");
}
- mCrossSimRedialingController = new CrossSimRedialingController(context, getLooper());
- mCarrierConfigHelper = (carrierConfigHelper != null)
- ? carrierConfigHelper : new CarrierConfigHelper(context, getLooper());
+ mCrossSimRedialingController = new CrossSimRedialingController(mContext, getLooper());
+ if (mCarrierConfigHelper == null) {
+ mCarrierConfigHelper = new CarrierConfigHelper(mContext, getLooper());
+ }
+ if (mEmergencyCallbackModeHelper == null) {
+ mEmergencyCallbackModeHelper = new EmergencyCallbackModeHelper(mContext, getLooper());
+ }
logi("TelephonyDomainSelectionService created");
}
@@ -282,6 +297,11 @@
mCarrierConfigHelper = null;
}
+ if (mEmergencyCallbackModeHelper != null) {
+ mEmergencyCallbackModeHelper.destroy();
+ mEmergencyCallbackModeHelper = null;
+ }
+
if (mServiceHandler != null) {
mServiceHandler.getLooper().quit();
mServiceHandler = null;
@@ -304,7 +324,7 @@
ImsStateTracker ist = getImsStateTracker(slotId);
DomainSelectorBase selector = mDomainSelectorFactory.create(mContext, slotId, subId,
selectorType, isEmergency, getLooper(), ist, mDestroyListener,
- mCrossSimRedialingController, mCarrierConfigHelper);
+ mCrossSimRedialingController, mCarrierConfigHelper, mEmergencyCallbackModeHelper);
if (selector != null) {
// Ensures that ImsStateTracker is started before selecting the domain if not started
@@ -313,15 +333,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);
+ });
}
/**
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/src/com/android/phone/testapps/satellitetestapp/Datagram.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
index 97f676f..015ddcd 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/Datagram.java
@@ -33,7 +33,7 @@
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 +61,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 +75,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 +121,7 @@
}
}
- protected class SatelliteStateCallbackTestApp implements SatelliteStateCallback {
+ protected class SatelliteModemStateCallbackTestApp implements SatelliteModemStateCallback {
@Override
public void onSatelliteModemStateChanged(int state) {
mModemState = state;
@@ -166,10 +166,10 @@
}
}
- 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(true, true, Runnable::run, error::offer);
TextView showErrorStatusTextView = findViewById(R.id.showErrorStatus);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -186,7 +186,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 +202,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 +220,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 +228,7 @@
if (SatelliteTestApp.getTestSatelliteService() != null) {
SatelliteTestApp.getTestSatelliteService().sendOnPendingDatagrams();
}
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.requestEnabled(true, true, Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -246,61 +246,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 +315,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/MultipleSendReceive.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java
index 3c0b2fd..0e5ab4f 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/MultipleSendReceive.java
@@ -66,20 +66,20 @@
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(true, true, 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 +100,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 +127,27 @@
private void multipleSendReceiveSatelliteDatagramApp(View view) {
mSatelliteManager.setDeviceAlignedWithSatellite(true);
LinkedBlockingQueue<Integer> resultListener = new LinkedBlockingQueue<>(1);
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, resultListener::offer);
+ mSatelliteManager.requestEnabled(true, true, 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/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..2d01aec 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteControl.java
@@ -52,16 +52,15 @@
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.Back).setOnClickListener(new OnClickListener() {
@@ -74,7 +73,7 @@
private void enableSatelliteApp(View view) {
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
- mSatelliteManager.requestSatelliteEnabled(true, true, Runnable::run, error::offer);
+ mSatelliteManager.requestEnabled(true, true, Runnable::run, error::offer);
TextView textView = findViewById(R.id.text_id);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -93,7 +92,7 @@
private void disableSatelliteApp(View view) {
LinkedBlockingQueue<Integer> error = new LinkedBlockingQueue<>(1);
- mSatelliteManager.requestSatelliteEnabled(false, true, Runnable::run, error::offer);
+ mSatelliteManager.requestEnabled(false, true, Runnable::run, error::offer);
TextView textView = findViewById(R.id.text_id);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
@@ -110,7 +109,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 +119,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 +130,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 +165,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 +175,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 +186,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 +202,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 +210,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 +243,7 @@
+ SatelliteErrorUtils.mapError(errorCode.get()));
}
};
- mSatelliteManager.requestIsSatelliteCommunicationAllowedForCurrentLocation(Runnable::run,
+ mSatelliteManager.requestIsCommunicationAllowedForCurrentLocation(Runnable::run,
receiver);
}
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..b5e82b1 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SendReceive.java
@@ -124,7 +124,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 +139,7 @@
+ mEnterMessage.getText().toString());
}
} catch (InterruptedException e) {
- messageStatusTextView.setText("sendSatelliteDatagram exception caught = " + e);
+ messageStatusTextView.setText("sendDatagram exception caught = " + e);
}
}
@@ -148,16 +148,16 @@
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(true, true, Runnable::run, resultListener::offer);
try {
Integer value = resultListener.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -173,7 +173,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 +185,7 @@
mMessageStatusTextView.setText("Successfully polled pending messages");
}
} catch (InterruptedException e) {
- mMessageStatusTextView.setText("pollPendingSatelliteDatagrams exception caught = " + e);
+ mMessageStatusTextView.setText("pollPendingDatagrams exception caught = " + e);
}
}
@@ -195,7 +195,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 +233,12 @@
+ 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(true, true, Runnable::run, error::offer);
try {
Integer value = error.poll(TIMEOUT, TimeUnit.MILLISECONDS);
if (value == null) {
@@ -254,7 +254,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..9bea30c 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteService.java
@@ -330,14 +330,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 +347,7 @@
if (mLocalListener != null) {
runWithExecutor(() -> mLocalListener.onSendSatelliteDatagram(datagram, isEmergency));
} else {
- loge("sendSatelliteDatagram: mLocalListener is null");
+ loge("sendDatagram: mLocalListener is null");
}
}
@@ -365,7 +365,7 @@
@Override
public void requestIsSatelliteCommunicationAllowedForCurrentLocation(
@NonNull IIntegerConsumer errorCallback, @NonNull IBooleanConsumer callback) {
- logd("requestIsSatelliteCommunicationAllowedForCurrentLocation: mErrorCode=" + mErrorCode);
+ logd("requestIsCommunicationAllowedForCurrentLocation: mErrorCode=" + mErrorCode);
if (mErrorCode != SatelliteResult.SATELLITE_RESULT_SUCCESS) {
runWithExecutor(() -> errorCallback.accept(mErrorCode));
return;
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..e4c2005 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;
@@ -41,7 +40,6 @@
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
-
/**
* Activity related to SatelliteControl APIs for satellite.
*/
@@ -74,9 +72,9 @@
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.Back).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
@@ -114,8 +112,8 @@
mNtnSignalStrengthCallback);
}
if (mSatelliteCapabilitiesCallback != null) {
- Log.d(TAG, "unregisterForSatelliteCapabilitiesChanged()");
- mSatelliteManagerWrapper.unregisterForSatelliteCapabilitiesChanged(
+ Log.d(TAG, "unregisterForCapabilitiesChanged()");
+ mSatelliteManagerWrapper.unregisterForCapabilitiesChanged(
mSatelliteCapabilitiesCallback);
}
}
@@ -148,7 +146,7 @@
try {
mSatelliteManagerWrapper.requestNtnSignalStrength(mExecutor, receiver);
- } catch (SecurityException | IllegalStateException ex) {
+ } catch (SecurityException ex) {
String errorMessage = "requestNtnSignalStrength: " + ex.getMessage();
Log.d(TAG, errorMessage);
addLogMessage(errorMessage);
@@ -167,18 +165,10 @@
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();
- }
+ String errorMessage = "registerForNtnSignalStrengthChanged: " + ex.getMessage();
Log.d(TAG, errorMessage);
addLogMessage(errorMessage);
mNtnSignalStrengthCallback = null;
-
}
}
@@ -222,9 +212,9 @@
}
}
- private void registerForSatelliteCapabilitiesChanged(View view) {
- addLogMessage("registerForSatelliteCapabilitiesChanged");
- Log.d(TAG, "registerForSatelliteCapabilitiesChanged()");
+ private void registerForCapabilitiesChanged(View view) {
+ addLogMessage("registerForCapabilitiesChanged");
+ Log.d(TAG, "registerForCapabilitiesChanged()");
if (mSatelliteCapabilitiesCallback == null) {
mSatelliteCapabilitiesCallback =
SatelliteCapabilities -> {
@@ -235,7 +225,7 @@
};
}
- int result = mSatelliteManagerWrapper.registerForSatelliteCapabilitiesChanged(mExecutor,
+ int result = mSatelliteManagerWrapper.registerForCapabilitiesChanged(mExecutor,
mSatelliteCapabilitiesCallback);
if (result != SatelliteManagerWrapper.SATELLITE_RESULT_SUCCESS) {
String onError = translateResultCodeToString(result);
@@ -245,11 +235,11 @@
}
}
- private void unregisterForSatelliteCapabilitiesChanged(View view) {
- addLogMessage("unregisterForSatelliteCapabilitiesChanged");
- Log.d(TAG, "unregisterForSatelliteCapabilitiesChanged()");
+ private void unregisterForCapabilitiesChanged(View view) {
+ addLogMessage("unregisterForCapabilitiesChanged");
+ Log.d(TAG, "unregisterForCapabilitiesChanged()");
if (mSatelliteCapabilitiesCallback != null) {
- mSatelliteManagerWrapper.unregisterForSatelliteCapabilitiesChanged(
+ mSatelliteManagerWrapper.unregisterForCapabilitiesChanged(
mSatelliteCapabilitiesCallback);
mSatelliteCapabilitiesCallback = null;
addLogMessage("mSatelliteCapabilitiesCallback was unregistered");
@@ -317,6 +307,8 @@
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;
}
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/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..2ca04b9 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,9 +95,10 @@
@Test
public void testPersistForTelecomDumpsys() throws IOException, InterruptedException {
+ TelephonyManager.EmergencyCallDiagnosticParams.Builder callDiagnosticBuilder =
+ new TelephonyManager.EmergencyCallDiagnosticParams.Builder();
TelephonyManager.EmergencyCallDiagnosticParams dp =
- new TelephonyManager.EmergencyCallDiagnosticParams();
- dp.setTelecomDumpSysCollection(true);
+ callDiagnosticBuilder.setTelecomDumpSysCollectionEnabled(true).build();
mDiagnosticDataCollector.persistEmergencyDianosticData(mConfig, dp, "test_tag_telecom");
verifyCmdAndDropboxTag(TELECOM_DUMPSYS_COMMAND, "test_tag_telecom", false);
@@ -104,9 +106,10 @@
@Test
public void testPersistForTelephonyDumpsys() throws IOException, InterruptedException {
+ TelephonyManager.EmergencyCallDiagnosticParams.Builder callDiagnosticBuilder =
+ new TelephonyManager.EmergencyCallDiagnosticParams.Builder();
TelephonyManager.EmergencyCallDiagnosticParams dp =
- new TelephonyManager.EmergencyCallDiagnosticParams();
- dp.setTelephonyDumpSysCollection(true);
+ callDiagnosticBuilder.setTelephonyDumpSysCollectionEnabled(true).build();
mDiagnosticDataCollector.persistEmergencyDianosticData(mConfig, dp, "test_tag_telephony");
verifyCmdAndDropboxTag(TELEPHONY_DUMPSYS_COMMAND, "test_tag_telephony", false);
@@ -114,9 +117,11 @@
@Test
public void testPersistForLogcat() throws IOException, InterruptedException {
+ TelephonyManager.EmergencyCallDiagnosticParams.Builder callDiagnosticBuilder =
+ new TelephonyManager.EmergencyCallDiagnosticParams.Builder();
TelephonyManager.EmergencyCallDiagnosticParams dp =
- new TelephonyManager.EmergencyCallDiagnosticParams();
- dp.setLogcatCollection(true, System.currentTimeMillis());
+ callDiagnosticBuilder.setLogcatCollectionStartTimeMillis(
+ SystemClock.elapsedRealtime()).build();
mDiagnosticDataCollector.persistEmergencyDianosticData(mConfig, dp, "test_tag_logcat");
verifyCmdAndDropboxTag(LOGCAT_BINARY, "test_tag_logcat", true);
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
index 150703d..2d338f2 100644
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -20,6 +20,7 @@
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.Mockito.doNothing;
@@ -31,8 +32,10 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+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 +52,17 @@
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.Locale;
/**
@@ -62,9 +70,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,7 +85,8 @@
Phone mPhone;
@Mock
FeatureFlags mFeatureFlags;
-
+ @Mock
+ PackageManager mPackageManager;
@Mock
private SubscriptionManagerService mSubscriptionManagerService;
@@ -82,6 +96,8 @@
@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 +108,15 @@
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());
}
@Test
@@ -269,6 +293,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.
*/
@@ -359,4 +485,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/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..c44b347
--- /dev/null
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
@@ -0,0 +1,658 @@
+/*
+ * 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_ERROR;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.res.Resources;
+import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.telecom.TelecomManager;
+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.SatelliteController;
+
+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.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 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;
+
+ 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<ResultReceiver> mResultReceiverFromSatelliteControllerCaptor;
+ 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);
+ }
+ }
+ };
+
+ private boolean mQueriedSatelliteAllowed2 = false;
+ private int mQueriedSatelliteAllowedResultCode2 = SATELLITE_RESULT_SUCCESS;
+ private Semaphore mSatelliteAllowedSemaphore2 = new Semaphore(0);
+ private ResultReceiver mSatelliteAllowedReceiver2 = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mQueriedSatelliteAllowedResultCode2 = resultCode;
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
+ mQueriedSatelliteAllowed2 = resultData.getBoolean(
+ KEY_SATELLITE_COMMUNICATION_ALLOWED);
+ } else {
+ logd("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist.");
+ mQueriedSatelliteAllowed2 = false;
+ }
+ } else {
+ logd("mSatelliteAllowedReceiver2: resultCode=" + resultCode);
+ mQueriedSatelliteAllowed2 = false;
+ }
+ try {
+ mSatelliteAllowedSemaphore2.release();
+ } catch (Exception ex) {
+ fail("mSatelliteAllowedReceiver2: 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(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);
+ doNothing().when(mMockSatelliteController)
+ .requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), any(ResultReceiver.class));
+
+ 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);
+
+ 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, but SatelliteController returns error for the query
+ when(mMockFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+
+ clearInvocations(mMockSatelliteController);
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver2);
+ mTestableLooper.processAllMessages();
+ verify(mMockSatelliteController, never())
+ .requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), any(ResultReceiver.class));
+
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_ERROR, null);
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore2, 1));
+ assertEquals(SATELLITE_RESULT_ERROR, mQueriedSatelliteAllowedResultCode);
+ assertEquals(SATELLITE_RESULT_ERROR, mQueriedSatelliteAllowedResultCode2);
+ assertFalse(mQueriedSatelliteAllowed);
+ assertFalse(mQueriedSatelliteAllowed2);
+
+ // SatelliteController returns success result but the result bundle does not have
+ // KEY_SATELLITE_COMMUNICATION_ALLOWED
+ clearAllInvocations();
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, null);
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertFalse(mQueriedSatelliteAllowed);
+
+ // SatelliteController returns disallowed result
+ clearAllInvocations();
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, false);
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertFalse(mQueriedSatelliteAllowed);
+
+ // SatelliteController returns allowed result. Network country codes are available, but one
+ // country code is not in the allowed list
+ clearAllInvocations();
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(listOf("US", "IN"));
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, true);
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertFalse(mQueriedSatelliteAllowed);
+
+ // SatelliteController returns allowed result. Network country codes are available, and all
+ // country codes are in the allowed list
+ clearAllInvocations();
+ when(mMockCountryDetector.getCurrentNetworkCountryIso()).thenReturn(listOf("US", "CA"));
+ mSatelliteAccessControllerUT.requestIsCommunicationAllowedForCurrentLocation(
+ SUB_ID, mSatelliteAllowedReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, true);
+ assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(
+ mSatelliteAllowedSemaphore, 1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
+ assertTrue(mQueriedSatelliteAllowed);
+
+ // SatelliteController returns allowed result. 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();
+ verify(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, true);
+ 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);
+
+ // SatelliteController returns allowed result. 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();
+ verify(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, true);
+ 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();
+ verify(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, true);
+ 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);
+
+ // SatelliteController returns allowed result. 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(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, true);
+ 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);
+
+ // SatelliteController returns allowed result. 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(mMockSatelliteController).requestIsSatelliteCommunicationAllowedForCurrentLocation(
+ anyInt(), mResultReceiverFromSatelliteControllerCaptor.capture());
+ sendSatelliteAllowResultFromSatelliteController(SATELLITE_RESULT_SUCCESS, true);
+ 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);
+ }
+
+ 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 sendSatelliteAllowResultFromSatelliteController(
+ int resultCode, Boolean satelliteAllowed) {
+ Bundle bundle = null;
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ bundle = new Bundle();
+ if (satelliteAllowed != null) {
+ bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, satelliteAllowed);
+ }
+ }
+ mResultReceiverFromSatelliteControllerCaptor.getValue().send(resultCode, bundle);
+ mTestableLooper.processAllMessages();
+ }
+
+ private void sendLocationRequestResult(Location location) {
+ mLocationRequestConsumerCaptor.getValue().accept(location);
+ mTestableLooper.processAllMessages();
+ }
+
+ @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..f096e0d
--- /dev/null
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementApiTest.java
@@ -0,0 +1,154 @@
+/*
+ * 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 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 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");
+ @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);
+ }
+
+ @Test
+ public void testCheckEntitlementStatus() throws Exception {
+ mCarrierConfigBundle.putString(
+ CarrierConfigManager.ImsServiceEntitlement.KEY_ENTITLEMENT_SERVER_URL_STRING,
+ TEST_URL);
+ Field fieldServiceEntitlement = SatelliteEntitlementApi.class.getDeclaredField(
+ "mServiceEntitlement");
+ fieldServiceEntitlement.setAccessible(true);
+ fieldServiceEntitlement.set(mSatelliteEntitlementAPI, mServiceEntitlement);
+
+ // 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);
+ }
+
+ 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..18a0284
--- /dev/null
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
@@ -0,0 +1,378 @@
+/*
+ * 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");
+ @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(), 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(), 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(), 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(), any());
+
+ // Verify start the query when isQueryAvailable return true
+ setLastQueryTime(0L);
+ doReturn(mSatelliteEntitlementResult).when(
+ mSatelliteEntitlementApi).checkEntitlementStatus();
+ setSatelliteEntitlementResult(SATELLITE_ENTITLEMENT_STATUS_ENABLED, PLMN_ALLOWED_LIST);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(anyInt(),
+ anyBoolean(), 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(), 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
+ // and empty PLMNAllowed
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID),
+ eq(false), 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);
+ mSatelliteEntitlementController.handleCmdStartQueryEntitlement();
+
+ verify(mSatelliteEntitlementApi).checkEntitlementStatus();
+ // Verify call the updateSatelliteEntitlementStatus with satellite service is enable and
+ // availablePLMNAllowedList
+ verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
+ eq(PLMN_ALLOWED_LIST), any());
+
+ // Change subId and verify call the updateSatelliteEntitlementStatus with satellite
+ // service is enable and availablePLMNAllowedList
+ 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), 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);
+
+ 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), 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);
+ 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), 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) {
+ doReturn(entitlementStatus).when(mSatelliteEntitlementResult).getEntitlementStatus();
+ doReturn(plmnAllowedList).when(mSatelliteEntitlementResult).getAllowedPLMNList();
+ }
+
+ 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..45e2a71
--- /dev/null
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementResponseTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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 + "\":{}}";
+
+ @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());
+ 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);
+ 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);
+ }
+
+ 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\"}]" : "";
+ }
+}
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index 16a5cdb..e5f7fd3 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;
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index f0a5220..129b6f4 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -319,6 +319,7 @@
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
@@ -1816,7 +1817,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 +1830,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 +1843,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 +1855,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 +1869,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 +1887,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
@@ -2385,132 +2402,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 +2494,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 +2529,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 +2566,11 @@
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
@@ -3349,6 +3281,52 @@
}
@Test
+ public void testIsAvailableForEmergencyCallsUsingNonTerrestrialNetwork_enableFlag() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_CARRIER_ENABLED_SATELLITE_FLAG);
+
+ Phone mockPhone = Mockito.mock(Phone.class);
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setIsNonTerrestrialNetwork(true)
+ .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
+ .build();
+ ServiceState ss = new ServiceState();
+ ss.addNetworkRegistrationInfo(nri);
+ 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);
+
+ Phone mockPhone = Mockito.mock(Phone.class);
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setIsNonTerrestrialNetwork(true)
+ .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_VOICE))
+ .build();
+ ServiceState ss = new ServiceState();
+ ss.addNetworkRegistrationInfo(nri);
+ 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);
@@ -3503,6 +3481,50 @@
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 {
diff --git a/tests/src/com/android/services/telephony/domainselection/CarrierConfigHelperTest.java b/tests/src/com/android/services/telephony/domainselection/CarrierConfigHelperTest.java
index 5d4fe17..8f51dab 100644
--- a/tests/src/com/android/services/telephony/domainselection/CarrierConfigHelperTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/CarrierConfigHelperTest.java
@@ -32,7 +32,6 @@
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;
@@ -68,11 +67,11 @@
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 Context mContext;
private HandlerThread mHandlerThread;
private TestableLooper mLooper;
private CarrierConfigHelper mCarrierConfigHelper;
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
index eab40f9..6217a92 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;
@@ -53,6 +55,7 @@
import static android.telephony.NetworkRegistrationInfo.REGISTRATION_STATE_HOME;
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 com.android.services.telephony.domainselection.EmergencyCallDomainSelector.MSG_MAX_CELLULAR_TIMEOUT;
import static com.android.services.telephony.domainselection.EmergencyCallDomainSelector.MSG_NETWORK_SCAN_TIMEOUT;
@@ -69,6 +72,7 @@
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;
@@ -100,6 +104,7 @@
import android.telephony.TelephonyManager;
import android.telephony.TransportSelectorCallback;
import android.telephony.WwanSelectorCallback;
+import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.ProvisioningManager;
@@ -119,7 +124,10 @@
import org.mockito.stubbing.Answer;
import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.function.Consumer;
/**
@@ -130,6 +138,7 @@
private static final int SLOT_0 = 0;
private static final int SLOT_0_SUB_ID = 1;
+ private static final String TEST_EMERGENCY_NUMBER = "911";
@Mock private CarrierConfigManager mCarrierConfigManager;
@Mock private ConnectivityManager mConnectivityManager;
@@ -142,6 +151,7 @@
@Mock private ProvisioningManager mProvisioningManager;
@Mock private CrossSimRedialingController mCsrdCtrl;
@Mock private CarrierConfigHelper mCarrierConfigHelper;
+ @Mock private EmergencyCallbackModeHelper mEcbmHelper;
@Mock private Resources mResources;
private Context mContext;
@@ -292,6 +302,26 @@
}
@Test
+ public void testDestroyed() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ mDomainSelector.destroy();
+ mDomainSelector.handleMessage(mDomainSelector.obtainMessage(Integer.MAX_VALUE));
+ unsolBarringInfoChanged(false);
+
+ verify(mTransportSelectorCallback, never()).onWwanSelected(any());
+ }
+
+ @Test
public void testNoRedundantDomainSelectionFromInitialState() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
@@ -479,6 +509,39 @@
}
@Test
+ public void testDefaultCombinedImsRegisteredSelectPsThenNotExtendedServiceRequestFails()
+ throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = getSelectionAttributes(SLOT_0, SLOT_0_SUB_ID, regResult);
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsService();
+
+ verifyPsDialed();
+
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyCsDialed();
+
+ SelectionAttributes.Builder builder =
+ new SelectionAttributes.Builder(SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setEmergency(true)
+ .setEmergencyRegResult(regResult);
+ attr = builder.build();
+ mDomainSelector.reselectDomain(attr);
+ processAllMessages();
+
+ verifyScanPsPreferred();
+ }
+
+ @Test
public void testDefaultCombinedImsNotRegisteredSelectCs() throws Exception {
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(false);
@@ -496,6 +559,56 @@
}
@Test
+ public void testAirplaneDefaultCombinedImsNotRegisteredSelectPs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = new SelectionAttributes.Builder(
+ SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setNumber(TEST_EMERGENCY_NUMBER)
+ .setEmergency(true)
+ .setEmergencyRegResult(regResult)
+ .setExitedFromAirplaneMode(true)
+ .build();
+ mDomainSelector.selectDomain(attr, mTransportSelectorCallback);
+ processAllMessages();
+
+ bindImsServiceUnregistered();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testAirplaneRequiresRegCombinedImsNotRegisteredSelectPs() throws Exception {
+ PersistableBundle bundle = getDefaultPersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_REQUIRES_IMS_REGISTRATION_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ NetworkRegistrationInfo.DOMAIN_CS | NetworkRegistrationInfo.DOMAIN_PS,
+ true, true, 0, 0, "", "");
+ SelectionAttributes attr = new SelectionAttributes.Builder(
+ SLOT_0, SLOT_0_SUB_ID, SELECTOR_TYPE_CALLING)
+ .setNumber(TEST_EMERGENCY_NUMBER)
+ .setEmergency(true)
+ .setEmergencyRegResult(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,
@@ -1117,6 +1230,7 @@
bundle.putBoolean(KEY_EMERGENCY_CALL_OVER_EMERGENCY_PDN_BOOL, true);
when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(bundle);
+ mResultConsumer = null;
createSelector(SLOT_0_SUB_ID);
unsolBarringInfoChanged(true);
@@ -1141,6 +1255,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
@@ -1335,6 +1457,36 @@
}
@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());
+
+ 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();
+
+ 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);
@@ -1371,6 +1523,30 @@
}
@Test
+ public void testEutranWithPsDomainOnly() throws Exception {
+ setupForHandleScanResult();
+
+ EmergencyRegResult regResult = getEmergencyRegResult(EUTRAN, REGISTRATION_STATE_HOME,
+ DOMAIN_PS, false, false, 0, 0, "", "");
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testUtran() throws Exception {
+ setupForHandleScanResult();
+
+ EmergencyRegResult regResult = getEmergencyRegResult(UTRAN, REGISTRATION_STATE_HOME,
+ DOMAIN_CS, false, false, 0, 0, "", "");
+ mResultConsumer.accept(regResult);
+ processAllMessages();
+
+ verifyCsDialed();
+ }
+
+ @Test
public void testFullService() throws Exception {
PersistableBundle bundle = getDefaultPersistableBundle();
bundle.putInt(KEY_EMERGENCY_NETWORK_SCAN_TYPE_INT, SCAN_TYPE_FULL_SERVICE);
@@ -1929,6 +2105,9 @@
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();
@@ -2108,6 +2287,226 @@
assertEquals(GERAN, (int) mAccessNetwork.get(3));
}
+ @Test
+ public void testDefaultLimitedServiceEutran() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult 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();
+ }
+
+ @Test
+ public void testDefaultLimitedServiceNgran() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult 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 {
+ EmergencyNumber num = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "us", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE, new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
+
+ Map<Integer, List<EmergencyNumber>> lists = new HashMap<>();
+ List<EmergencyNumber> list = new ArrayList<>();
+ list.add(num);
+ lists.put(SLOT_0_SUB_ID, list);
+
+ doReturn(lists).when(mTelephonyManager).getEmergencyNumberList();
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult 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();
+
+ verifyCsDialed();
+ }
+
+ @Test
+ public void testTestEmergencyNumberOverPs() throws Exception {
+ EmergencyNumber num = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "us", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE, new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
+
+ Map<Integer, List<EmergencyNumber>> lists = new HashMap<>();
+ List<EmergencyNumber> list = new ArrayList<>();
+ list.add(num);
+ lists.put(SLOT_0_SUB_ID, list);
+
+ doReturn(lists).when(mTelephonyManager).getEmergencyNumberList();
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult 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();
+
+ bindImsService();
+
+ verifyPsDialed();
+ }
+
+ @Test
+ public void testTestEmergencyNumberOverWifi() throws Exception {
+ EmergencyNumber num = new EmergencyNumber(TEST_EMERGENCY_NUMBER, "us", "",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE, new ArrayList<String>(),
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
+
+ Map<Integer, List<EmergencyNumber>> lists = new HashMap<>();
+ List<EmergencyNumber> list = new ArrayList<>();
+ list.add(num);
+ lists.put(SLOT_0_SUB_ID, list);
+
+ doReturn(lists).when(mTelephonyManager).getEmergencyNumberList();
+
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult 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();
+
+ bindImsService(true);
+ processAllMessages();
+
+ verify(mTransportSelectorCallback, times(1)).onWlanSelected(anyBoolean());
+ }
+
+ @Test
+ public void testLimitedServiceDialCs() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ EmergencyRegResult 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(mEcbmHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WWAN).when(mEcbmHelper).getTransportType(anyInt());
+ doReturn(DATA_CONNECTED).when(mEcbmHelper).getDataConnectionState(anyInt());
+
+ 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(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback).onWwanSelected(any());
+ }
+
+ @Test
+ public void testWhileInEcbmOnWlanConnected() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ doReturn(true).when(mEcbmHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WLAN).when(mEcbmHelper).getTransportType(anyInt());
+ doReturn(DATA_CONNECTED).when(mEcbmHelper).getDataConnectionState(anyInt());
+
+ 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(mTransportSelectorCallback).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback, never()).onWwanSelected(any());
+ }
+
+ @Test
+ public void testWhileInEcbmOnWlanNotConnected() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ doReturn(true).when(mEcbmHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WLAN).when(mEcbmHelper).getTransportType(anyInt());
+
+ 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(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback).onWwanSelected(any());
+ }
+
+ @Test
+ public void testNotInEcbmOnWlanConnected() throws Exception {
+ createSelector(SLOT_0_SUB_ID);
+ unsolBarringInfoChanged(false);
+
+ doReturn(false).when(mEcbmHelper).isInEmergencyCallbackMode(anyInt());
+ doReturn(TRANSPORT_TYPE_WLAN).when(mEcbmHelper).getTransportType(anyInt());
+ doReturn(DATA_CONNECTED).when(mEcbmHelper).getDataConnectionState(anyInt());
+
+ 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(mTransportSelectorCallback, never()).onWlanSelected(anyBoolean());
+ verify(mTransportSelectorCallback).onWwanSelected(any());
+ }
+
private void setupForScanListTest(PersistableBundle bundle) throws Exception {
setupForScanListTest(bundle, false);
}
@@ -2181,7 +2580,7 @@
private void createSelector(int subId) throws Exception {
mDomainSelector = new EmergencyCallDomainSelector(
mContext, SLOT_0, subId, mHandlerThread.getLooper(),
- mImsStateTracker, mDestroyListener, mCsrdCtrl, mCarrierConfigHelper);
+ mImsStateTracker, mDestroyListener, mCsrdCtrl, mCarrierConfigHelper, mEcbmHelper);
mDomainSelector.clearResourceConfiguration();
replaceInstance(DomainSelectorBase.class,
"mWwanSelectorCallback", mDomainSelector, mWwanSelectorCallback);
@@ -2354,6 +2753,7 @@
EmergencyRegResult regResult) {
SelectionAttributes.Builder builder =
new SelectionAttributes.Builder(slotId, subId, SELECTOR_TYPE_CALLING)
+ .setNumber(TEST_EMERGENCY_NUMBER)
.setEmergency(true)
.setEmergencyRegResult(regResult);
return builder.build();
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallbackModeHelperTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallbackModeHelperTest.java
new file mode 100644
index 0000000..9a4e0d8
--- /dev/null
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallbackModeHelperTest.java
@@ -0,0 +1,305 @@
+/*
+ * 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.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL;
+
+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.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+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.MockitoAnnotations;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Unit tests for EmergencyCallbackModeHelper
+ */
+public class EmergencyCallbackModeHelperTest {
+ private static final String TAG = "EmergencyCallbackModeHelperTest";
+
+ 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;
+
+ private Context mContext;
+ private HandlerThread mHandlerThread;
+ private TestableLooper mLooper;
+ private EmergencyCallbackModeHelper mEcbmHelper;
+ 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("EmergencyCallbackModeHelperTest");
+ 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(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
+
+ mEcbmHelper = new EmergencyCallbackModeHelper(mContext, mHandlerThread.getLooper());
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if (mEcbmHelper != null) {
+ mEcbmHelper.destroy();
+ mEcbmHelper = 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 testEmergencyCallbackModeNotSupported() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
+ callbackCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ // ECBM not supported
+ PersistableBundle b = getPersistableBundle(false);
+ doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+
+ // No TelephonyCallback registered
+ verify(mTelephonyManager, never()).registerTelephonyCallback(any(), any());
+ }
+
+ @Test
+ public void testEmergencyCallbackModeSupported() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
+ callbackCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ // ECBM supported
+ PersistableBundle b = getPersistableBundle(true);
+ doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+
+ verify(mTelephonyManager).createForSubscriptionId(eq(SUB_1));
+
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+
+ // TelephonyCallback registered
+ verify(mTelephonyManager).registerTelephonyCallback(any(),
+ telephonyCallbackCaptor.capture());
+
+ assertNotNull(telephonyCallbackCaptor.getValue());
+ }
+
+ @Test
+ public void testEmergencyCallbackModeChanged() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
+ callbackCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ // ECBM supported
+ PersistableBundle b = getPersistableBundle(true);
+ doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+
+ verify(mTelephonyManager).createForSubscriptionId(eq(SUB_1));
+
+ ArgumentCaptor<TelephonyCallback> telephonyCallbackCaptor =
+ ArgumentCaptor.forClass(TelephonyCallback.class);
+
+ // TelephonyCallback registered
+ verify(mTelephonyManager).registerTelephonyCallback(any(),
+ telephonyCallbackCaptor.capture());
+
+ TelephonyCallback telephonyCallback = telephonyCallbackCaptor.getValue();
+
+ assertNotNull(telephonyCallback);
+
+ // Carrier config changes, ECBM not supported
+ b = getPersistableBundle(false);
+ doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+
+ // TelephonyCallback unregistered
+ verify(mTelephonyManager).unregisterTelephonyCallback(eq(telephonyCallback));
+ }
+
+ @Test
+ public void testEmergencyCallbackModeEnter() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
+ callbackCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ // ECBM supported
+ PersistableBundle b = getPersistableBundle(true);
+ doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+ callback.onCarrierConfigChanged(SLOT_1, SUB_2, 0, 0);
+
+ // Enter ECBM on slot 1
+ mContext.sendStickyBroadcast(getIntent(true, SLOT_1));
+
+ assertFalse(mEcbmHelper.isInEmergencyCallbackMode(SLOT_0));
+ assertTrue(mEcbmHelper.isInEmergencyCallbackMode(SLOT_1));
+ }
+
+ @Test
+ public void testEmergencyCallbackModeExit() throws Exception {
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> callbackCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+
+ verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
+ callbackCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener callback = callbackCaptor.getValue();
+
+ assertNotNull(callback);
+
+ // ECBM supported
+ PersistableBundle b = getPersistableBundle(true);
+ doReturn(b).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyString());
+ callback.onCarrierConfigChanged(SLOT_0, SUB_1, 0, 0);
+
+ // Exit ECBM
+ mContext.sendStickyBroadcast(getIntent(false, SLOT_0));
+
+ assertFalse(mEcbmHelper.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 PersistableBundle getPersistableBundle(boolean supported) {
+ PersistableBundle bundle = new PersistableBundle();
+ bundle.putBoolean(KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL, supported);
+ return bundle;
+ }
+
+ private static void logd(String str) {
+ Log.d(TAG, str);
+ }
+}
diff --git a/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java b/tests/src/com/android/services/telephony/domainselection/TelephonyDomainSelectionServiceTest.java
index f4d2732..d9c737e 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;
@@ -81,7 +82,8 @@
@NonNull Looper looper, @NonNull ImsStateTracker imsStateTracker,
@NonNull DomainSelectorBase.DestroyListener listener,
@NonNull CrossSimRedialingController crossSimRedialingController,
- @NonNull CarrierConfigHelper carrierConfigHelper) {
+ @NonNull CarrierConfigHelper carrierConfigHelper,
+ @NonNull EmergencyCallbackModeHelper ecbmHelper) {
switch (selectorType) {
case DomainSelectionService.SELECTOR_TYPE_CALLING: // fallthrough
case DomainSelectionService.SELECTOR_TYPE_SMS: // fallthrough
@@ -97,6 +99,26 @@
}
}
};
+ private static class TestTelephonyDomainSelectionService
+ extends TelephonyDomainSelectionService {
+ private final Context mContext;
+
+ TestTelephonyDomainSelectionService(Context context,
+ @NonNull ImsStateTrackerFactory imsStateTrackerFactory,
+ @NonNull DomainSelectorFactory domainSelectorFactory,
+ @Nullable CarrierConfigHelper carrierConfigHelper,
+ @Nullable EmergencyCallbackModeHelper ecbmHelper) {
+ super(imsStateTrackerFactory, domainSelectorFactory, carrierConfigHelper, ecbmHelper);
+ 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;
@@ -111,6 +133,7 @@
@Mock private TransportSelectorCallback mSelectorCallback2;
@Mock private ImsStateTracker mImsStateTracker;
@Mock private CarrierConfigHelper mCarrierConfigHelper;
+ @Mock private EmergencyCallbackModeHelper mEcbmHelper;
private final ServiceState mServiceState = new ServiceState();
private final BarringInfo mBarringInfo = new BarringInfo();
@@ -131,8 +154,9 @@
}
mContext = new TestContext();
- mDomainSelectionService = new TelephonyDomainSelectionService(mContext,
- mImsStateTrackerFactory, mDomainSelectorFactory, mCarrierConfigHelper);
+ mDomainSelectionService = new TestTelephonyDomainSelectionService(mContext,
+ mImsStateTrackerFactory, mDomainSelectorFactory, mCarrierConfigHelper, mEcbmHelper);
+ mDomainSelectionService.onCreate();
mServiceHandler = new Handler(mDomainSelectionService.getLooper());
mTestableLooper = new TestableLooper(mDomainSelectionService.getLooper());
@@ -184,9 +208,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 +225,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 +242,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 +258,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 +275,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 +288,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 +321,7 @@
.setCallId(CALL_ID)
.setEmergency(true)
.build();
- mServiceHandler.post(() -> {
- mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
- });
+ mDomainSelectionService.onDomainSelection(attr1, mSelectorCallback1);
processAllMessages();
mDomainSelectionService.onDestroy();
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;
+ }
+}