Merge "Fix NPE at RadioInfo" into main
diff --git a/assets/CarrierRestrictionOperatorDetails.json b/assets/CarrierRestrictionOperatorDetails.json
index 4f650a0..b3c8976 100644
--- a/assets/CarrierRestrictionOperatorDetails.json
+++ b/assets/CarrierRestrictionOperatorDetails.json
@@ -7,5 +7,8 @@
"com.comcast.mobile.mxs":{"carrierIds": [2032,2532,2556],"callerSHA256Ids":["914C26403B57D2D482359FC235CC825AD00D52B0121C18EF2B2B9D4DDA4B8996"]},
"com.xfinity.digitalhome": {"carrierIds": [2032,2532,2556],"callerSHA256Ids":["31b4c17315c2269040d535f7b6a79cf4d11517c664d9de8f1ddf4f8a785aad47"]},
"com.xfinity.digitalhome.debug":{"carrierIds": [2032,2532,2556],"callerSHA256Ids":["c9133e8168f97573c8c567f46777dff74ade0c015ecf2c5e91be3e4e76ddcae2"]},
- "com.xfinity.dh.xm.app": {"carrierIds": [2032,2532,2556],"callerSHA256Ids":["c9133e8168f97573c8c567f46777dff74ade0c015ecf2c5e91be3e4e76ddcae2"]}
+ "com.xfinity.dh.xm.app": {"carrierIds": [2032,2532,2556],"callerSHA256Ids":["c9133e8168f97573c8c567f46777dff74ade0c015ecf2c5e91be3e4e76ddcae2"]},
+ "com.tmobile.tmte": {"carrierIds": [1],"callerSHA256Ids":["3D:1A:4B:EF:6E:E7:AF:7D:34:D1:20:E7:B1:AA:C0:DD:24:55:85:DE:62:37:CF:10:0F:68:33:3A:FA:CF:F5:62"]},
+ "com.tmobile.tuesdays": {"carrierIds": [1],"callerSHA256Ids":["3D:1A:4B:EF:6E:E7:AF:7D:34:D1:20:E7:B1:AA:C0:DD:24:55:85:DE:62:37:CF:10:0F:68:33:3A:FA:CF:F5:62","92:B5:F8:11:7F:BD:9B:D5:73:8F:F1:68:A4:FA:12:CB:E2:84:BE:83:4E:DE:1A:7B:B4:4D:D8:45:5B:A1:59:20"]},
+ "com.tmobile.pr.mytmobile": {"carrierIds": [1],"callerSHA256Ids":["92:B5:F8:11:7F:BD:9B:D5:73:8F:F1:68:A4:FA:12:CB:E2:84:BE:83:4E:DE:1A:7B:B4:4D:D8:45:5B:A1:59:20"]}
}
\ No newline at end of file
diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml
index 226ab18..f553698 100644
--- a/res/values-bs/strings.xml
+++ b/res/values-bs/strings.xml
@@ -284,33 +284,33 @@
<string name="data_enable_summary" msgid="696860063456536557">"Dozvoli korištenje podataka"</string>
<string name="dialog_alert_title" msgid="5260471806940268478">"Pažnja"</string>
<string name="roaming" msgid="1576180772877858949">"Roming"</string>
- <string name="roaming_enable" msgid="6853685214521494819">"Povezivanje na usluge prijenosa podataka u romingu"</string>
- <string name="roaming_disable" msgid="8856224638624592681">"Povezivanje na usluge prijenosa podataka u romingu"</string>
+ <string name="roaming_enable" msgid="6853685214521494819">"Povezivanje na usluge prenosa podataka u romingu"</string>
+ <string name="roaming_disable" msgid="8856224638624592681">"Povezivanje na usluge prenosa podataka u romingu"</string>
<string name="roaming_reenable_message" msgid="1951802463885727915">"Roming podataka je isključen. Dodirnite da ga uključite."</string>
<string name="roaming_enabled_message" msgid="9022249120750897">"Mogu nastati troškovi za roming. Dodirnite da izmijenite."</string>
- <string name="roaming_notification_title" msgid="3590348480688047320">"Veza za prijenos podataka na mobilnoj mreži je izgubljena"</string>
+ <string name="roaming_notification_title" msgid="3590348480688047320">"Veza za prenos podataka na mobilnoj mreži je izgubljena"</string>
<string name="roaming_on_notification_title" msgid="7451473196411559173">"Roming podataka je uključen"</string>
<string name="roaming_warning" msgid="7855681468067171971">"Može dovesti do značajnih troškova."</string>
<string name="roaming_check_price_warning" msgid="8212484083990570215">"Raspitajte se kod svog mobilnog operatera za cijene."</string>
<string name="roaming_alert_title" msgid="5689615818220960940">"Dozvoliti roming podataka?"</string>
<string name="limited_sim_function_notification_title" msgid="612715399099846281">"Ograničena funkcionalnost SIM-a"</string>
- <string name="limited_sim_function_with_phone_num_notification_message" msgid="5928988883403677610">"Pozivi i usluge prijenosa podataka operatera <xliff:g id="CARRIER_NAME">%1$s</xliff:g> mogu biti blokirane kada koristite broj <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>."</string>
- <string name="limited_sim_function_notification_message" msgid="5338638075496721160">"Pozivi i usluge prijenosa pod. op. <xliff:g id="CARRIER_NAME">%1$s</xliff:g> mogu biti blok. kada koristite drugi SIM."</string>
+ <string name="limited_sim_function_with_phone_num_notification_message" msgid="5928988883403677610">"Pozivi i usluge prenosa podataka operatera <xliff:g id="CARRIER_NAME">%1$s</xliff:g> mogu biti blokirane kada koristite broj <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>."</string>
+ <string name="limited_sim_function_notification_message" msgid="5338638075496721160">"Pozivi i usluge prenosa pod. op. <xliff:g id="CARRIER_NAME">%1$s</xliff:g> mogu biti blok. kada koristite drugi SIM."</string>
<string name="sip_accounts_removed_notification_title" msgid="3528076957535736095">"Zastarjeli SIP računi su pronađeni i uklonjeni"</string>
<string name="sip_accounts_removed_notification_message" msgid="1916856744869791592">"Android platforma više ne podržva SIP pozivanje.\nVaši postojeći SIP računi <xliff:g id="REMOVED_SIP_ACCOUNTS">%s</xliff:g> su uklonjeni.\nPotvrdite zadanu postavku računa za pozivanje."</string>
<string name="sip_accounts_removed_notification_action" msgid="3772778402370555562">"Idi u postavke"</string>
<string name="data_usage_title" msgid="8438592133893837464">"Prijenos podataka u aplikaciji"</string>
- <string name="data_usage_template" msgid="6287906680674061783">"Iskorišteno je <xliff:g id="ID_1">%1$s</xliff:g> prijenosa podataka u periodu <xliff:g id="ID_2">%2$s</xliff:g>"</string>
+ <string name="data_usage_template" msgid="6287906680674061783">"Iskorišteno je <xliff:g id="ID_1">%1$s</xliff:g> prenosa podataka u periodu <xliff:g id="ID_2">%2$s</xliff:g>"</string>
<string name="advanced_options_title" msgid="9208195294513520934">"Napredno"</string>
<string name="carrier_settings_euicc" msgid="1190237227261337749">"Operater"</string>
<string name="keywords_carrier_settings_euicc" msgid="8540160967922063745">"mobilni operater, esim, sim, euicc, promijeni mobilnog operatera, dodaj mobilnog operatera"</string>
<string name="carrier_settings_euicc_summary" msgid="2027941166597330117">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g> — <xliff:g id="PHONE_NUMBER">%2$s</xliff:g>"</string>
<string name="mobile_data_settings_title" msgid="7228249980933944101">"Prijenos podataka na mobilnoj mreži"</string>
- <string name="mobile_data_settings_summary" msgid="5012570152029118471">"Pristup prijenosu podataka mobilnom mrežom"</string>
+ <string name="mobile_data_settings_summary" msgid="5012570152029118471">"Pristup prenosu podataka mobilnom mrežom"</string>
<string name="data_usage_disable_mobile" msgid="5669109209055988308">"Isključiti prijenos podataka na mobilnoj mreži?"</string>
<string name="sim_selection_required_pref" msgid="6985901872978341314">"Potreban izbor"</string>
- <string name="sim_change_data_title" msgid="9142726786345906606">"Promijeniti SIM za prijenos podataka?"</string>
- <string name="sim_change_data_message" msgid="3567358694255933280">"Koristiti SIM karticu <xliff:g id="NEW_SIM">%1$s</xliff:g> umjesto SIM kartice <xliff:g id="OLD_SIM">%2$s</xliff:g> za prijenos podataka na mobilnoj mreži?"</string>
+ <string name="sim_change_data_title" msgid="9142726786345906606">"Promijeniti SIM za prenos podataka?"</string>
+ <string name="sim_change_data_message" msgid="3567358694255933280">"Koristiti SIM karticu <xliff:g id="NEW_SIM">%1$s</xliff:g> umjesto SIM kartice <xliff:g id="OLD_SIM">%2$s</xliff:g> za prenos podataka na mobilnoj mreži?"</string>
<string name="wifi_calling_settings_title" msgid="5800018845662016507">"Pozivanje putem WiFi-ja"</string>
<string name="video_calling_settings_title" msgid="342829454913266078">"Video pozivi putem operatera"</string>
<string name="gsm_umts_options" msgid="4968446771519376808">"GSM/UMTS opcije"</string>
@@ -318,13 +318,13 @@
<string name="throttle_data_usage" msgid="1944145350660420711">"Korištenje podataka"</string>
<string name="throttle_current_usage" msgid="7483859109708658613">"Iskorišteni podaci u trenutnom periodu"</string>
<string name="throttle_time_frame" msgid="1813452485948918791">"Period korištenja podataka"</string>
- <string name="throttle_rate" msgid="7641913901133634905">"Pravila o brzini prijenosa podataka"</string>
+ <string name="throttle_rate" msgid="7641913901133634905">"Pravila o brzini prenosa podataka"</string>
<string name="throttle_help" msgid="2624535757028809735">"Saznajte više"</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> ٪) od <xliff:g id="USED_2">%3$s</xliff:g> maksimuma perioda\nSljedeći period počinje za <xliff:g id="USED_3">%4$d</xliff:g> dan(a) (<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> ٪) od <xliff:g id="USED_2">%3$s</xliff:g> maksimuma perioda"</string>
- <string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> ograničenje je prekoračeno \nBrzina prijenosa podataka je smanjena na <xliff:g id="USED_1">%2$d</xliff:g> Kb/s"</string>
+ <string name="throttle_data_rate_reduced_subtext" msgid="8369839346277847725">"<xliff:g id="USED_0">%1$s</xliff:g> ograničenje je prekoračeno \nBrzina prenosa podataka je smanjena na <xliff:g id="USED_1">%2$d</xliff:g> Kb/s"</string>
<string name="throttle_time_frame_subtext" msgid="6462089615392402127">"Proteklo je <xliff:g id="USED_0">%1$d</xliff:g> ٪ ciklusa\nSljedeći period počinje za <xliff:g id="USED_1">%2$d</xliff:g> dan(a) (<xliff:g id="USED_2">%3$s</xliff:g>)"</string>
- <string name="throttle_rate_subtext" msgid="7221971817325779535">"Brzina prijenosa podataka se smanjuje na <xliff:g id="USED">%1$d</xliff:g> Kb/s ako se prekorači ograničenje korištenja podataka"</string>
+ <string name="throttle_rate_subtext" msgid="7221971817325779535">"Brzina prenosa podataka se smanjuje na <xliff:g id="USED">%1$d</xliff:g> Kb/s ako se prekorači ograničenje korištenja podataka"</string>
<string name="throttle_help_subtext" msgid="2817114897095534807">"Više informacija o pravilima korištenja podataka mobilne mreže vašeg operatera"</string>
<string name="cell_broadcast_sms" msgid="4053449797289031063">"SMS info servisa"</string>
<string name="enable_disable_cell_bc_sms" msgid="4759958924031721350">"SMS info servisa"</string>
@@ -553,7 +553,7 @@
<string name="incall_error_supp_service_switch" msgid="5272822448189448479">"Nije moguće prebacivati pozive."</string>
<string name="incall_error_supp_service_resume" msgid="1276861499306817035">"Nije moguće nastaviti poziv."</string>
<string name="incall_error_supp_service_separate" msgid="8932660028965274353">"Nije moguće odvojiti poziv."</string>
- <string name="incall_error_supp_service_transfer" msgid="8211925891867334323">"Prijenos nije moguć."</string>
+ <string name="incall_error_supp_service_transfer" msgid="8211925891867334323">"Prenos nije moguć."</string>
<string name="incall_error_supp_service_conference" msgid="27578082433544702">"Nije moguće spajati pozive."</string>
<string name="incall_error_supp_service_reject" msgid="3044363092441655912">"Nije moguće odbiti poziv."</string>
<string name="incall_error_supp_service_hangup" msgid="836524952243836735">"Nije moguće uputiti poziv(e)."</string>
@@ -621,7 +621,7 @@
<string name="ota_title_activate" msgid="4049645324841263423">"Aktivirajte svoj telefon"</string>
<string name="ota_touch_activate" msgid="838764494319694754">"Za aktiviranje telefonske usluge potrebno je uputiti poseban poziv. \n\nNakon što pritisnete „Aktiviraj“, poslušajte uputstva za aktiviranje telefona."</string>
<string name="ota_hfa_activation_title" msgid="3300556778212729671">"Aktivacija u toku..."</string>
- <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Telefon aktivira uslugu prijenosa mobilnih podataka.\n\nTo može potrajati do 5 minuta."</string>
+ <string name="ota_hfa_activation_dialog_message" msgid="7921718445773342996">"Telefon aktivira uslugu prenosa mobilnih podataka.\n\nTo može potrajati do 5 minuta."</string>
<string name="ota_skip_activation_dialog_title" msgid="7666611236789203797">"Preskočiti aktivaciju?"</string>
<string name="ota_skip_activation_dialog_message" msgid="6691722887019708713">"Ako preskočite aktivaciju, nećete moći upućivati pozive niti se povezati na mobilne podatkovne mreže (iako se možete povezati s WiFi mrežama). Dok ne aktivirate telefon, prikazivat će se upit za aktivaciju svaki put kada upalite telefon."</string>
<string name="ota_skip_activation_dialog_skip_label" msgid="5908029466817825633">"Preskoči"</string>
@@ -642,7 +642,7 @@
<string name="phone_entered_ecm_text" msgid="8431238297843035842">"Aktiviran način rada za hitni povratni poziv"</string>
<string name="phone_in_ecm_notification_title" msgid="6825016389926367946">"Način rada za hitni povratni poziv"</string>
<string name="phone_in_ecm_call_notification_text" msgid="653972232922670335">"Podatkovna veza je onemogućena"</string>
- <string name="phone_in_ecm_notification_complete_time" msgid="7341624337163082759">"Nema veze za prijenos podataka do <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
+ <string name="phone_in_ecm_notification_complete_time" msgid="7341624337163082759">"Nema veze za prenos podataka do <xliff:g id="COMPLETETIME">%s</xliff:g>"</string>
<!-- format error in translation for alert_dialog_exit_ecm (7661603870224398025) -->
<!-- format error in translation for alert_dialog_not_avaialble_in_ecm (8717711120099503279) -->
<string name="alert_dialog_in_ecm_call" msgid="1207545603149771978">"Odabrana radnja nije dostupna tokom hitnog poziva."</string>
@@ -707,10 +707,10 @@
<string name="mobile_data_status_roaming_with_plan_subtext" msgid="2576177169108123095">"Trenutno u romingu, plan za podatke je aktivan"</string>
<string name="mobile_data_status_no_plan_subtext" msgid="170331026419263657">"Nema preostalih mobilnih podataka"</string>
<string name="mobile_data_activate_prepaid" msgid="4276738964416795596">"Nema preostalih mobilnih podataka"</string>
- <string name="mobile_data_activate_prepaid_summary" msgid="6846085278531605925">"Dodajte podatke za prijenos na mobilnoj mreži putem operatera <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
+ <string name="mobile_data_activate_prepaid_summary" msgid="6846085278531605925">"Dodajte podatke za prenos na mobilnoj mreži putem operatera <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
<string name="mobile_data_activate_roaming_plan" msgid="922290995866269366">"Nema plana za roming"</string>
<string name="mobile_data_activate_roaming_plan_summary" msgid="5379228493306235969">"Dodajte plan za roming pomoću pružaoca usluga <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
- <string name="mobile_data_activate_footer" msgid="7895874069807204548">"Možete dodati podatke za prijenos na mobilnoj mreži ili plan za roming pomoću operatera, <xliff:g id="PROVIDER_NAME">%s</xliff:g>."</string>
+ <string name="mobile_data_activate_footer" msgid="7895874069807204548">"Možete dodati podatke za prenos na mobilnoj mreži ili plan za roming pomoću operatera, <xliff:g id="PROVIDER_NAME">%s</xliff:g>."</string>
<string name="mobile_data_activate_diag_title" msgid="5401741936224757312">"Dodati podatke?"</string>
<string name="mobile_data_activate_diag_message" msgid="3527260988020415441">"Možda ćete morati dodati podatke preko pružaoca usluga <xliff:g id="PROVIDER_NAME">%s</xliff:g>"</string>
<string name="mobile_data_activate_button" msgid="1139792516354374612">"DODAJTE PODATKE"</string>
@@ -830,8 +830,8 @@
<string name="supp_service_over_ut_precautions_dual_sim" msgid="5166866975550910474">"Za korištenje usluge <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, provjerite je li za SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g> uključen prijenos podataka na mobilnoj mreži. Ovo možete promijeniti u postavkama mobilne mreže."</string>
<string name="supp_service_over_ut_precautions_roaming_dual_sim" msgid="6627654855191817965">"Za korištenje usluge <xliff:g id="SUPP_SERVICE">%1$s</xliff:g>, provjerite jesu li za SIM <xliff:g id="SIM_NUMBER">%2$d</xliff:g> uključeni prijenos podataka na mobilnoj mreži i roming podataka. Ovo možete promijeniti u postavkama mobilne mreže."</string>
<string name="supp_service_over_ut_precautions_dialog_dismiss" msgid="5934541487903081652">"Odbaci"</string>
- <string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Omogućite vezu za prijenos podataka"</string>
- <string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Onemogući vezu za prijenos podataka"</string>
+ <string name="radio_info_data_connection_enable" msgid="6183729739783252840">"Omogućite vezu za prenos podataka"</string>
+ <string name="radio_info_data_connection_disable" msgid="6404751291511368706">"Onemogući vezu za prenos podataka"</string>
<string name="volte_provisioned_switch_string" msgid="4812874990480336178">"VoLTE omogućen"</string>
<string name="vt_provisioned_switch_string" msgid="8295542122512195979">"Video pozivi su omogućeni"</string>
<string name="wfc_provisioned_switch_string" msgid="3835004640321078988">"WiFi poziv obezbijeđen"</string>
@@ -882,7 +882,7 @@
<string name="radioInfo_lac" msgid="3892986460272607013">"LAC"</string>
<string name="radioInfo_cid" msgid="1423185536264406705">"CID"</string>
<string name="radio_info_subid" msgid="6839966868621703203">"Trenutni pomoćni ID:"</string>
- <string name="radio_info_dds" msgid="1122593144425697126">"Pomoćni ID za zadani SIM za prijenos podataka:"</string>
+ <string name="radio_info_dds" msgid="1122593144425697126">"Pomoćni ID za zadani SIM za prenos podataka:"</string>
<string name="radio_info_dl_kbps" msgid="2382922659525318726">"DL propusnost (kbps):"</string>
<string name="radio_info_ul_kbps" msgid="2102225400904799036">"UL propusnost (kbps):"</string>
<string name="radio_info_phy_chan_config" msgid="608045501232211303">"Konfiguracije fizičkih kanala:"</string>
@@ -902,7 +902,7 @@
<string name="radio_info_message_waiting_label" msgid="1886549432566952078">"Poruka na čekanju:"</string>
<string name="radio_info_phone_number_label" msgid="2533852539562512203">"Broj telefona:"</string>
<string name="radio_info_voice_network_type_label" msgid="2395347336419593265">"Vrsta glasovne mreže:"</string>
- <string name="radio_info_data_network_type_label" msgid="8886597029237501929">"Vrsta mreže za prijenos podataka:"</string>
+ <string name="radio_info_data_network_type_label" msgid="8886597029237501929">"Vrsta mreže za prenos podataka:"</string>
<string name="radio_info_override_network_type_label" msgid="4176280017221092005">"Zaobilaženje vrste mreže:"</string>
<string name="radio_info_voice_raw_registration_state_label" msgid="2822988327145825128">"Stanje registracije sirovog glasa:"</string>
<string name="radio_info_data_raw_registration_state_label" msgid="2895895513822604539">"Stanje registracije sirovih podataka:"</string>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
index ddbec3a..8cb4d1d 100644
--- a/res/values-ja/strings.xml
+++ b/res/values-ja/strings.xml
@@ -184,7 +184,7 @@
<string name="connect_later" msgid="1950138106010005425">"現在このネットワークに接続できません。しばらくしてからもう一度お試しください。"</string>
<string name="registration_done" msgid="5337407023566953292">"ネットワークに登録されました。"</string>
<string name="already_auto" msgid="8607068290733079336">"すでに自動選択が適用されています。"</string>
- <string name="select_automatically" msgid="779750291257872651">"ネットワークを自動的に選択"</string>
+ <string name="select_automatically" msgid="779750291257872651">"ネットワークを自動的に選択する"</string>
<string name="manual_mode_disallowed_summary" msgid="3970048592179890197">"%1$s に接続中はご利用いただけません"</string>
<string name="network_select_title" msgid="4117305053881611988">"ネットワーク"</string>
<string name="register_automatically" msgid="3907580547590554834">"自動登録..."</string>
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index bd90a9d..440c39d 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -6641,6 +6641,8 @@
* Sets the ImsService Package Name that Telephony will bind to.
*
* @param slotIndex the slot ID that the ImsService should bind for.
+ * @param userId the user ID that the ImsService should bind for or {@link UserHandle#USER_NULL}
+ * if there is no preference.
* @param isCarrierService true if the ImsService is the carrier override, false if the
* ImsService is the device default ImsService.
* @param featureTypes An integer array of feature types associated with a packageName.
@@ -6648,7 +6650,7 @@
* with.
* @return true if setting the ImsService to bind to succeeded, false if it did not.
*/
- public boolean setBoundImsServiceOverride(int slotIndex, boolean isCarrierService,
+ public boolean setBoundImsServiceOverride(int slotIndex, int userId, boolean isCarrierService,
int[] featureTypes, String packageName) {
TelephonyPermissions.enforceShellOnly(Binder.getCallingUid(), "setBoundImsServiceOverride");
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(mApp,
@@ -6660,12 +6662,8 @@
// may happen if the device does not support IMS.
return false;
}
- Map<Integer, String> featureConfig = new HashMap<>();
- for (int featureType : featureTypes) {
- featureConfig.put(featureType, packageName);
- }
- return mImsResolver.overrideImsServiceConfiguration(slotIndex, isCarrierService,
- featureConfig);
+ return mImsResolver.overrideImsServiceConfiguration(packageName, slotIndex, userId,
+ isCarrierService, featureTypes);
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -13204,11 +13202,14 @@
final long identity = Binder.clearCallingIdentity();
try {
if (enableSatellite) {
+ String caller = "PIM:requestSatelliteEnabled";
ResultReceiver resultReceiver = new ResultReceiver(mMainThreadHandler) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
Log.d(LOG_TAG, "Satellite access restriction resultCode=" + resultCode
+ ", resultData=" + resultData);
+ mSatelliteController.decrementResultReceiverCount(caller);
+
boolean isAllowed = false;
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(
callback::accept);
@@ -13241,6 +13242,7 @@
};
mSatelliteAccessController.requestIsCommunicationAllowedForCurrentLocation(
resultReceiver, true);
+ mSatelliteController.incrementResultReceiverCount(caller);
} else {
// No need to check if satellite is allowed at current location when disabling
// satellite
@@ -13723,6 +13725,29 @@
}
/**
+ * Request to get satellite access configuration for the current location.
+ *
+ * @param result The result receiver that returns the satellite access configuration
+ * for the current location if the request is successful or an error code
+ * if the request failed.
+ *
+ * @throws SecurityException if the caller doesn't have the required permission.
+ */
+ @Override
+ public void requestSatelliteAccessConfigurationForCurrentLocation(
+ @NonNull ResultReceiver result) {
+ enforceSatelliteCommunicationPermission(
+ "requestSatelliteAccessConfigurationForCurrentLocation");
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mSatelliteAccessController
+ .requestSatelliteAccessConfigurationForCurrentLocation(result);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ /**
* Request to get the time after which the satellite will be visible.
*
* @param result The result receiver that returns the time after which the satellite will
@@ -14725,6 +14750,24 @@
}
}
+
+ /**
+ * Inform whether application supports NTN SMS in satellite mode.
+ *
+ * This method is used by default messaging application to inform framework whether it supports
+ * NTN SMS or not.
+ *
+ * @param ntnSmsSupported {@code true} If application supports NTN SMS, else {@code false}.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ */
+ @Override
+ public void setNtnSmsSupported(boolean ntnSmsSupported) {
+ enforceSatelliteCommunicationPermission("setNtnSmsSupported");
+ enforceSendSmsPermission();
+ mSatelliteController.setNtnSmsSupportedByMessagesApp(ntnSmsSupported);
+ }
+
/**
* This API can be used by only CTS to override the cached value for the device overlay config
* value :
diff --git a/src/com/android/phone/TelephonyShellCommand.java b/src/com/android/phone/TelephonyShellCommand.java
index 840f961..5ea1304 100644
--- a/src/com/android/phone/TelephonyShellCommand.java
+++ b/src/com/android/phone/TelephonyShellCommand.java
@@ -526,11 +526,14 @@
private void onHelpIms() {
PrintWriter pw = getOutPrintWriter();
pw.println("IMS Commands:");
- pw.println(" ims set-ims-service [-s SLOT_ID] (-c | -d | -f) PACKAGE_NAME");
+ pw.println(" ims set-ims-service [-s SLOT_ID] [-u USER_ID] (-c | -d | -f) PACKAGE_NAME");
pw.println(" Sets the ImsService defined in PACKAGE_NAME to to be the bound");
pw.println(" ImsService. Options are:");
pw.println(" -s: the slot ID that the ImsService should be bound for. If no option");
pw.println(" is specified, it will choose the default voice SIM slot.");
+ pw.println(" -u: the user ID that the ImsService should be bound on. If no option");
+ pw.println(" is specified, the SYSTEM user ID will be preferred followed by the");
+ pw.println(" current user ID if they are different");
pw.println(" -c: Override the ImsService defined in the carrier configuration.");
pw.println(" -d: Override the ImsService defined in the device overlay.");
pw.println(" -f: Set the feature that this override if for, if no option is");
@@ -1353,12 +1356,22 @@
private int handleImsSetServiceCommand() {
PrintWriter errPw = getErrPrintWriter();
int slotId = getDefaultSlot();
+ int userId = UserHandle.USER_NULL; // By default, set no userId constraint
Boolean isCarrierService = null;
List<Integer> featuresList = new ArrayList<>();
String opt;
while ((opt = getNextOption()) != null) {
switch (opt) {
+ case "-u": {
+ try {
+ userId = Integer.parseInt(getNextArgRequired());
+ } catch (NumberFormatException e) {
+ errPw.println("ims set-ims-service requires an integer as a USER_ID");
+ return -1;
+ }
+ break;
+ }
case "-s": {
try {
slotId = Integer.parseInt(getNextArgRequired());
@@ -1414,17 +1427,17 @@
for (int i = 0; i < featuresList.size(); i++) {
featureArray[i] = featuresList.get(i);
}
- boolean result = mInterface.setBoundImsServiceOverride(slotId, isCarrierService,
+ boolean result = mInterface.setBoundImsServiceOverride(slotId, userId, isCarrierService,
featureArray, packageName);
if (VDBG) {
- Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " "
+ Log.v(LOG_TAG, "ims set-ims-service -s " + slotId + " -u " + userId + " "
+ (isCarrierService ? "-c " : "-d ")
+ "-f " + featuresList + " "
+ packageName + ", result=" + result);
}
getOutPrintWriter().println(result);
} catch (RemoteException e) {
- Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " "
+ Log.w(LOG_TAG, "ims set-ims-service -s " + slotId + " -u " + userId + " "
+ (isCarrierService ? "-c " : "-d ")
+ "-f " + featuresList + " "
+ packageName + ", error" + e.getMessage());
diff --git a/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessController.java b/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessController.java
index c5ecfd9..845ff18 100644
--- a/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessController.java
@@ -15,15 +15,11 @@
*/
package com.android.phone.satellite.accesscontrol;
-import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.telephony.Rlog;
import com.android.internal.telephony.flags.FeatureFlags;
-import com.android.storage.s2.S2LevelRange;
-
import com.android.telephony.sats2range.read.SatS2RangeFileReader;
import com.android.telephony.sats2range.read.SuffixTableRange;
@@ -178,18 +174,22 @@
@Override
@Nullable
- public Integer getRegionalConfigIdForLocation(LocationToken locationToken)
+ public Integer getRegionalConfigIdForLocation(@NonNull LocationToken locationToken)
throws IOException {
if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
logd("getAccessControlConfigIdForLocation: carrierRoamingNbIotNtn is disabled");
return null;
}
- if (!isSatCommunicationAllowedAtLocation(locationToken)) {
- logd("getRegionalConfigIdForLocation: isSatCommunicationAllowedAtLocation is false");
- return null;
+ if (locationToken instanceof LocationTokenImpl locationTokenImpl) {
+ return getRegionalConfigIdForLocation(locationTokenImpl.getS2CellId());
+ } else {
+ throw new IllegalArgumentException("Unknown locationToken=" + locationToken);
}
+ }
- return DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
+ private Integer getRegionalConfigIdForLocation(long s2CellId) throws IOException {
+ SuffixTableRange entry = mSatS2RangeFileReader.findEntryByCellId(s2CellId);
+ return (entry == null) ? null : entry.getEntryValue();
}
}
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index 49edf6a..5f60291 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -16,6 +16,7 @@
package com.android.phone.satellite.accesscontrol;
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_ACCESS_CONFIGURATION;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_PROVISIONED;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
@@ -24,6 +25,7 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_NOT_IN_ALLOWED_REGION;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_UNSUPPORTED_DEFAULT_MSG_APP;
import static android.telephony.satellite.SatelliteManager.SATELLITE_DISALLOWED_REASON_LOCATION_DISABLED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_LOCATION_DISABLED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_LOCATION_NOT_AVAILABLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
@@ -78,6 +80,7 @@
import android.telephony.satellite.ISatelliteDisallowedReasonsCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
import android.telephony.satellite.ISatelliteSupportedStateCallback;
+import android.telephony.satellite.SatelliteAccessConfiguration;
import android.telephony.satellite.SatelliteManager;
import android.telephony.satellite.SatelliteSubscriberProvisionStatus;
import android.text.TextUtils;
@@ -116,6 +119,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -160,6 +164,8 @@
protected static final int EVENT_LOCATION_SETTINGS_ENABLED = 6;
public static final int DEFAULT_REGIONAL_SATELLITE_CONFIG_ID = 0;
+ public static final int UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID = -1;
+
private static final String KEY_AVAILABLE_NOTIFICATION_SHOWN = "available_notification_shown";
private static final String KEY_UNAVAILABLE_NOTIFICATION_SHOWN =
@@ -260,11 +266,11 @@
private long mOverriddenLocationFreshDurationNanos;
@GuardedBy("mLock")
@NonNull
- private final Map<SatelliteOnDeviceAccessController.LocationToken, Boolean>
+ private final Map<SatelliteOnDeviceAccessController.LocationToken, Integer>
mCachedAccessRestrictionMap = new LinkedHashMap<>() {
@Override
protected boolean removeEldestEntry(
- Entry<SatelliteOnDeviceAccessController.LocationToken, Boolean> eldest) {
+ Entry<SatelliteOnDeviceAccessController.LocationToken, Integer> eldest) {
return size() > MAX_CACHE_SIZE;
}
};
@@ -277,7 +283,15 @@
private Location mFreshLastKnownLocation = null;
@GuardedBy("mLock")
@Nullable
- private Integer mRegionalConfigId = null;
+ protected Integer mRegionalConfigId = null;
+ @GuardedBy("mLock")
+ @Nullable
+ protected Integer mNewRegionalConfigId = null;
+
+ /** Key: Config ID; Value: SatelliteAccessConfiguration */
+ @NonNull
+ private HashMap<Integer, SatelliteAccessConfiguration> mSatelliteAccessConfigMap =
+ new HashMap<>();
/** These are used for CTS test */
private Path mCtsSatS2FilePath = null;
@@ -425,6 +439,9 @@
handleIsSatelliteSupportedResult(resultCode, resultData);
}
};
+ mSatelliteController.incrementResultReceiverCount(
+ "SAC:mInternalSatelliteSupportedResultReceiver");
+
mInternalSatelliteProvisionedResultReceiver = new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
@@ -442,13 +459,16 @@
public void onSatelliteSupportedStateChanged(boolean isSupported) {
logd("onSatelliteSupportedStateChanged: isSupported=" + isSupported);
if (isSupported) {
+ final String caller = "SAC:onSatelliteSupportedStateChanged";
requestIsCommunicationAllowedForCurrentLocation(
new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mSatelliteController.decrementResultReceiverCount(caller);
// do nothing
}
}, false);
+ mSatelliteController.incrementResultReceiverCount(caller);
if (mSatelliteDisallowedReasons.contains(
Integer.valueOf(SATELLITE_DISALLOWED_REASON_NOT_SUPPORTED))) {
mSatelliteDisallowedReasons.remove(
@@ -473,13 +493,16 @@
public void onSatelliteProvisionStateChanged(boolean isProvisioned) {
logd("onSatelliteProvisionStateChanged: isProvisioned=" + isProvisioned);
if (isProvisioned) {
+ final String caller = "SAC:onSatelliteProvisionStateChanged";
requestIsCommunicationAllowedForCurrentLocation(
new ResultReceiver(null) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
+ mSatelliteController.decrementResultReceiverCount(caller);
// do nothing
}
}, false);
+ mSatelliteController.incrementResultReceiverCount(caller);
if (mSatelliteDisallowedReasons.contains(
SATELLITE_DISALLOWED_REASON_NOT_PROVISIONED)) {
mSatelliteDisallowedReasons.remove(
@@ -522,6 +545,13 @@
mCurrentSatelliteAllowedState = isAllowed;
notifySatelliteCommunicationAllowedStateChanged(isAllowed);
mControllerMetricsStats.reportAllowedStateChanged();
+ if (!isAllowed) {
+ synchronized (mLock) {
+ plogd("updateCurrentSatelliteAllowedState : set mNewRegionalConfigId null");
+ mNewRegionalConfigId = null;
+ }
+ }
+ updateRegionalConfigId();
}
}
}
@@ -591,6 +621,68 @@
mAccessControllerMetricsStats.setTriggeringEvent(TRIGGERING_EVENT_EXTERNAL_REQUEST);
sendRequestAsync(CMD_IS_SATELLITE_COMMUNICATION_ALLOWED,
new Pair<>(mSatelliteController.getSelectedSatelliteSubId(), result));
+ mSatelliteController.incrementResultReceiverCount(
+ "SAC:requestIsCommunicationAllowedForCurrentLocation");
+ }
+
+ /**
+ * Request to get satellite access configuration for the current location.
+ *
+ * @param result The result receiver that returns satellite access configuration
+ * for the current location if the request is successful or an error code
+ * if the request failed.
+ */
+ public void requestSatelliteAccessConfigurationForCurrentLocation(
+ @NonNull ResultReceiver result) {
+ if (!mFeatureFlags.carrierRoamingNbIotNtn()) {
+ plogd("carrierRoamingNbIotNtnFlag is disabled");
+ result.send(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, null);
+ return;
+ }
+ plogd("requestSatelliteAccessConfigurationForCurrentLocation");
+ ResultReceiver internalResultReceiver = new ResultReceiver(this) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ plogd("requestSatelliteAccessConfigurationForCurrentLocation: resultCode="
+ + resultCode + ", resultData=" + resultData);
+ boolean isSatelliteCommunicationAllowed = false;
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ if (resultData.containsKey(KEY_SATELLITE_COMMUNICATION_ALLOWED)) {
+ isSatelliteCommunicationAllowed =
+ resultData.getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED);
+ } else {
+ loge("KEY_SATELLITE_COMMUNICATION_ALLOWED does not exist.");
+ result.send(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, null);
+ return;
+ }
+ } else {
+ loge("resultCode is not SATELLITE_RESULT_SUCCESS.");
+ result.send(resultCode, null);
+ return;
+ }
+
+ SatelliteAccessConfiguration satelliteAccessConfig = null;
+ synchronized (mLock) {
+ if (isSatelliteCommunicationAllowed && isRegionalConfigIdValid(
+ mRegionalConfigId)) {
+ plogd("requestSatelliteAccessConfigurationForCurrentLocation : "
+ + "mRegionalConfigId is " + mRegionalConfigId);
+ satelliteAccessConfig =
+ mSatelliteAccessConfigMap.get(mRegionalConfigId);
+ }
+ }
+ plogd("requestSatelliteAccessConfigurationForCurrentLocation : "
+ + "satelliteAccessConfig is " + satelliteAccessConfig);
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(KEY_SATELLITE_ACCESS_CONFIGURATION, satelliteAccessConfig);
+ result.send(resultCode, bundle);
+ }
+ };
+ requestIsCommunicationAllowedForCurrentLocation(internalResultReceiver, false);
+ }
+
+ private boolean isRegionalConfigIdValid(@Nullable Integer configId) {
+ return (configId != null && configId >= 0);
}
/**
@@ -1125,8 +1217,8 @@
if (isRegionDisallowed(networkCountryIsoList)) {
Bundle bundle = new Bundle();
bundle.putBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED, false);
- mAccessControllerMetricsStats.setAccessControlType(
- SatelliteConstants.ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE)
+ mAccessControllerMetricsStats.setAccessControlType(SatelliteConstants
+ .ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE)
.setCountryCodes(networkCountryIsoList);
sendSatelliteAllowResultToReceivers(SATELLITE_RESULT_SUCCESS, bundle,
false);
@@ -1180,6 +1272,8 @@
synchronized (mLock) {
for (ResultReceiver resultReceiver : mSatelliteAllowResultReceivers) {
resultReceiver.send(resultCode, resultData);
+ mSatelliteController.decrementResultReceiverCount(
+ "SAC:requestIsCommunicationAllowedForCurrentLocation");
}
mSatelliteAllowResultReceivers.clear();
}
@@ -1704,8 +1798,11 @@
location.getLatitude(),
location.getLongitude(), mS2Level);
boolean satelliteAllowed;
+
if (mCachedAccessRestrictionMap.containsKey(locationToken)) {
- satelliteAllowed = mCachedAccessRestrictionMap.get(locationToken);
+ mNewRegionalConfigId = mCachedAccessRestrictionMap.get(locationToken);
+ satelliteAllowed = (mNewRegionalConfigId != null);
+ plogd("mNewRegionalConfigId is " + mNewRegionalConfigId);
} else {
if (!initSatelliteOnDeviceAccessController()) {
ploge("Failed to init SatelliteOnDeviceAccessController");
@@ -1718,16 +1815,20 @@
if (mFeatureFlags.carrierRoamingNbIotNtn()) {
synchronized (mLock) {
- mRegionalConfigId = mSatelliteOnDeviceAccessController
+ mNewRegionalConfigId = mSatelliteOnDeviceAccessController
.getRegionalConfigIdForLocation(locationToken);
- plogd("mRegionalConfigId is " + mRegionalConfigId);
- satelliteAllowed = (mRegionalConfigId != null);
+ plogd("mNewRegionalConfigId is " + mNewRegionalConfigId);
+ satelliteAllowed = (mNewRegionalConfigId != null);
}
} else {
+ plogd("checkSatelliteAccessRestrictionForLocation: "
+ + "carrierRoamingNbIotNtn is disabled");
satelliteAllowed = mSatelliteOnDeviceAccessController
.isSatCommunicationAllowedAtLocation(locationToken);
+ mNewRegionalConfigId =
+ satelliteAllowed ? UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID : null;
}
- updateCachedAccessRestrictionMap(locationToken, satelliteAllowed);
+ updateCachedAccessRestrictionMap(locationToken, mNewRegionalConfigId);
}
mAccessControllerMetricsStats.setOnDeviceLookupTime(mOnDeviceLookupStartTimeMillis);
Bundle bundle = new Bundle();
@@ -1756,11 +1857,23 @@
}
}
+ private void updateRegionalConfigId() {
+ synchronized (mLock) {
+ plogd("mNewRegionalConfigId: updatedValue = " + mNewRegionalConfigId
+ + " | mRegionalConfigId: beforeValue = " + mRegionalConfigId);
+ if (!Objects.equals(mRegionalConfigId, mNewRegionalConfigId)) {
+ mRegionalConfigId = mNewRegionalConfigId;
+ notifyRegionalSatelliteConfigurationChanged(
+ mSatelliteAccessConfigMap.get(mRegionalConfigId));
+ }
+ }
+ }
+
private void updateCachedAccessRestrictionMap(
@NonNull SatelliteOnDeviceAccessController.LocationToken locationToken,
- boolean satelliteAllowed) {
+ Integer regionalConfigId) {
synchronized (mLock) {
- mCachedAccessRestrictionMap.put(locationToken, satelliteAllowed);
+ mCachedAccessRestrictionMap.put(locationToken, regionalConfigId);
}
}
@@ -2199,6 +2312,14 @@
logd("registerForCommunicationAllowedStateChanged: "
+ "mCurrentSatelliteAllowedState " + mCurrentSatelliteAllowedState);
}
+ synchronized (mLock) {
+ SatelliteAccessConfiguration satelliteAccessConfig =
+ mSatelliteAccessConfigMap.get(mRegionalConfigId);
+ callback.onSatelliteAccessConfigurationChanged(satelliteAccessConfig);
+ logd("registerForCommunicationAllowedStateChanged: satelliteAccessConfig: "
+ + satelliteAccessConfig + " of mRegionalConfigId: "
+ + mRegionalConfigId);
+ }
} catch (RemoteException ex) {
ploge("registerForCommunicationAllowedStateChanged: RemoteException ex=" + ex);
}
@@ -2382,6 +2503,25 @@
});
}
+ protected void notifyRegionalSatelliteConfigurationChanged(
+ @Nullable SatelliteAccessConfiguration satelliteAccessConfig) {
+ plogd("notifyRegionalSatelliteConfigurationChanged : satelliteAccessConfig is "
+ + satelliteAccessConfig);
+
+ List<ISatelliteCommunicationAllowedStateCallback> deadCallersList = new ArrayList<>();
+ mSatelliteCommunicationAllowedStateChangedListeners.values().forEach(listener -> {
+ try {
+ listener.onSatelliteAccessConfigurationChanged(satelliteAccessConfig);
+ } catch (RemoteException e) {
+ plogd("handleEventNtnSignalStrengthChanged RemoteException: " + e);
+ deadCallersList.add(listener);
+ }
+ });
+ deadCallersList.forEach(listener -> {
+ mSatelliteCommunicationAllowedStateChangedListeners.remove(listener.asBinder());
+ });
+ }
+
private void reportMetrics(int resultCode, boolean allowed) {
if (resultCode == SATELLITE_RESULT_SUCCESS) {
mControllerMetricsStats.reportAllowedSatelliteAccessCount(allowed);
diff --git a/src/com/android/phone/settings/RadioInfo.java b/src/com/android/phone/settings/RadioInfo.java
index abc7289..4d98d92 100644
--- a/src/com/android/phone/settings/RadioInfo.java
+++ b/src/com/android/phone/settings/RadioInfo.java
@@ -367,7 +367,7 @@
private String mActionEsos;
private String mActionEsosDemo;
-
+ private Intent mNonEsosIntent;
private TelephonyDisplayInfo mDisplayInfo;
private List<PhysicalChannelConfig> mPhysicalChannelConfigs = new ArrayList<>();
@@ -785,37 +785,33 @@
mEsosDemoButton = (Button) findViewById(R.id.demo_esos_questionnaire);
mSatelliteEnableNonEmergencyModeButton = (Button) findViewById(
R.id.satellite_enable_non_emergency_mode);
- CarrierConfigManager cm = getSystemService(CarrierConfigManager.class);
- PersistableBundle bundle = cm.getConfigForSubId(mSubId,
- CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
- CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
- if (!bundle.getBoolean(
- CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false)
- || !bundle.getBoolean(
- CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false)) {
- mSatelliteEnableNonEmergencyModeButton.setVisibility(View.GONE);
- }
- if (!Build.isDebuggable()) {
- if (!TextUtils.isEmpty(mActionEsos)) {
- mEsosButton.setVisibility(View.GONE);
- }
- if (!TextUtils.isEmpty(mActionEsosDemo)) {
- mEsosDemoButton.setVisibility(View.GONE);
- }
- mSatelliteEnableNonEmergencyModeButton.setVisibility(View.GONE);
+
+ if (shouldHideButton(mActionEsos)) {
+ mEsosButton.setVisibility(View.GONE);
} else {
mEsosButton.setOnClickListener(v -> startActivityAsUser(
new Intent(mActionEsos).addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK),
UserHandle.CURRENT)
);
+ }
+ if (shouldHideButton(mActionEsosDemo)) {
+ mEsosDemoButton.setVisibility(View.GONE);
+ } else {
mEsosDemoButton.setOnClickListener(v -> startActivityAsUser(
new Intent(mActionEsosDemo).addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK),
UserHandle.CURRENT)
);
- mSatelliteEnableNonEmergencyModeButton.setOnClickListener(v ->
- enableSatelliteNonEmergencyMode());
+ }
+ if (shouldHideNonEmergencyMode()) {
+ mSatelliteEnableNonEmergencyModeButton.setVisibility(View.GONE);
+ } else {
+ mSatelliteEnableNonEmergencyModeButton.setOnClickListener(v -> {
+ if (mNonEsosIntent != null) {
+ sendBroadcast(mNonEsosIntent);
+ }
+ });
}
mOemInfoButton = (Button) findViewById(R.id.oem_info);
@@ -839,6 +835,21 @@
restoreFromBundle(icicle);
}
+ boolean shouldHideButton(String action) {
+ if (!Build.isDebuggable()) {
+ return true;
+ }
+ if (TextUtils.isEmpty(action)) {
+ return true;
+ }
+ PackageManager pm = getPackageManager();
+ Intent intent = new Intent(action);
+ if (pm.resolveActivity(intent, 0) == null) {
+ return true;
+ }
+ return false;
+ }
+
@Override
public Intent getParentActivityIntent() {
Intent parentActivity = super.getParentActivityIntent();
@@ -2143,26 +2154,36 @@
}
};
- /**
- * Enable modem satellite for non-emergency mode.
- */
- private void enableSatelliteNonEmergencyMode() {
+ private boolean shouldHideNonEmergencyMode() {
+ if (!Build.isDebuggable()) {
+ return true;
+ }
+ String action = SatelliteManager.ACTION_SATELLITE_START_NON_EMERGENCY_SESSION;
+ if (TextUtils.isEmpty(action)) {
+ return true;
+ }
+ if (mNonEsosIntent != null) {
+ mNonEsosIntent = null;
+ }
CarrierConfigManager cm = getSystemService(CarrierConfigManager.class);
if (cm == null) {
- loge("enableSatelliteNonEmergencyMode: sm or cm is null");
- return;
+ loge("shouldHideNonEmergencyMode: cm is null");
+ return true;
}
- if (!cm.getConfigForSubId(mSubId,
- CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL)
- .getBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL)) {
- loge("enableSatelliteNonEmergencyMode: KEY_SATELLITE_ATTACH_SUPPORTED_BOOL is false");
- return;
+ PersistableBundle bundle = cm.getConfigForSubId(mSubId,
+ CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL);
+ if (!bundle.getBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ESOS_SUPPORTED_BOOL, false)) {
+ log("shouldHideNonEmergencyMode: esos_supported false");
+ return true;
}
- log("enableSatelliteNonEmergencyMode: requestEnabled");
- sendBroadCastForSatelliteNonEmergencyMode();
- }
+ if (!bundle.getBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, false)) {
+ log("shouldHideNonEmergencyMode: attach_supported false");
+ return true;
+ }
- private void sendBroadCastForSatelliteNonEmergencyMode() {
String packageName = getStringFromOverlayConfig(
com.android.internal.R.string.config_satellite_gateway_service_package);
@@ -2170,16 +2191,20 @@
.config_satellite_carrier_roaming_non_emergency_session_class);
if (packageName == null || className == null
|| packageName.isEmpty() || className.isEmpty()) {
- Log.d(TAG, "sendBroadCastForSatelliteNonEmergencyMode:"
+ Log.d(TAG, "shouldHideNonEmergencyMode:"
+ " packageName or className is null or empty.");
- return;
+ return true;
}
- String action = SatelliteManager.ACTION_SATELLITE_START_NON_EMERGENCY_SESSION;
-
+ PackageManager pm = getPackageManager();
Intent intent = new Intent(action);
intent.setComponent(new ComponentName(packageName, className));
- sendBroadcast(intent);
- Log.d(TAG, "sendBroadCastForSatelliteNonEmergencyMode" + intent);
+ if (pm.queryBroadcastReceivers(intent, 0).isEmpty()) {
+ Log.d(TAG, "shouldHideNonEmergencyMode: Broadcast receiver not found for intent: "
+ + intent);
+ return true;
+ }
+ mNonEsosIntent = intent;
+ return false;
}
private String getStringFromOverlayConfig(int resourceId) {
diff --git a/src/com/android/services/telephony/ImsConference.java b/src/com/android/services/telephony/ImsConference.java
index 7f0c800..af1ddb6 100644
--- a/src/com/android/services/telephony/ImsConference.java
+++ b/src/com/android/services/telephony/ImsConference.java
@@ -430,9 +430,9 @@
super(phoneAccountHandle);
- mTelecomAccountRegistry = telecomAccountRegistry;
- mFeatureFlagProxy = featureFlagProxy;
- mCarrierConfig = carrierConfig;
+ mTelecomAccountRegistry = Objects.requireNonNull(telecomAccountRegistry);
+ mFeatureFlagProxy = Objects.requireNonNull(featureFlagProxy);
+ mCarrierConfig = Objects.requireNonNull(carrierConfig);
// Specify the connection time of the conference to be the connection time of the original
// connection.
diff --git a/src/com/android/services/telephony/ImsConferenceController.java b/src/com/android/services/telephony/ImsConferenceController.java
index fa2151b..ca3bcfe 100644
--- a/src/com/android/services/telephony/ImsConferenceController.java
+++ b/src/com/android/services/telephony/ImsConferenceController.java
@@ -142,9 +142,9 @@
public ImsConferenceController(TelecomAccountRegistry telecomAccountRegistry,
TelephonyConnectionServiceProxy connectionService,
ImsConference.FeatureFlagProxy featureFlagProxy) {
- mConnectionService = connectionService;
- mTelecomAccountRegistry = telecomAccountRegistry;
- mFeatureFlagProxy = featureFlagProxy;
+ mConnectionService = Objects.requireNonNull(connectionService);
+ mTelecomAccountRegistry = Objects.requireNonNull(telecomAccountRegistry);
+ mFeatureFlagProxy = Objects.requireNonNull(featureFlagProxy);
}
void addConference(ImsConference conference) {
diff --git a/src/com/android/services/telephony/TelecomAccountRegistry.java b/src/com/android/services/telephony/TelecomAccountRegistry.java
index c7d97f5..8956266 100644
--- a/src/com/android/services/telephony/TelecomAccountRegistry.java
+++ b/src/com/android/services/telephony/TelecomAccountRegistry.java
@@ -70,6 +70,7 @@
import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.phone.PhoneGlobals;
+import com.android.phone.PhoneInterfaceManager;
import com.android.phone.PhoneUtils;
import com.android.phone.R;
import com.android.telephony.Rlog;
@@ -651,8 +652,8 @@
// Check if IMS video pause is supported.
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b != null &&
- b.getBoolean(CarrierConfigManager.KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL);
+ if (b == null) return false;
+ return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL);
}
/**
@@ -697,8 +698,8 @@
private boolean isCarrierInstantLetteringSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b != null &&
- b.getBoolean(CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL);
+ if (b == null) return false;
+ return b.getBoolean(CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL);
}
/**
@@ -709,8 +710,8 @@
private boolean isCarrierAdhocConferenceCallSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b != null &&
- b.getBoolean(CarrierConfigManager.KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL);
+ if (b == null) return false;
+ return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_ADHOC_CONFERENCE_CALLS_BOOL);
}
@@ -722,8 +723,8 @@
private boolean isCarrierMergeCallSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b != null &&
- b.getBoolean(CarrierConfigManager.KEY_SUPPORT_CONFERENCE_CALL_BOOL);
+ if (b == null) return false;
+ return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_CONFERENCE_CALL_BOOL);
}
/**
@@ -734,6 +735,7 @@
private boolean isCarrierMergeImsCallSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ if (b == null) return false;
return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_IMS_CONFERENCE_CALL_BOOL);
}
@@ -745,8 +747,8 @@
private boolean isCarrierEmergencyVideoCallsAllowed() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b != null &&
- b.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL);
+ if (b == null) return false;
+ return b.getBoolean(CarrierConfigManager.KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL);
}
/**
@@ -757,8 +759,8 @@
private boolean isCarrierVideoConferencingSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b != null &&
- b.getBoolean(CarrierConfigManager.KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL);
+ if (b == null) return false;
+ return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_VIDEO_CONFERENCE_CALL_BOOL);
}
/**
@@ -771,7 +773,8 @@
private boolean isCarrierMergeOfWifiCallsAllowedWhenVoWifiOff() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
- return b != null && b.getBoolean(
+ if (b == null) return false;
+ return b.getBoolean(
CarrierConfigManager.KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL);
}
@@ -784,6 +787,7 @@
private boolean isCarrierManageImsConferenceCallSupported() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ if (b == null) return false;
return b.getBoolean(CarrierConfigManager.KEY_SUPPORT_MANAGE_IMS_CONFERENCE_CALL_BOOL);
}
@@ -796,6 +800,7 @@
private boolean isCarrierUsingSimCallManager() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ if (b == null) return false;
return !TextUtils.isEmpty(
b.getString(CarrierConfigManager.KEY_DEFAULT_SIM_CALL_MANAGER_STRING));
}
@@ -810,6 +815,7 @@
private boolean isCarrierShowPreciseFailedCause() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ if (b == null) return false;
return b.getBoolean(CarrierConfigManager.KEY_SHOW_PRECISE_FAILED_CAUSE_BOOL);
}
@@ -822,6 +828,7 @@
private boolean isCarrierUseCallRecordingTone() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ if (b == null) return false;
return b.getBoolean(CarrierConfigManager.KEY_PLAY_CALL_RECORDING_TONE_BOOL);
}
@@ -831,6 +838,7 @@
private boolean isCarrierAllowRttWhenRoaming() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ if (b == null) return false;
return b.getBoolean(CarrierConfigManager.KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL);
}
@@ -843,6 +851,7 @@
private Bundle getPhoneAccountExtras() {
PersistableBundle b =
PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId());
+ if (b == null) return new Bundle();
int instantLetteringMaxLength = b.getInt(
CarrierConfigManager.KEY_CARRIER_INSTANT_LETTERING_LENGTH_LIMIT_INT);
@@ -1054,8 +1063,10 @@
boolean hasVoiceAvailability = isImsVoiceAvailable();
- boolean isRttSupported = PhoneGlobals.getInstance().phoneMgr
- .isRttEnabled(mPhone.getSubId());
+ PhoneInterfaceManager phoneMgr = PhoneGlobals.getInstance()
+ .phoneMgr;
+ boolean isRttSupported = (phoneMgr != null) ?
+ phoneMgr.isRttEnabled(mPhone.getSubId()) : false;
boolean isRoaming = mTelephonyManager.isNetworkRoaming(mPhone.getSubId());
boolean isOnWfc = mPhone.getImsRegistrationTech()
diff --git a/testapps/TestSatelliteApp/AndroidManifest.xml b/testapps/TestSatelliteApp/AndroidManifest.xml
index eaddf95..a1f22fa 100644
--- a/testapps/TestSatelliteApp/AndroidManifest.xml
+++ b/testapps/TestSatelliteApp/AndroidManifest.xml
@@ -20,6 +20,7 @@
<uses-permission android:name="android.permission.BIND_SATELLITE_SERVICE"/>
<uses-permission android:name="android.permission.SATELLITE_COMMUNICATION"/>
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ <uses-permission android:name="android.permission.SEND_SMS"/>
<application android:label="SatelliteTestApp">
<activity android:name=".SatelliteTestApp"
android:label="SatelliteTestApp"
diff --git a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
index 9aec52b..d046f03 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
@@ -191,6 +191,19 @@
android:layout_height="wrap_content"
android:paddingRight="4dp"
android:text="@string/deprovisionSatellite"/>
+ <Button
+ android:id="@+id/setNtnSmsSupportedTrue"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/setNtnSmsSupportedTrue"/>
+ <Button
+ android:id="@+id/setNtnSmsSupportedFalse"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="4dp"
+ android:text="@string/setNtnSmsSupportedFalse"/>
+
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
index 54f2722..4b5ea5b 100644
--- a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
+++ b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
@@ -97,6 +97,9 @@
<string name="requestSatelliteSubscriberProvisionStatus">requestSatelliteSubscriberProvisionStatus</string>
<string name="provisionSatellite">provisionSatellite</string>
<string name="deprovisionSatellite">deprovisionSatellite</string>
+ <string name="setNtnSmsSupportedTrue">setNtnSmsSupportedTrue</string>
+ <string name="setNtnSmsSupportedFalse">setNtnSmsSupportedFalse</string>
+
<string name="Back">Back</string>
<string name="ClearLog">Clear Log</string>
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
index 7c4ae00..cb56e87 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/SatelliteTestApp.java
@@ -16,11 +16,13 @@
package com.android.phone.testapps.satellitetestapp;
+import android.Manifest;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.telephony.satellite.stub.SatelliteDatagram;
@@ -42,6 +44,7 @@
private TestSatelliteServiceConnection mSatelliteServiceConn;
private List<SatelliteDatagram> mSentSatelliteDatagrams = new ArrayList<>();
+ private static final int REQUEST_CODE_SEND_SMS = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -105,6 +108,16 @@
});
}
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (checkSelfPermission(Manifest.permission.SEND_SMS)
+ != PackageManager.PERMISSION_GRANTED) {
+ requestPermissions(new String[]{Manifest.permission.SEND_SMS}, REQUEST_CODE_SEND_SMS);
+ }
+ }
+
+
private final ILocalSatelliteListener mSatelliteListener =
new ILocalSatelliteListener.Stub() {
@Override
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 97cb9c3..7d5e9af 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
@@ -127,6 +127,11 @@
.setOnClickListener(this::provisionSatellite);
findViewById(R.id.deprovisionSatelliteWrapper)
.setOnClickListener(this::deprovisionSatellite);
+ findViewById(R.id.setNtnSmsSupportedTrue)
+ .setOnClickListener(this::setNtnSmsSupportedTrue);
+ findViewById(R.id.setNtnSmsSupportedFalse)
+ .setOnClickListener(this::setNtnSmsSupportedFalse);
+
findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
@Override
@@ -799,6 +804,31 @@
}
}
+ private void setNtnSmsSupportedTrue(View view) {
+ setNtnSmsSupported(true);
+ }
+
+ private void setNtnSmsSupportedFalse(View view) {
+ setNtnSmsSupported(false);
+ }
+
+ private void setNtnSmsSupported(boolean ntnSmsSupported) {
+ String msg = "setNtnSmsSupported:" + ntnSmsSupported;
+ addLogMessage(msg);
+ logd(msg);
+
+ try {
+ mSatelliteManagerWrapper.setNtnSmsSupported(ntnSmsSupported);
+ msg = "setNtnSmsSupported=" + ntnSmsSupported + " is successful";
+ logd(msg);
+ addLogMessage(msg);
+ } catch (SecurityException | IllegalStateException ex) {
+ msg = "setNtnSmsSupported=" + ntnSmsSupported + " failed. " + ex.getMessage();
+ logd(msg);
+ addLogMessage(msg);
+ }
+ }
+
private int getActiveSubId() {
int subId;
List<SubscriptionInfo> subscriptionInfoList =
diff --git a/tests/src/com/android/TelephonyTestBase.java b/tests/src/com/android/TelephonyTestBase.java
index 2bc7bb9..3e74eb7 100644
--- a/tests/src/com/android/TelephonyTestBase.java
+++ b/tests/src/com/android/TelephonyTestBase.java
@@ -16,21 +16,38 @@
package com.android;
+import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
+import android.content.ContextWrapper;
+import android.content.res.Resources;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
+import androidx.test.InstrumentationRegistry;
+
+import com.android.internal.telephony.GsmCdmaPhone;
+import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConfigurationManager;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.data.DataConfigManager;
+import com.android.internal.telephony.data.DataNetworkController;
+import com.android.phone.PhoneGlobals;
+import com.android.phone.PhoneInterfaceManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
+import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.lang.reflect.Field;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@@ -39,12 +56,15 @@
import java.util.concurrent.TimeUnit;
/**
- * Helper class to load Mockito Resources into a test.
+ * Helper class to load Mockito Resources into Telephony unit tests.
*/
public class TelephonyTestBase {
@Rule public final MockitoRule mocks = MockitoJUnit.rule();
protected TestContext mContext;
+ @Mock protected PhoneGlobals mPhoneGlobals;
+ @Mock protected GsmCdmaPhone mPhone;
+ @Mock protected DataNetworkController mDataNetworkController;
private final HashMap<InstanceKey, Object> mOldInstances = new HashMap<>();
private final LinkedList<InstanceKey> mInstanceKeys = new LinkedList<>();
@@ -55,7 +75,31 @@
Looper.prepare();
}
+ doCallRealMethod().when(mPhoneGlobals).getBaseContext();
+ doCallRealMethod().when(mPhoneGlobals).getResources();
+ doCallRealMethod().when(mPhone).getServiceState();
+
mContext = spy(new TestContext());
+ doReturn(mContext).when(mPhone).getContext();
+ replaceInstance(ContextWrapper.class, "mBase", mPhoneGlobals, mContext);
+
+ Resources resources = InstrumentationRegistry.getTargetContext().getResources();
+ assertNotNull(resources);
+ doReturn(resources).when(mContext).getResources();
+
+ replaceInstance(Handler.class, "mLooper", mPhone, Looper.myLooper());
+ replaceInstance(PhoneFactory.class, "sMadeDefaults", null, true);
+ replaceInstance(PhoneFactory.class, "sPhone", null, mPhone);
+ replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone});
+ replaceInstance(PhoneGlobals.class, "sMe", null, mPhoneGlobals);
+
+ doReturn(mDataNetworkController).when(mPhone).getDataNetworkController();
+ doReturn(Collections.emptyList()).when(mDataNetworkController)
+ .getInternetDataDisallowedReasons();
+ doReturn(Mockito.mock(DataConfigManager.class)).when(mDataNetworkController)
+ .getDataConfigManager();
+
+ mPhoneGlobals.phoneMgr = Mockito.mock(PhoneInterfaceManager.class);
}
@After
diff --git a/tests/src/com/android/TestContext.java b/tests/src/com/android/TestContext.java
index e464ad5..a684ef5 100644
--- a/tests/src/com/android/TestContext.java
+++ b/tests/src/com/android/TestContext.java
@@ -103,6 +103,11 @@
}
@Override
+ public String getOpPackageName() {
+ return getPackageName();
+ }
+
+ @Override
public String getAttributionTag() {
return "";
}
@@ -212,6 +217,11 @@
}
@Override
+ public Looper getMainLooper() {
+ return Looper.getMainLooper();
+ }
+
+ @Override
public Handler getMainThreadHandler() {
return new Handler(Looper.getMainLooper());
}
diff --git a/tests/src/com/android/phone/CarrierConfigLoaderTest.java b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
index 99064dd..5190b21 100644
--- a/tests/src/com/android/phone/CarrierConfigLoaderTest.java
+++ b/tests/src/com/android/phone/CarrierConfigLoaderTest.java
@@ -41,7 +41,6 @@
import android.content.res.Resources;
import android.os.Build;
import android.os.Handler;
-import android.os.HandlerThread;
import android.os.PermissionEnforcer;
import android.os.PersistableBundle;
import android.os.UserHandle;
@@ -51,16 +50,13 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyRegistryManager;
+import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.TelephonyTestBase;
-import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.IccCardConstants;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
@@ -75,7 +71,6 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -84,7 +79,8 @@
/**
* Unit Test for CarrierConfigLoader.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class CarrierConfigLoaderTest extends TelephonyTestBase {
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -107,12 +103,10 @@
@Mock SharedPreferences mSharedPreferences;
@Mock TelephonyRegistryManager mTelephonyRegistryManager;
@Mock FeatureFlags mFeatureFlags;
- @Mock GsmCdmaPhone mMockPhone;
private TelephonyManager mTelephonyManager;
private CarrierConfigLoader mCarrierConfigLoader;
private Handler mHandler;
- private HandlerThread mHandlerThread;
private TestableLooper mTestableLooper;
// The AIDL stub will use PermissionEnforcer to check permission from the caller.
@@ -121,10 +115,6 @@
@Before
public void setUp() throws Exception {
super.setUp();
- MockitoAnnotations.initMocks(this);
- Phone[] mPhones = new Phone[]{mMockPhone};
- replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
- replaceInstance(PhoneFactory.class, "sMadeDefaults", null, true);
doReturn(Context.PERMISSION_ENFORCER_SERVICE).when(mContext).getSystemServiceName(
eq(PermissionEnforcer.class));
doReturn(mFakePermissionEnforcer).when(mContext).getSystemService(
@@ -158,10 +148,7 @@
when(mContext.getSystemService(TelephonyRegistryManager.class)).thenReturn(
mTelephonyRegistryManager);
- mHandlerThread = new HandlerThread("CarrierConfigLoaderTest");
- mHandlerThread.start();
-
- mTestableLooper = new TestableLooper(mHandlerThread.getLooper());
+ mTestableLooper = TestableLooper.get(this);
mCarrierConfigLoader = new CarrierConfigLoader(mContext, mTestableLooper.getLooper(),
mFeatureFlags);
mHandler = mCarrierConfigLoader.getHandler();
@@ -176,8 +163,6 @@
mFakePermissionEnforcer.revoke(android.Manifest.permission.DUMP);
mFakePermissionEnforcer.revoke(android.Manifest.permission.MODIFY_PHONE_STATE);
mFakePermissionEnforcer.revoke(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
- mTestableLooper.destroy();
- mHandlerThread.quit();
super.tearDown();
}
diff --git a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
index 0e902a8..5521ac0 100644
--- a/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
+++ b/tests/src/com/android/phone/ImsStateCallbackControllerTest.java
@@ -46,7 +46,6 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
-import android.os.Looper;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyRegistryManager;
import android.testing.TestableLooper;
@@ -70,7 +69,6 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -110,7 +108,6 @@
@Captor ArgumentCaptor<FeatureConnector.Listener<ImsManager>> mMmTelConnectorListenerSlot1;
@Captor ArgumentCaptor<FeatureConnector.Listener<RcsFeatureManager>> mRcsConnectorListenerSlot0;
@Captor ArgumentCaptor<FeatureConnector.Listener<RcsFeatureManager>> mRcsConnectorListenerSlot1;
- @Mock private PhoneGlobals mPhone;
@Mock ImsStateCallbackController.PhoneFactoryProxy mPhoneFactoryProxy;
@Mock Phone mPhoneSlot0;
@Mock Phone mPhoneSlot1;
@@ -134,16 +131,16 @@
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
+ super.setUp();
- when(mPhone.getMainExecutor()).thenReturn(mExecutor);
- when(mPhone.getSystemServiceName(eq(SubscriptionManager.class)))
+ when(mPhoneGlobals.getMainExecutor()).thenReturn(mExecutor);
+ when(mPhoneGlobals.getSystemServiceName(eq(SubscriptionManager.class)))
.thenReturn(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- when(mPhone.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
+ when(mPhoneGlobals.getSystemService(eq(Context.TELEPHONY_SUBSCRIPTION_SERVICE)))
.thenReturn(mSubscriptionManager);
- when(mPhone.getSystemServiceName(eq(TelephonyRegistryManager.class)))
+ when(mPhoneGlobals.getSystemServiceName(eq(TelephonyRegistryManager.class)))
.thenReturn(Context.TELEPHONY_REGISTRY_SERVICE);
- when(mPhone.getSystemService(eq(Context.TELEPHONY_REGISTRY_SERVICE)))
+ when(mPhoneGlobals.getSystemService(eq(Context.TELEPHONY_REGISTRY_SERVICE)))
.thenReturn(mTelephonyRegistryManager);
when(mPhoneFactoryProxy.getPhone(eq(0))).thenReturn(mPhoneSlot0);
when(mPhoneFactoryProxy.getPhone(eq(1))).thenReturn(mPhoneSlot1);
@@ -937,9 +934,6 @@
}
private void createController(int slotCount) throws Exception {
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
makeFakeActiveSubIds(slotCount);
when(mMmTelFeatureFactory
@@ -956,7 +950,7 @@
.thenReturn(mRcsFeatureConnectorSlot1);
mImsStateCallbackController =
- new ImsStateCallbackController(mPhone, mHandlerThread.getLooper(),
+ new ImsStateCallbackController(mPhoneGlobals, mHandlerThread.getLooper(),
slotCount, mMmTelFeatureFactory, mRcsFeatureFactory, mImsResolver,
mFeatureFlags);
diff --git a/tests/src/com/android/phone/NotificationMgrTest.java b/tests/src/com/android/phone/NotificationMgrTest.java
index 2b0ff94..0c1f8a3 100644
--- a/tests/src/com/android/phone/NotificationMgrTest.java
+++ b/tests/src/com/android/phone/NotificationMgrTest.java
@@ -77,11 +77,8 @@
import com.android.TelephonyTestBase;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.SignalStrengthController;
-import com.android.internal.telephony.data.DataConfigManager;
-import com.android.internal.telephony.data.DataNetworkController;
import com.android.internal.telephony.data.DataSettingsManager;
import com.android.internal.telephony.util.NotificationChannelController;
@@ -90,9 +87,7 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import java.util.Collections;
import java.util.concurrent.TimeUnit;
/**
@@ -111,13 +106,12 @@
private static final String MOBILE_NETWORK_SELECTION_CLASS = ".testClass";
private static final String CARRIER_NAME = "CoolCarrier";
- @Mock PhoneGlobals mApp;
+ PhoneGlobals mApp; // mPhoneGlobals alias
@Mock StatusBarManager mStatusBarManager;
@Mock UserManager mUserManager;
@Mock SubscriptionManager mSubscriptionManager;
@Mock TelecomManager mTelecomManager;
@Mock TelephonyManager mTelephonyManager;
- @Mock Phone mPhone;
@Mock SharedPreferences mSharedPreferences;
@Mock NotificationManager mNotificationManager;
@Mock SubscriptionInfo mSubscriptionInfo;
@@ -126,20 +120,16 @@
@Mock ServiceStateTracker mServiceStateTracker;
@Mock ServiceState mServiceState;
@Mock CarrierConfigManager mCarrierConfigManager;
- @Mock DataNetworkController mDataNetworkController;
@Mock DataSettingsManager mDataSettingsManager;
- @Mock DataConfigManager mDataConfigManager;
@Mock SignalStrengthController mSignalStrengthController;
- private Phone[] mPhones;
private NotificationMgr mNotificationMgr;
private TestableLooper mTestableLooper;
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- mPhones = new Phone[]{mPhone};
- replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ super.setUp();
+ mApp = mPhoneGlobals;
when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
when(mPhone.getContext()).thenReturn(mMockedContext);
when(mMockedContext.getResources()).thenReturn(mResources);
@@ -152,10 +142,6 @@
when(mPhone.getServiceStateTracker()).thenReturn(mServiceStateTracker);
mServiceStateTracker.mSS = mServiceState;
when(mPhone.getSignalStrengthController()).thenReturn(mSignalStrengthController);
- when(mPhone.getDataNetworkController()).thenReturn(mDataNetworkController);
- when(mDataNetworkController.getInternetDataDisallowedReasons()).thenReturn(
- Collections.emptyList());
- when(mDataNetworkController.getDataConfigManager()).thenReturn(mDataConfigManager);
when(mPhone.getDataSettingsManager()).thenReturn(mDataSettingsManager);
when(mDataSettingsManager.isDataEnabledForReason(anyInt())).thenReturn(true);
when(mApp.getSharedPreferences(anyString(), anyInt())).thenReturn(mSharedPreferences);
diff --git a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
index 5ecf111..ef6a02a 100644
--- a/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
+++ b/tests/src/com/android/phone/PhoneInterfaceManagerTest.java
@@ -47,9 +47,10 @@
import android.preference.PreferenceManager;
import android.telephony.RadioAccessFamily;
import android.telephony.TelephonyManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
import androidx.test.annotation.UiThreadTest;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.TelephonyTestBase;
@@ -78,7 +79,8 @@
/**
* Unit Test for PhoneInterfaceManager.
*/
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class PhoneInterfaceManagerTest extends TelephonyTestBase {
@Rule
public TestRule compatChangeRule = new PlatformCompatChangeRule();
@@ -90,8 +92,6 @@
PhoneInterfaceManagerTest.class.getPackageName();
@Mock
- PhoneGlobals mPhoneGlobals;
- @Mock
Phone mPhone;
@Mock
FeatureFlags mFeatureFlags;
@@ -121,6 +121,8 @@
mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_AND_INTEGRITY_ENABLED).commit();
mSharedPreferences.edit().remove(Phone.PREF_NULL_CIPHER_NOTIFICATIONS_ENABLED).commit();
+ // Trigger sInstance restore in tearDown, after PhoneInterfaceManager.init.
+ replaceInstance(PhoneInterfaceManager.class, "sInstance", null, null);
// 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
@@ -503,7 +505,7 @@
doNothing().when(mPhoneInterfaceManager).enforceModifyPermission();
// FEATURE_TELEPHONY_CALLING
- mPhoneInterfaceManager.handlePinMmiForSubscriber(1, "123456789");
+ mPhoneInterfaceManager.getVoiceActivationState(1, "com.test.package");
// FEATURE_TELEPHONY_RADIO_ACCESS
mPhoneInterfaceManager.toggleRadioOnOffForSubscriber(1);
diff --git a/tests/src/com/android/phone/PhoneUtilsTest.java b/tests/src/com/android/phone/PhoneUtilsTest.java
index 3d7815c..2d3d065 100644
--- a/tests/src/com/android/phone/PhoneUtilsTest.java
+++ b/tests/src/com/android/phone/PhoneUtilsTest.java
@@ -30,15 +30,11 @@
import androidx.test.runner.AndroidJUnit4;
import com.android.TelephonyTestBase;
-import com.android.internal.telephony.GsmCdmaPhone;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public class PhoneUtilsTest extends TelephonyTestBase {
@@ -46,8 +42,6 @@
private SubscriptionManager mMockSubscriptionManager;
@Mock
private SubscriptionInfo mMockSubscriptionInfo;
- @Mock
- private GsmCdmaPhone mMockPhone;
private final int mPhoneAccountHandleIdInteger = 123;
private final String mPhoneAccountHandleIdString = "123";
@@ -58,12 +52,10 @@
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
+ super.setUp();
when(mMockSubscriptionManager.getActiveSubscriptionInfo(
eq(mPhoneAccountHandleIdInteger))).thenReturn(mMockSubscriptionInfo);
- when(mMockPhone.getSubId()).thenReturn(mPhoneAccountHandleIdInteger);
- Phone[] mPhones = new Phone[] {mMockPhone};
- replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
+ when(mPhone.getSubId()).thenReturn(mPhoneAccountHandleIdInteger);
}
@Test
@@ -74,7 +66,7 @@
@Test
public void testGetPhoneForPhoneAccountHandle() throws Exception {
- assertEquals(mMockPhone, PhoneUtils.getPhoneForPhoneAccountHandle(
+ assertEquals(mPhone, PhoneUtils.getPhoneForPhoneAccountHandle(
mPhoneAccountHandleTest));
}
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessControllerTest.java
index 678d069..27f3ef7 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessControllerTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/S2RangeSatelliteOnDeviceAccessControllerTest.java
@@ -16,20 +16,19 @@
package com.android.phone.satellite.accesscontrol;
-import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
-
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.doReturn;
+import android.annotation.Nullable;
+
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.telephony.flags.FeatureFlags;
-import com.android.storage.s2.S2LevelRange;
-
import com.android.telephony.sats2range.read.SatS2RangeFileFormat;
import com.android.telephony.sats2range.read.SuffixTableRange;
import com.android.telephony.sats2range.utils.TestUtils;
@@ -73,18 +72,42 @@
@Test
public void testSatelliteAccessControl_AllowedList() throws Exception {
- testSatelliteAccessControl(true);
+ testSatelliteAccessControl(true, null);
}
@Test
public void testSatelliteAccessControl_DisallowedList() throws Exception {
- testSatelliteAccessControl(false);
+ testSatelliteAccessControl(false, null);
}
- private void testSatelliteAccessControl(boolean isAllowedList) throws Exception {
+ @Test
+ public void testSatelliteAccessControl_AllowedList_validEntryValue() throws Exception {
+ testSatelliteAccessControl(true, 1);
+ }
+
+ @Test
+ public void testSatelliteAccessControl_DisallowedList_validEntryValue() {
+ assertThrows(IllegalArgumentException.class,
+ () -> testSatelliteAccessControl(false, 1));
+ }
+
+ private void testSatelliteAccessControl(boolean isAllowedList, @Nullable Integer entryValue)
+ throws Exception {
+ final int defaultEntryValue = -1;
+
+ if (!isAllowedList && entryValue != null) {
+ throw new IllegalArgumentException(
+ "isAllowedList must be true when entryValue is present.");
+ }
+
+ List<Integer> expectedConfigIds = List.of(1, 1, 3);
SatS2RangeFileFormat fileFormat = null;
try {
- fileFormat = createSatS2File(mFile, isAllowedList);
+ if (entryValue == null) {
+ fileFormat = createSatS2File(mFile, isAllowedList);
+ } else {
+ fileFormat = createSatS2FileWithEntryValue(mFile, isAllowedList, expectedConfigIds);
+ }
} catch (Exception ex) {
fail("Got unexpected exception in createSatS2File, ex=" + ex);
}
@@ -94,6 +117,10 @@
try {
accessController = SatelliteOnDeviceAccessController.create(mFile, mMockFeatureFlags);
int s2Level = accessController.getS2Level();
+ if (entryValue == null) {
+ expectedConfigIds = List.of(defaultEntryValue, defaultEntryValue,
+ defaultEntryValue);
+ }
// Verify an edge cell of range 1 not in the output file
S2CellId s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1000, 999));
@@ -111,12 +138,7 @@
assertTrue(isAllowed != isAllowedList);
Integer configId = accessController.getRegionalConfigIdForLocation(locationToken);
- if (isAllowedList) {
- assertNull(configId);
- } else {
- assertNotNull(configId);
- assertEquals(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, (int) configId);
- }
+ assertNull(configId);
// Verify cells in range1 present in the output file
for (int suffix = 1000; suffix < 2000; suffix++) {
@@ -130,12 +152,8 @@
assertTrue(isAllowed == isAllowedList);
configId = accessController.getRegionalConfigIdForLocation(locationToken);
- if (isAllowedList) {
- assertNotNull(configId);
- assertEquals(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, (int) configId);
- } else {
- assertNull(configId);
- }
+ assertNotNull(configId);
+ assertEquals((int) expectedConfigIds.get(0), (int) configId);
}
// Verify the middle cell not in the output file
@@ -147,12 +165,8 @@
assertTrue(isAllowed != isAllowedList);
configId = accessController.getRegionalConfigIdForLocation(locationToken);
- if (isAllowedList) {
- assertNull(configId);
- } else {
- assertNotNull(configId);
- assertEquals(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, (int) configId);
- }
+ assertNull(configId);
+
// Verify cells in range2 present in the output file
for (int suffix = 2001; suffix < 3000; suffix++) {
@@ -164,12 +178,8 @@
assertTrue(isAllowed == isAllowedList);
configId = accessController.getRegionalConfigIdForLocation(locationToken);
- if (isAllowedList) {
- assertNotNull(configId);
- assertEquals(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, (int) configId);
- } else {
- assertNull(configId);
- }
+ assertNotNull(configId);
+ assertEquals((int) expectedConfigIds.get(1), (int) configId);
}
// Verify an edge cell of range 2 not in the output file
@@ -181,12 +191,7 @@
assertTrue(isAllowed != isAllowedList);
configId = accessController.getRegionalConfigIdForLocation(locationToken);
- if (isAllowedList) {
- assertNull(configId);
- } else {
- assertNotNull(configId);
- assertEquals(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, (int) configId);
- }
+ assertNull(configId);
// Verify an edge cell of range 3 not in the output file
s2CellId = new S2CellId(TestUtils.createCellId(fileFormat, 1, 1001, 999));
@@ -197,12 +202,7 @@
assertTrue(isAllowed != isAllowedList);
configId = accessController.getRegionalConfigIdForLocation(locationToken);
- if (isAllowedList) {
- assertNull(configId);
- } else {
- assertNotNull(configId);
- assertEquals(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, (int) configId);
- }
+ assertNull(configId);
// Verify cells in range1 present in the output file
for (int suffix = 1000; suffix < 2000; suffix++) {
@@ -214,12 +214,8 @@
assertTrue(isAllowed == isAllowedList);
configId = accessController.getRegionalConfigIdForLocation(locationToken);
- if (isAllowedList) {
- assertNotNull(configId);
- assertEquals(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, (int) configId);
- } else {
- assertNull(configId);
- }
+ assertNotNull(configId);
+ assertEquals((int) expectedConfigIds.get(2), (int) configId);
}
// Verify an edge cell of range 3 not in the output file
@@ -231,12 +227,7 @@
assertTrue(isAllowed != isAllowedList);
configId = accessController.getRegionalConfigIdForLocation(locationToken);
- if (isAllowedList) {
- assertNull(configId);
- } else {
- assertNotNull(configId);
- assertEquals(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID, (int) configId);
- }
+ assertNull(configId);
} catch (Exception ex) {
fail("Unexpected exception when validating the output ex=" + ex);
@@ -247,8 +238,8 @@
}
}
- private SatS2RangeFileFormat createSatS2File(
- File file, boolean isAllowedList) throws Exception {
+ private SatS2RangeFileFormat createSatS2File(File file, boolean isAllowedList)
+ throws Exception {
SatS2RangeFileFormat fileFormat;
SuffixTableRange range1, range2, range3;
try (SatS2RangeFileWriter satS2RangeFileWriter = SatS2RangeFileWriter.open(
@@ -276,4 +267,38 @@
assertTrue(file.length() > 0);
return fileFormat;
}
+
+ private SatS2RangeFileFormat createSatS2FileWithEntryValue(
+ File file, boolean isAllowedList, List<Integer> entryValues) throws Exception {
+
+ SatS2RangeFileFormat fileFormat;
+ SuffixTableRange range1, range2, range3;
+ try (SatS2RangeFileWriter satS2RangeFileWriter = SatS2RangeFileWriter.open(
+ file, TestUtils.createS2RangeFileFormat(isAllowedList, 4, 1))) {
+ fileFormat = satS2RangeFileWriter.getFileFormat();
+
+ // Two ranges that share a prefix.
+ range1 = new SuffixTableRange(
+ TestUtils.createCellId(fileFormat, 1, 1000, 1000),
+ TestUtils.createCellId(fileFormat, 1, 1000, 2000),
+ entryValues.get(0));
+ range2 = new SuffixTableRange(
+ TestUtils.createCellId(fileFormat, 1, 1000, 2001),
+ TestUtils.createCellId(fileFormat, 1, 1000, 3000),
+ entryValues.get(1));
+ // This range has a different prefix, so will be in a different suffix table.
+ range3 = new SuffixTableRange(
+ TestUtils.createCellId(fileFormat, 1, 1001, 1000),
+ TestUtils.createCellId(fileFormat, 1, 1001, 2000),
+ entryValues.get(2));
+
+ List<SuffixTableRange> ranges = new ArrayList<>();
+ ranges.add(range1);
+ ranges.add(range2);
+ ranges.add(range3);
+ satS2RangeFileWriter.createSortedSuffixBlocks(ranges.iterator());
+ }
+ assertTrue(file.length() > 0);
+ return fileFormat;
+ }
}
diff --git a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
index c2f5979..5c18cc5 100644
--- a/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
+++ b/tests/src/com/android/phone/satellite/accesscontrol/SatelliteAccessControllerTest.java
@@ -17,6 +17,8 @@
package com.android.phone.satellite.accesscontrol;
import static android.location.LocationManager.MODE_CHANGED_ACTION;
+import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_ACCESS_CONFIGURATION;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_PROVISIONED;
import static android.telephony.satellite.SatelliteManager.KEY_SATELLITE_SUPPORTED;
@@ -29,15 +31,17 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.ALLOWED_STATE_CACHE_VALID_DURATION_NANOS;
-import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
-import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_COUNTRY_CODE_CHANGED;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.CMD_IS_SATELLITE_COMMUNICATION_ALLOWED;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_DELAY_MINUTES_BEFORE_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_REGIONAL_SATELLITE_CONFIG_ID;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_S2_LEVEL;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_THROTTLE_INTERVAL_FOR_LOCATION_QUERY_MINUTES;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_CONFIG_DATA_UPDATED;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_COUNTRY_CODE_CHANGED;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.EVENT_WAIT_FOR_CURRENT_LOCATION_TIMEOUT;
import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.GOOGLE_US_SAN_SAT_S2_FILE_NAME;
-import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.DEFAULT_MAX_RETRY_COUNT_FOR_VALIDATING_POSSIBLE_CHANGE_IN_ALLOWED_REGION;
+import static com.android.phone.satellite.accesscontrol.SatelliteAccessController.UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -51,6 +55,7 @@
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
@@ -83,13 +88,18 @@
import android.os.DropBoxManager;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
+import android.os.Parcel;
import android.os.ResultReceiver;
import android.os.UserHandle;
import android.telecom.TelecomManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.satellite.ISatelliteCommunicationAllowedStateCallback;
+import android.telephony.satellite.SatelliteAccessConfiguration;
+import android.telephony.satellite.SatelliteInfo;
import android.telephony.satellite.SatelliteManager;
import android.testing.TestableLooper;
import android.util.Log;
@@ -124,6 +134,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
@@ -188,15 +199,16 @@
@Mock
private SharedPreferences.Editor mMockSharedPreferencesEditor;
@Mock
- private Map<SatelliteOnDeviceAccessController.LocationToken, Boolean>
+ private Map<SatelliteOnDeviceAccessController.LocationToken, Integer>
mMockCachedAccessRestrictionMap;
@Mock
+ HashMap<Integer, SatelliteAccessConfiguration> mMockSatelliteAccessConfigMap;
+
+ @Mock
private Intent mMockLocationIntent;
@Mock
private Set<ResultReceiver> mMockSatelliteAllowResultReceivers;
@Mock
- private ResultReceiver mMockSatelliteSupportedResultReceiver;
- @Mock
private TelephonyManager mMockTelephonyManager;
@Mock
private PackageManager mMockPackageManager;
@@ -206,7 +218,11 @@
private NotificationManager mMockNotificationManager;
@Mock
private ApplicationInfo mMockApplicationInfo;
-
+ @Mock
+ private ResultReceiver mMockResultReceiver;
+ @Mock
+ private ConcurrentHashMap<IBinder, ISatelliteCommunicationAllowedStateCallback>
+ mSatelliteCommunicationAllowedStateCallbackMap;
private Looper mLooper;
private TestableLooper mTestableLooper;
@@ -241,6 +257,8 @@
private ArgumentCaptor<Integer> mResultCodeIntCaptor;
@Captor
private ArgumentCaptor<Bundle> mResultDataBundleCaptor;
+ @Captor
+ private ArgumentCaptor<ISatelliteCommunicationAllowedStateCallback> mAllowedStateCallbackCaptor;
private boolean mQueriedSatelliteAllowed = false;
private int mQueriedSatelliteAllowedResultCode = SATELLITE_RESULT_SUCCESS;
@@ -304,6 +322,7 @@
mMockCountryDetector);
when(mMockSatelliteController.getSatellitePhone()).thenReturn(mMockPhone);
when(mMockPhone.getSubId()).thenReturn(SubscriptionManager.getDefaultSubscriptionId());
+
when(mMockContext.getResources()).thenReturn(mMockResources);
when(mMockResources.getStringArray(
com.android.internal.R.array.config_oem_enabled_satellite_country_codes))
@@ -430,11 +449,11 @@
// and allowedState is false when the location is null and the cache is expired
mSatelliteAccessControllerUT.elapsedRealtimeNanos =
ALLOWED_STATE_CACHE_VALID_DURATION_NANOS + 1;
- Iterator<ResultReceiver> mockIterator = mock(Iterator.class);
- doReturn(mockIterator).when(mMockSatelliteAllowResultReceivers).iterator();
- doReturn(true, false).when(mockIterator).hasNext();
+ Iterator<ResultReceiver> mockResultReceiverIterator = mock(Iterator.class);
+ doReturn(mockResultReceiverIterator).when(mMockSatelliteAllowResultReceivers).iterator();
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
doNothing().when(mMockSatelliteAllowResultReceivers).clear();
- doReturn(mMockSatelliteSupportedResultReceiver).when(mockIterator).next();
+ doReturn(mMockResultReceiver).when(mockResultReceiverIterator).next();
replaceInstance(SatelliteAccessController.class, "mSatelliteAllowResultReceivers",
mSatelliteAccessControllerUT, mMockSatelliteAllowResultReceivers);
mSatelliteAccessControllerUT.setIsSatelliteCommunicationAllowedForCurrentLocationCache(
@@ -442,7 +461,7 @@
mSatelliteAccessControllerUT.setLocationRequestCancellationSignalAsNull(false);
sendCurrentLocationTimeoutEvent();
- verify(mMockSatelliteSupportedResultReceiver)
+ verify(mMockResultReceiver)
.send(mResultCodeIntCaptor.capture(), any());
assertEquals(Integer.valueOf(SATELLITE_RESULT_LOCATION_NOT_AVAILABLE),
mResultCodeIntCaptor.getValue());
@@ -514,6 +533,314 @@
.isSatelliteAccessAllowedForLocation(List.of(TEST_SATELLITE_COUNTRY_CODE_US)));
}
+
+ private void setSatelliteCommunicationAllowed() throws Exception {
+ when(mMockContext.getResources()).thenReturn(mMockResources);
+ when(mMockResources.getBoolean(
+ com.android.internal.R.bool.config_oem_enabled_satellite_access_allow))
+ .thenReturn(TEST_SATELLITE_ALLOW);
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ doReturn(true).when(mMockLocationManager).isLocationEnabled();
+ when(mMockSatelliteOnDeviceAccessController.getRegionalConfigIdForLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class)))
+ .thenReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID);
+ replaceInstance(SatelliteAccessController.class, "mCachedAccessRestrictionMap",
+ mSatelliteAccessControllerUT, mMockCachedAccessRestrictionMap);
+ doReturn(true).when(mMockCachedAccessRestrictionMap).containsKey(any());
+ doReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID)
+ .when(mMockCachedAccessRestrictionMap).get(any());
+ }
+
+ @Test
+ public void testRequestSatelliteAccessConfigurationForCurrentLocation() throws Exception {
+ // setup result receiver and satellite access configuration data
+ ResultReceiver mockResultReceiver = mock(ResultReceiver.class);
+ ArgumentCaptor<Integer> resultCodeCaptor = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ SatelliteAccessConfiguration satelliteAccessConfig = getSatelliteAccessConfiguration();
+
+ // setup satellite communication allwed state as true
+ setSatelliteCommunicationAllowed();
+
+ // setup map data of location and configId.
+ replaceInstance(SatelliteAccessController.class, "mSatelliteAccessConfigMap",
+ mSatelliteAccessControllerUT, mMockSatelliteAccessConfigMap);
+ doReturn(satelliteAccessConfig).when(mMockSatelliteAccessConfigMap).get(anyInt());
+ doReturn(null).when(mMockSatelliteAccessConfigMap).get(eq(null));
+ doReturn(null).when(mMockSatelliteAccessConfigMap)
+ .get(eq(UNKNOWN_REGIONAL_SATELLITE_CONFIG_ID));
+
+ // setup callback
+ ISatelliteCommunicationAllowedStateCallback mockSatelliteAllowedStateCallback = mock(
+ ISatelliteCommunicationAllowedStateCallback.class);
+ ArgumentCaptor<SatelliteAccessConfiguration> satelliteAccessConfigurationCaptor =
+ ArgumentCaptor.forClass(SatelliteAccessConfiguration.class);
+
+ when(mSatelliteCommunicationAllowedStateCallbackMap.values())
+ .thenReturn(List.of(mockSatelliteAllowedStateCallback));
+ replaceInstance(SatelliteAccessController.class,
+ "mSatelliteCommunicationAllowedStateChangedListeners", mSatelliteAccessControllerUT,
+ mSatelliteCommunicationAllowedStateCallbackMap);
+
+ // Test when the featureFlags.carrierRoamingNbIotNtn() is false
+ doReturn(false).when(mMockFeatureFlags).carrierRoamingNbIotNtn();
+
+ clearInvocations(mockResultReceiver);
+ mSatelliteAccessControllerUT
+ .requestSatelliteAccessConfigurationForCurrentLocation(mockResultReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mockResultReceiver, times(1)).send(resultCodeCaptor.capture(),
+ bundleCaptor.capture());
+ assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, (int) resultCodeCaptor.getValue());
+ assertNull(bundleCaptor.getValue());
+ verify(mockSatelliteAllowedStateCallback, never())
+ .onSatelliteAccessConfigurationChanged(any());
+
+ doReturn(true).when(mMockFeatureFlags).carrierRoamingNbIotNtn();
+
+ // satellite communication allowed state is enabled and
+ // regional config id is DEFAULT_REGIONAL_SATELLITE_CONFIG_ID.
+ clearInvocations(mockResultReceiver);
+ clearInvocations(mockSatelliteAllowedStateCallback);
+ mSatelliteAccessControllerUT
+ .requestSatelliteAccessConfigurationForCurrentLocation(mockResultReceiver);
+ mTestableLooper.processAllMessages();
+ verify(mockResultReceiver, times(1)).send(resultCodeCaptor.capture(),
+ bundleCaptor.capture());
+ assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS, (int) resultCodeCaptor.getValue());
+ assertTrue(bundleCaptor.getValue().containsKey(KEY_SATELLITE_ACCESS_CONFIGURATION));
+ assertSame(bundleCaptor.getValue().getParcelable(KEY_SATELLITE_ACCESS_CONFIGURATION,
+ SatelliteAccessConfiguration.class), satelliteAccessConfig);
+ verify(mockSatelliteAllowedStateCallback, times(1))
+ .onSatelliteAccessConfigurationChanged(
+ satelliteAccessConfigurationCaptor.capture());
+ assertEquals(satelliteAccessConfigurationCaptor.getValue(), satelliteAccessConfig);
+
+ // satellite communication allowed state is disabled and
+ // regional config id is null.
+ clearInvocations(mockResultReceiver);
+ clearInvocations(mockSatelliteAllowedStateCallback);
+ when(mMockCachedAccessRestrictionMap.get(any())).thenReturn(null);
+ mSatelliteAccessControllerUT
+ .requestSatelliteAccessConfigurationForCurrentLocation(mockResultReceiver);
+ mTestableLooper.processAllMessages();
+
+ verify(mockResultReceiver, times(1)).send(resultCodeCaptor.capture(),
+ bundleCaptor.capture());
+ assertEquals(SATELLITE_RESULT_SUCCESS, (int) resultCodeCaptor.getValue());
+ assertTrue(bundleCaptor.getValue().containsKey(KEY_SATELLITE_ACCESS_CONFIGURATION));
+ assertNull(bundleCaptor.getValue().getParcelable(KEY_SATELLITE_ACCESS_CONFIGURATION,
+ SatelliteAccessConfiguration.class));
+ verify(mockSatelliteAllowedStateCallback, times(1))
+ .onSatelliteAccessConfigurationChanged(
+ satelliteAccessConfigurationCaptor.capture());
+ assertNull(satelliteAccessConfigurationCaptor.getValue());
+ }
+
+ private SatelliteAccessConfiguration getSatelliteAccessConfiguration() {
+ Parcel satelliteAccessconfigParcel = Parcel.obtain();
+
+ List<SatelliteInfo> satelliteInfoList = new ArrayList<>();
+ satelliteInfoList.add(mock(SatelliteInfo.class));
+ satelliteAccessconfigParcel.writeTypedList(satelliteInfoList);
+
+ List<Integer> tagIds = new ArrayList<>(List.of(1, 2));
+ satelliteAccessconfigParcel.writeList(tagIds);
+
+ return new SatelliteAccessConfiguration(satelliteAccessconfigParcel);
+ }
+
+ @Test
+ public void testRegisterForCommunicationAllowedStateChanged() throws Exception {
+ ISatelliteCommunicationAllowedStateCallback mockSatelliteAllowedStateCallback = mock(
+ ISatelliteCommunicationAllowedStateCallback.class);
+ doReturn(true).when(mSatelliteCommunicationAllowedStateCallbackMap)
+ .put(any(IBinder.class), any(ISatelliteCommunicationAllowedStateCallback.class));
+ replaceInstance(SatelliteAccessController.class,
+ "mSatelliteCommunicationAllowedStateChangedListeners", mSatelliteAccessControllerUT,
+ mSatelliteCommunicationAllowedStateCallbackMap);
+
+ doReturn(false).when(mMockFeatureFlags).oemEnabledSatelliteFlag();
+ int result = mSatelliteAccessControllerUT.registerForCommunicationAllowedStateChanged(
+ DEFAULT_SUBSCRIPTION_ID, mockSatelliteAllowedStateCallback);
+ mTestableLooper.processAllMessages();
+ assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, result);
+ verify(mockSatelliteAllowedStateCallback, never())
+ .onSatelliteCommunicationAllowedStateChanged(anyBoolean());
+ verify(mockSatelliteAllowedStateCallback, never())
+ .onSatelliteAccessConfigurationChanged(any(SatelliteAccessConfiguration.class));
+
+ doReturn(true).when(mMockFeatureFlags).oemEnabledSatelliteFlag();
+ result = mSatelliteAccessControllerUT.registerForCommunicationAllowedStateChanged(
+ DEFAULT_SUBSCRIPTION_ID, mockSatelliteAllowedStateCallback);
+ mTestableLooper.processAllMessages();
+ assertEquals(SATELLITE_RESULT_SUCCESS, result);
+ verify(mockSatelliteAllowedStateCallback, times(1))
+ .onSatelliteCommunicationAllowedStateChanged(anyBoolean());
+ verify(mockSatelliteAllowedStateCallback, times(1))
+ .onSatelliteAccessConfigurationChanged(
+ nullable(SatelliteAccessConfiguration.class));
+ }
+
+ @Test
+ public void testNotifyRegionalSatelliteConfigurationChanged() throws Exception {
+ // setup test
+ ISatelliteCommunicationAllowedStateCallback mockSatelliteAllowedStateCallback = mock(
+ ISatelliteCommunicationAllowedStateCallback.class);
+ ArgumentCaptor<SatelliteAccessConfiguration> satelliteAccessConfigurationCaptor =
+ ArgumentCaptor.forClass(SatelliteAccessConfiguration.class);
+
+ when(mSatelliteCommunicationAllowedStateCallbackMap.values())
+ .thenReturn(List.of(mockSatelliteAllowedStateCallback));
+ replaceInstance(SatelliteAccessController.class,
+ "mSatelliteCommunicationAllowedStateChangedListeners", mSatelliteAccessControllerUT,
+ mSatelliteCommunicationAllowedStateCallbackMap);
+
+ // register callback
+ mSatelliteAccessControllerUT.registerForCommunicationAllowedStateChanged(
+ DEFAULT_SUBSCRIPTION_ID, mockSatelliteAllowedStateCallback);
+
+ // verify if the callback is
+ // the same instance from onmSatelliteCommunicationAllowedStateCallbackMap
+ verify(mSatelliteCommunicationAllowedStateCallbackMap).put(any(),
+ mAllowedStateCallbackCaptor.capture());
+ assertSame(mockSatelliteAllowedStateCallback, mAllowedStateCallbackCaptor.getValue());
+
+ // create SatelliteAccessConfiguration data for this test
+ SatelliteAccessConfiguration satelliteAccessConfig = getSatelliteAccessConfiguration();
+
+ // trigger notifyRegionalSatelliteConfigurationChanged
+ mSatelliteAccessControllerUT
+ .notifyRegionalSatelliteConfigurationChanged(satelliteAccessConfig);
+
+ // verify if the satelliteAccessConfig is the same instance with the captured one.
+ verify(mockSatelliteAllowedStateCallback).onSatelliteAccessConfigurationChanged(
+ satelliteAccessConfigurationCaptor.capture());
+ assertSame(satelliteAccessConfig, satelliteAccessConfigurationCaptor.getValue());
+ }
+
+ @Test
+ public void testCheckSatelliteAccessRestrictionForLocation() throws Exception {
+ // Setup
+ logd("testCheckSatelliteAccessRestrictionForLocation : setup");
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ ArgumentCaptor<Integer> regionalConfigIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ replaceInstance(SatelliteAccessController.class, "mS2Level",
+ mSatelliteAccessControllerUT, DEFAULT_S2_LEVEL);
+ Iterator<ResultReceiver> mockResultReceiverIterator = mock(Iterator.class);
+ mSatelliteAccessControllerUT.setRegionalConfigId(null);
+
+ doReturn(mockResultReceiverIterator).when(mMockSatelliteAllowResultReceivers).iterator();
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+ doNothing().when(mMockSatelliteAllowResultReceivers).clear();
+ doReturn(mMockResultReceiver).when(mockResultReceiverIterator).next();
+ replaceInstance(SatelliteAccessController.class, "mSatelliteAllowResultReceivers",
+ mSatelliteAccessControllerUT, mMockSatelliteAllowResultReceivers);
+ replaceInstance(SatelliteAccessController.class, "mCachedAccessRestrictionMap",
+ mSatelliteAccessControllerUT, mMockCachedAccessRestrictionMap);
+
+ // when mMockCachedAccessRestrictionMap is hit and has DEFAULT_REGIONAL_SATELLITE_CONFIG_ID,
+ // verify belows
+ // - the bundle data of KEY_SATELLITE_COMMUNICATION_ALLOWED is true
+ // - the newRegionalConfigId is the same as DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+ // - the regionalConfigId is the same as DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+ logd("testCheckSatelliteAccessRestrictionForLocation : case 1");
+ clearInvocations(mMockSatelliteOnDeviceAccessController);
+ clearInvocations(mMockCachedAccessRestrictionMap);
+
+ doReturn(true).when(mMockCachedAccessRestrictionMap)
+ .containsKey(any(SatelliteOnDeviceAccessController.LocationToken.class));
+ doReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID).when(mMockCachedAccessRestrictionMap)
+ .get(any(SatelliteOnDeviceAccessController.LocationToken.class));
+
+ mSatelliteAccessControllerUT.checkSatelliteAccessRestrictionForLocation(mMockLocation0);
+ verify(mMockResultReceiver, times(1))
+ .send(mResultCodeIntCaptor.capture(), bundleCaptor.capture());
+ verify(mMockSatelliteOnDeviceAccessController, never()).getRegionalConfigIdForLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class));
+ assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
+ assertTrue(bundleCaptor.getValue().getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED));
+ assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+ mSatelliteAccessControllerUT.getNewRegionalConfigId());
+ assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+ mSatelliteAccessControllerUT.getRegionalConfigId());
+
+ // when mMockCachedAccessRestrictionMap is not hit and regionalConfigId is null
+ // verify belows
+ // - the bundle data of KEY_SATELLITE_COMMUNICATION_ALLOWED is false
+ // - the regionalConfigId is null
+ logd("testCheckSatelliteAccessRestrictionForLocation : case 2");
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ doReturn(false).when(mMockCachedAccessRestrictionMap)
+ .containsKey(any(SatelliteOnDeviceAccessController.LocationToken.class));
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+ when(mMockSatelliteOnDeviceAccessController.getRegionalConfigIdForLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class)))
+ .thenReturn(null);
+
+ mSatelliteAccessControllerUT.checkSatelliteAccessRestrictionForLocation(mMockLocation0);
+ verify(mMockResultReceiver, times(2))
+ .send(mResultCodeIntCaptor.capture(), bundleCaptor.capture());
+ assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
+ assertFalse(bundleCaptor.getValue().getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED));
+ verify(mMockCachedAccessRestrictionMap, times(1))
+ .put(any(), regionalConfigIdCaptor.capture());
+ assertNull(regionalConfigIdCaptor.getValue());
+ assertNull(mSatelliteAccessControllerUT.getNewRegionalConfigId());
+ assertNull(mSatelliteAccessControllerUT.getRegionalConfigId());
+
+ // when mMockCachedAccessRestrictionMap is not hit and
+ // regionalConfigId is DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+ // verify belows
+ // - the bundle data of KEY_SATELLITE_COMMUNICATION_ALLOWED is true
+ // - the regionalConfigId is DEFAULT_REGIONAL_SATELLITE_CONFIG_ID
+ logd("testCheckSatelliteAccessRestrictionForLocation : case 3");
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockSatelliteOnDeviceAccessController.getRegionalConfigIdForLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class)))
+ .thenReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID);
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+
+ mSatelliteAccessControllerUT.checkSatelliteAccessRestrictionForLocation(mMockLocation0);
+ verify(mMockResultReceiver, times(3))
+ .send(mResultCodeIntCaptor.capture(), bundleCaptor.capture());
+ assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
+ assertTrue(bundleCaptor.getValue().getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED));
+ verify(mMockCachedAccessRestrictionMap, times(1))
+ .put(any(), regionalConfigIdCaptor.capture());
+
+ assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+ regionalConfigIdCaptor.getValue());
+ assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+ mSatelliteAccessControllerUT.getNewRegionalConfigId());
+ assertEquals(Integer.valueOf(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID),
+ mSatelliteAccessControllerUT.getRegionalConfigId());
+
+
+ // when mMockCachedAccessRestrictionMap is not hit and regionalConfigId is null
+ // verify belows
+ // - the bundle data of KEY_SATELLITE_COMMUNICATION_ALLOWED is false
+ // - the regionalConfigId is null
+ logd("testCheckSatelliteAccessRestrictionForLocation : case 4");
+ clearInvocations(mMockCachedAccessRestrictionMap);
+ when(mMockSatelliteOnDeviceAccessController.getRegionalConfigIdForLocation(
+ any(SatelliteOnDeviceAccessController.LocationToken.class)))
+ .thenReturn(null);
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+
+ mSatelliteAccessControllerUT.checkSatelliteAccessRestrictionForLocation(mMockLocation0);
+ verify(mMockResultReceiver, times(4))
+ .send(mResultCodeIntCaptor.capture(), bundleCaptor.capture());
+ assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
+ assertFalse(bundleCaptor.getValue().getBoolean(KEY_SATELLITE_COMMUNICATION_ALLOWED));
+ verify(mMockCachedAccessRestrictionMap, times(1))
+ .put(any(), regionalConfigIdCaptor.capture());
+ assertNull(regionalConfigIdCaptor.getValue());
+ assertNull(mSatelliteAccessControllerUT.getNewRegionalConfigId());
+ assertNull(mSatelliteAccessControllerUT.getRegionalConfigId());
+ }
+
@Test
public void testIsRegionDisallowed() throws Exception {
// setup to make the return value of mQueriedSatelliteAllowed 'true'
@@ -531,7 +858,8 @@
replaceInstance(SatelliteAccessController.class, "mCachedAccessRestrictionMap",
mSatelliteAccessControllerUT, mMockCachedAccessRestrictionMap);
doReturn(true).when(mMockCachedAccessRestrictionMap).containsKey(any());
- doReturn(true).when(mMockCachedAccessRestrictionMap).get(any());
+ doReturn(DEFAULT_REGIONAL_SATELLITE_CONFIG_ID)
+ .when(mMockCachedAccessRestrictionMap).get(any());
// get allowed country codes EMPTY from resources
when(mMockResources.getStringArray(
@@ -946,7 +1274,6 @@
// current time is greater than the location query throttle interval
// verify mMockLocationManager.getCurrentLocation() is invoked
// verify time(mLastLocationQueryForPossibleChangeInAllowedRegionTimeNanos) is updated
- logd("youngcha 1");
clearInvocations(mMockLocationManager);
mSatelliteAccessControllerUT.setLocationRequestCancellationSignalAsNull(true);
mSatelliteAccessControllerUT.elapsedRealtimeNanos =
@@ -1254,10 +1581,10 @@
@Test
public void testHandleIsSatelliteSupportedResult() throws Exception {
// Setup for this test case
- Iterator<ResultReceiver> mockIterator = mock(Iterator.class);
- doReturn(mockIterator).when(mMockSatelliteAllowResultReceivers).iterator();
- doReturn(true, false).when(mockIterator).hasNext();
- doReturn(mMockSatelliteSupportedResultReceiver).when(mockIterator).next();
+ Iterator<ResultReceiver> mockResultReceiverIterator = mock(Iterator.class);
+ doReturn(mockResultReceiverIterator).when(mMockSatelliteAllowResultReceivers).iterator();
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+ doReturn(mMockResultReceiver).when(mockResultReceiverIterator).next();
replaceInstance(SatelliteAccessController.class, "mSatelliteAllowResultReceivers",
mSatelliteAccessControllerUT, mMockSatelliteAllowResultReceivers);
@@ -1266,10 +1593,10 @@
// case that resultCode is not SATELLITE_RESULT_SUCCESS
int resultCode = SATELLITE_RESULT_ERROR;
Bundle bundle = new Bundle();
- doReturn(true, false).when(mockIterator).hasNext();
- clearInvocations(mMockSatelliteSupportedResultReceiver);
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+ clearInvocations(mMockResultReceiver);
mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
- verify(mMockSatelliteSupportedResultReceiver)
+ verify(mMockResultReceiver)
.send(mResultCodeIntCaptor.capture(), any());
assertEquals(Integer.valueOf(SATELLITE_RESULT_ERROR), mResultCodeIntCaptor.getValue());
@@ -1277,20 +1604,19 @@
// verify that the resultCode is delivered as it were
resultCode = SATELLITE_RESULT_SUCCESS;
bundle.putBoolean(KEY_SATELLITE_PROVISIONED, false);
- doReturn(true, false).when(mockIterator).hasNext();
- clearInvocations(mMockSatelliteSupportedResultReceiver);
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+ clearInvocations(mMockResultReceiver);
mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
- verify(mMockSatelliteSupportedResultReceiver)
- .send(mResultCodeIntCaptor.capture(), any());
+ verify(mMockResultReceiver).send(mResultCodeIntCaptor.capture(), any());
assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS), mResultCodeIntCaptor.getValue());
// case KEY_SATELLITE_SUPPORTED is false
// verify SATELLITE_RESULT_NOT_SUPPORTED is captured
bundle.putBoolean(KEY_SATELLITE_SUPPORTED, false);
- doReturn(true, false).when(mockIterator).hasNext();
- clearInvocations(mMockSatelliteSupportedResultReceiver);
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+ clearInvocations(mMockResultReceiver);
mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
- verify(mMockSatelliteSupportedResultReceiver)
+ verify(mMockResultReceiver)
.send(mResultCodeIntCaptor.capture(), mResultDataBundleCaptor.capture());
assertEquals(Integer.valueOf(SATELLITE_RESULT_NOT_SUPPORTED),
mResultCodeIntCaptor.getValue());
@@ -1302,10 +1628,10 @@
bundle.putBoolean(KEY_SATELLITE_SUPPORTED, true);
when(mMockCountryDetector.getCurrentNetworkCountryIso())
.thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_KR));
- doReturn(true, false).when(mockIterator).hasNext();
- clearInvocations(mMockSatelliteSupportedResultReceiver);
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+ clearInvocations(mMockResultReceiver);
mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
- verify(mMockSatelliteSupportedResultReceiver)
+ verify(mMockResultReceiver)
.send(mResultCodeIntCaptor.capture(), mResultDataBundleCaptor.capture());
assertEquals(Integer.valueOf(SATELLITE_RESULT_SUCCESS),
mResultCodeIntCaptor.getValue());
@@ -1317,10 +1643,10 @@
when(mMockCountryDetector.getCurrentNetworkCountryIso())
.thenReturn(List.of(TEST_SATELLITE_COUNTRY_CODE_US));
doReturn(false).when(mMockLocationManager).isLocationEnabled();
- doReturn(true, false).when(mockIterator).hasNext();
- clearInvocations(mMockSatelliteSupportedResultReceiver);
+ doReturn(true, false).when(mockResultReceiverIterator).hasNext();
+ clearInvocations(mMockResultReceiver);
mSatelliteAccessControllerUT.handleIsSatelliteSupportedResult(resultCode, bundle);
- verify(mMockSatelliteSupportedResultReceiver)
+ verify(mMockResultReceiver)
.send(mResultCodeIntCaptor.capture(), mResultDataBundleCaptor.capture());
assertEquals(Integer.valueOf(SATELLITE_RESULT_LOCATION_DISABLED),
mResultCodeIntCaptor.getValue());
@@ -1367,7 +1693,7 @@
private void sendSatelliteCommunicationAllowedEvent() {
Pair<Integer, ResultReceiver> requestPair =
- new Pair<>(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ new Pair<>(DEFAULT_SUBSCRIPTION_ID,
mSatelliteAccessControllerUT.getResultReceiverCurrentLocation());
Message msg = mSatelliteAccessControllerUT.obtainMessage(
CMD_IS_SATELLITE_COMMUNICATION_ALLOWED);
@@ -1567,5 +1893,25 @@
return mCurrentSatelliteAllowedState;
}
}
+
+ @Nullable
+ public Integer getRegionalConfigId() {
+ synchronized (mLock) {
+ return mRegionalConfigId;
+ }
+ }
+
+ @Nullable
+ public Integer getNewRegionalConfigId() {
+ synchronized (mLock) {
+ return mNewRegionalConfigId;
+ }
+ }
+
+ public void setRegionalConfigId(@Nullable Integer regionalConfigId) {
+ synchronized (mLock) {
+ mRegionalConfigId = regionalConfigId;
+ }
+ }
}
}
diff --git a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
index 11f982e..9f8a733 100644
--- a/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
+++ b/tests/src/com/android/phone/satellite/entitlement/SatelliteEntitlementControllerTest.java
@@ -20,6 +20,7 @@
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 org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -46,18 +47,16 @@
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.AndroidTestingRunner;
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;
@@ -74,7 +73,6 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -87,7 +85,8 @@
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
-@RunWith(AndroidJUnit4.class)
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
public class SatelliteEntitlementControllerTest extends TelephonyTestBase {
private static final String TAG = "SatelliteEntitlementControllerTest";
private static final int SUB_ID = 0;
@@ -101,10 +100,8 @@
private static final int CMD_RETRY_QUERY_ENTITLEMENT = 2;
private static final int CMD_SIM_REFRESH = 3;
private static final int MAX_RETRY_COUNT = 5;
- @Mock
- CarrierConfigManager mCarrierConfigManager;
- @Mock
- ConnectivityManager mConnectivityManager;
+ @Mock CarrierConfigManager mCarrierConfigManager;
+ @Mock ConnectivityManager mConnectivityManager;
@Mock Network mNetwork;
@Mock TelephonyManager mTelephonyManager;
@Mock SubscriptionManagerService mMockSubscriptionManagerService;
@@ -118,10 +115,10 @@
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);
@@ -129,14 +126,8 @@
replaceInstance(PhoneFactory.class, "sMetricsCollector", null, mMetricsCollector);
doReturn(Mockito.mock(PersistAtomsStorage.class)).when(mMetricsCollector).getAtomsStorage();
- HandlerThread handlerThread = new HandlerThread("SatelliteEntitlementController");
- handlerThread.start();
- mHandler = new Handler(handlerThread.getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- }
- };
- mTestableLooper = new TestableLooper(mHandler.getLooper());
+ mTestableLooper = TestableLooper.get(this);
+ mHandler = new Handler(mTestableLooper.getLooper());
doReturn(Context.TELEPHONY_SERVICE).when(mContext).getSystemServiceName(
TelephonyManager.class);
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
@@ -167,9 +158,8 @@
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);
+ mSatelliteEntitlementController = spy(new TestSatelliteEntitlementController(mContext,
+ mTestableLooper.getLooper(), mSatelliteEntitlementApi));
doReturn(mSatelliteEntitlementResult).when(
mSatelliteEntitlementApi).checkEntitlementStatus();
}
@@ -181,7 +171,6 @@
@Test
public void testShouldStartQueryEntitlement() throws Exception {
- logd("testShouldStartQueryEntitlement");
doReturn(ACTIVE_SUB_ID).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
// Verify don't start the query when KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL is false.
@@ -256,7 +245,6 @@
@Test
public void testCheckSatelliteEntitlementStatus() throws Exception {
- logd("testCheckSatelliteEntitlementStatus");
setIsQueryAvailableTrue();
// Verify don't call the checkSatelliteEntitlementStatus when getActiveSubIdList is empty.
doReturn(new int[]{}).when(mMockSubscriptionManagerService).getActiveSubIdList(true);
@@ -347,7 +335,6 @@
@Test
public void testCheckSatelliteEntitlementStatusWhenInternetConnected() throws Exception {
- logd("testCheckSatelliteEntitlementStatusWhenInternetConnected");
ConnectivityManager.NetworkCallback networkCallback =
(ConnectivityManager.NetworkCallback) getValue("mNetworkCallback");
Network mockNetwork = mock(Network.class);
@@ -369,7 +356,6 @@
@Test
public void testCheckSatelliteEntitlementStatusWhenCarrierConfigChanged() throws Exception {
- logd("testCheckSatelliteEntitlementStatusWhenCarrierConfigChanged");
// Verify the called the checkSatelliteEntitlementStatus when CarrierConfigChanged
// occurred and Internet is connected.
setInternetConnected(true);
@@ -386,7 +372,6 @@
@Test
public void testCheckWhenStartCmdIsReceivedDuringRetry() throws Exception {
- logd("testCheckWhenStartCmdIsReceivedDuringRetry");
// Verify that start cmd is ignored and retry is performed up to 5 times when start cmd
// occurs during retries.
setIsQueryAvailableTrue();
@@ -400,47 +385,47 @@
verify(mSatelliteEntitlementApi, times(1)).checkEntitlementStatus();
// Verify that the retry count is 0 after receiving a 503 with retry-after header in
// response.
- assertTrue(retryCountPerSub.getOrDefault(SUB_ID, 0) == 0);
+ assertEquals(0, retryCountPerSub.getOrDefault(SUB_ID, 0).longValue());
// Verify that the retry count is 1 for the second query when receiving a 503 with
// retry-after header in response.
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 1);
+ assertEquals(1, retryCountPerSub.get(SUB_ID).longValue());
// Verify that the retry count is 2 for the third query when receiving a 503 with
// retry-after header in response.
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(3)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 2);
+ assertEquals(2, retryCountPerSub.get(SUB_ID).longValue());
// Verify that start CMD is ignored during retries.
sendMessage(CMD_START_QUERY_ENTITLEMENT, SUB_ID);
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(3)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 2);
+ assertEquals(2, retryCountPerSub.get(SUB_ID).longValue());
// Verify that the retry count is 3 for the forth query when receiving a 503 with
// retry-after header in response.
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(4)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 3);
+ assertEquals(3, retryCountPerSub.get(SUB_ID).longValue());
// Verify that the retry count is 4 for the fifth query when receiving a 503 with
// retry-after header in response.
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(5)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 4);
+ assertEquals(4, retryCountPerSub.get(SUB_ID).longValue());
// Verify that start CMD is ignored during retries.
sendMessage(CMD_START_QUERY_ENTITLEMENT, SUB_ID);
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(5)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 4);
+ assertEquals(4, retryCountPerSub.get(SUB_ID).longValue());
// Verify that the retry count is 5 for the sixth query when receiving a 503 with
// retry-after header in response.
@@ -470,7 +455,6 @@
@Test
public void testCheckAfterInternetConnectionChangedDuringRetry() throws Exception {
- logd("testCheckAfterInternetConnectionChangedDuringRetry");
// Verify that the retry count is maintained even when internet connection is lost and
// connected during retries, and that up to 5 retries are performed.
setIsQueryAvailableTrue();
@@ -484,48 +468,48 @@
verify(mSatelliteEntitlementApi, times(1)).checkEntitlementStatus();
// Verify that the retry count is 0 after receiving a 503 with retry-after header in
// response.
- assertTrue(retryCountPerSub.getOrDefault(SUB_ID, 0) == 0);
+ assertEquals(0, retryCountPerSub.getOrDefault(SUB_ID, 0).longValue());
// Verify that the retry count is 1 for the second query when receiving a 503 with
// retry-after header in response.
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 1);
+ assertEquals(1, retryCountPerSub.get(SUB_ID).longValue());
// Verify that no query is executed and the retry count does not increase when internet
// connection is lost during the second retry.
setInternetConnected(false);
- mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
+ mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(2));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 1);
+ assertEquals(1, retryCountPerSub.get(SUB_ID).longValue());
// Verify that the query is started when internet connection is restored and that the
// retry count does not increase.
setInternetConnected(true);
- logd("internet connected again");
+ Log.d(TAG, "internet connected again");
sendMessage(CMD_START_QUERY_ENTITLEMENT, SUB_ID);
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(3)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 1);
+ assertEquals(1, retryCountPerSub.get(SUB_ID).longValue());
// Verify that the retry count is increases after received a 503 with retry-after header
// in response.
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(4)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 2);
+ assertEquals(2, retryCountPerSub.get(SUB_ID).longValue());
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(5)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 3);
+ assertEquals(3, retryCountPerSub.get(SUB_ID).longValue());
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(6)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 4);
+ assertEquals(4, retryCountPerSub.get(SUB_ID).longValue());
mTestableLooper.moveTimeForward(TimeUnit.SECONDS.toMillis(1));
mTestableLooper.processAllMessages();
@@ -553,7 +537,6 @@
@Test
public void testStartQueryEntitlementStatus_error500() throws Exception {
- logd("testStartQueryEntitlementStatus_error500");
setIsQueryAvailableTrue();
Map<Integer, Integer> retryCountPerSub =
(Map<Integer, Integer>) getValue("mRetryCountPerSub");
@@ -569,7 +552,6 @@
@Test
public void testStartQueryEntitlementStatus_error503_retrySuccess() throws Exception {
- logd("testStartQueryEntitlementStatus_error503_retrySuccess");
setIsQueryAvailableTrue();
set503RetryAfterResponse();
Map<Integer, Integer> retryCountPerSub =
@@ -597,7 +579,6 @@
@Test
public void testStartQueryEntitlementStatus_otherError_retrySuccess() throws Exception {
- logd("testStartQueryEntitlementStatus_otherError_retrySuccess");
setIsQueryAvailableTrue();
Map<Integer, Integer> retryCountPerSub =
(Map<Integer, Integer>) getValue("mRetryCountPerSub");
@@ -622,7 +603,7 @@
sendMessage(CMD_RETRY_QUERY_ENTITLEMENT, SUB_ID);
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(2)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 1);
+ assertEquals(1, retryCountPerSub.get(SUB_ID).longValue());
// Verify don't call the onSatelliteEntitlementStatusUpdated.
verify(mSatelliteController, never()).onSatelliteEntitlementStatusUpdated(anyInt(),
anyBoolean(), anyList(), anyList(), any());
@@ -637,14 +618,13 @@
sendMessage(CMD_RETRY_QUERY_ENTITLEMENT, SUB_ID);
mTestableLooper.processAllMessages();
verify(mSatelliteEntitlementApi, times(3)).checkEntitlementStatus();
- assertTrue(retryCountPerSub.get(SUB_ID) == 1);
+ assertEquals(1, retryCountPerSub.get(SUB_ID).longValue());
verify(mSatelliteController).onSatelliteEntitlementStatusUpdated(eq(SUB_ID), eq(true),
eq(PLMN_ALLOWED_LIST), eq(PLMN_BARRED_LIST), any());
}
@Test
public void testSatelliteEntitlementSupportedChangedFromSupportToNotSupport() throws Exception {
- logd("testSatelliteEntitlementSupportedChangedFromSupportToNotSupport");
setIsQueryAvailableTrue();
// KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL changed from Support(entitlement status
@@ -699,7 +679,6 @@
@Test
public void testStartQueryEntitlementStatus_refreshStatus() throws Exception {
- logd("testStartQueryEntitlementStatus_refreshStatus");
setIsQueryAvailableTrue();
mCarrierConfigBundle.putInt(
CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT, 1);
@@ -729,7 +708,6 @@
@Test
public void testStartQueryEntitlementStatus_internetDisconnectedAndConnectedAgain()
throws Exception {
- logd("testStartQueryEntitlementStatus_internetDisconnectedAndConnectedAgain");
setIsQueryAvailableTrue();
// Verify the query does not start if there is no internet connection.
@@ -757,7 +735,6 @@
@Test
public void testStartQueryEntitlementStatus_error503_error500() throws Exception {
- logd("testStartQueryEntitlementStatus_error503_error500");
setIsQueryAvailableTrue();
set503RetryAfterResponse();
@@ -782,7 +759,6 @@
@Test
public void testStartQueryEntitlementStatus_error503_otherError() throws Exception {
- logd("testStartQueryEntitlementStatus_error503_otherError");
setIsQueryAvailableTrue();
set503RetryAfterResponse();
@@ -820,7 +796,6 @@
@Test
public void testStartQueryEntitlementStatus_AfterSimRefresh() throws Exception {
- logd("testStartQueryEntitlementStatus_AfterSimRefresh");
setIsQueryAvailableTrue();
// Verify the first query complete.
@@ -959,12 +934,8 @@
@Override
public SatelliteEntitlementApi getSatelliteEntitlementApi(int subId) {
- logd("getSatelliteEntitlementApi");
+ Log.d(TAG, "getSatelliteEntitlementApi");
return mInjectSatelliteEntitlementApi;
}
}
-
- private static void logd(String log) {
- Log.d(TAG, log);
- }
}
diff --git a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
index 71a23e6..fe6d6f7 100644
--- a/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
+++ b/tests/src/com/android/services/telephony/DisconnectCauseUtilTest.java
@@ -22,7 +22,6 @@
import static junit.framework.Assert.assertNotNull;
import static junit.framework.TestCase.assertEquals;
-import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
@@ -38,15 +37,11 @@
import com.android.TelephonyTestBase;
import com.android.internal.telephony.CallFailCause;
-import com.android.internal.telephony.GsmCdmaPhone;
-import com.android.internal.telephony.Phone;
-import com.android.internal.telephony.PhoneFactory;
import com.android.phone.R;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import java.util.Locale;
@@ -57,13 +52,6 @@
public static final int PHONE_ID = 123;
public static final String EMPTY_STRING = "";
- // dynamic
- private Context mContext;
-
- //Mocks
- @Mock
- private GsmCdmaPhone mMockPhone;
-
private final FlagsAdapter mFeatureFlags = new FlagsAdapter(){
@Override
public boolean doNotOverridePreciseLabel() {
@@ -74,11 +62,6 @@
@Before
public void setUp() throws Exception {
super.setUp();
- // objects that call static getInstance()
- mMockPhone = mock(GsmCdmaPhone.class);
- mContext = InstrumentationRegistry.getTargetContext();
- // set mocks
- setSinglePhone();
}
/**
@@ -253,11 +236,6 @@
return config;
}
- private void setSinglePhone() throws Exception {
- Phone[] mPhones = new Phone[]{mMockPhone};
- replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
- }
-
private Resources getResourcesForLocale(Context context, Locale locale) {
Configuration config = new Configuration();
config.setToDefaults();
@@ -268,7 +246,7 @@
private void safeAssertLabel(Integer resourceId,
android.telecom.DisconnectCause disconnectCause) {
- Resources r = getResourcesForLocale(mContext, Locale.US);
+ Resources r = getResourcesForLocale(InstrumentationRegistry.getTargetContext(), Locale.US);
if (resourceId == null || r == null) {
return;
}
diff --git a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
index b1572f1..eacb001 100644
--- a/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
+++ b/tests/src/com/android/services/telephony/ImsConferenceControllerTest.java
@@ -25,21 +25,27 @@
import static org.mockito.Mockito.when;
import android.content.ComponentName;
-import android.os.Looper;
+import android.content.pm.PackageManager;
import android.telecom.PhoneAccountHandle;
import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+import com.android.TelephonyTestBase;
+
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
/**
* Tests the functionality in ImsConferenceController.java
*/
-
-public class ImsConferenceControllerTest {
+@RunWith(AndroidJUnit4.class)
+public class ImsConferenceControllerTest extends TelephonyTestBase {
+ @Mock
+ PackageManager mPackageManager;
@Mock
private TelephonyConnectionServiceProxy mMockTelephonyConnectionServiceProxy;
@@ -64,11 +70,14 @@
@Before
public void setUp() throws Exception {
- MockitoAnnotations.initMocks(this);
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
- mTelecomAccountRegistry = TelecomAccountRegistry.getInstance(null);
+ super.setUp();
+
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)).thenReturn(true);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CALLING))
+ .thenReturn(true);
+
+ mTelecomAccountRegistry = TelecomAccountRegistry.getInstance(mContext);
mTestTelephonyConnectionA = new TestTelephonyConnection();
mTestTelephonyConnectionB = new TestTelephonyConnection();
@@ -79,6 +88,11 @@
mMockTelephonyConnectionServiceProxy, () -> false);
}
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
/**
* Behavior: add telephony connections B and A to conference controller,
* set status for connections, remove one call
diff --git a/tests/src/com/android/services/telephony/TelecomAccountRegistryTest.java b/tests/src/com/android/services/telephony/TelecomAccountRegistryTest.java
index a8a54f8..d0fc69d 100644
--- a/tests/src/com/android/services/telephony/TelecomAccountRegistryTest.java
+++ b/tests/src/com/android/services/telephony/TelecomAccountRegistryTest.java
@@ -50,10 +50,8 @@
import com.android.TelephonyTestBase;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SimultaneousCallingTracker;
import com.android.internal.telephony.flags.Flags;
-import com.android.phone.PhoneGlobals;
import com.android.phone.PhoneInterfaceManager;
import com.android.phone.R;
@@ -65,7 +63,6 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@@ -85,7 +82,6 @@
@Mock ImsManager mImsManager;
@Mock SubscriptionManager mSubscriptionManager;
@Mock ContentProvider mContentProvider;
- @Mock PhoneGlobals mPhoneGlobals;
@Mock Phone mPhone;
@Mock Resources mResources;
@Mock Drawable mDrawable;
@@ -98,18 +94,13 @@
private BroadcastReceiver mUserSwitchedAndConfigChangedReceiver;
private BroadcastReceiver mLocaleChangedBroadcastReceiver;
private ContentResolver mContentResolver;
- private Phone[] mPhones;
private TestableLooper mTestableLooper;
@Before
public void setUp() throws Exception {
super.setUp();
mSetFlagsRule.disableFlags(Flags.FLAG_DELAY_PHONE_ACCOUNT_REGISTRATION);
- MockitoAnnotations.initMocks(this);
- mPhones = new Phone[]{mPhone};
- replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
- replaceInstance(PhoneGlobals.class, "sMe", null, mPhoneGlobals);
replaceInstance(PhoneInterfaceManager.class, "sInstance", null, mPhoneInterfaceManager);
when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
when(mPhone.getContext()).thenReturn(mMockedContext);
diff --git a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
index 5618770..6a10d75 100644
--- a/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
+++ b/tests/src/com/android/services/telephony/TelephonyConnectionServiceTest.java
@@ -61,7 +61,6 @@
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
-import android.os.Looper;
import android.platform.test.flag.junit.SetFlagsRule;
import android.telecom.Conference;
import android.telecom.Conferenceable;
@@ -283,7 +282,7 @@
@Before
public void setUp() throws Exception {
super.setUp();
- doReturn(Looper.getMainLooper()).when(mContext).getMainLooper();
+
mTestConnectionService = new TestTelephonyConnectionService(mContext);
mTestConnectionService.setFeatureFlags(mFeatureFlags);
mTestConnectionService.setPhoneFactoryProxy(mPhoneFactoryProxy);
diff --git a/tests/src/com/android/services/telephony/TestTelephonyConnection.java b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
index d91435c..9f1a0ec 100644
--- a/tests/src/com/android/services/telephony/TestTelephonyConnection.java
+++ b/tests/src/com/android/services/telephony/TestTelephonyConnection.java
@@ -16,27 +16,31 @@
package com.android.services.telephony;
-import android.content.AttributionSource;
-import android.content.ContentResolver;
-import android.os.Process;
-import android.os.UserHandle;
-import android.telephony.TelephonyManager;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.notNull;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.content.AttributionSource;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.res.Resources;
+import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
+import android.os.Process;
+import android.os.UserHandle;
+import android.provider.Settings;
import android.telecom.PhoneAccountHandle;
import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.test.mock.MockContentProvider;
+import android.test.mock.MockContentResolver;
import com.android.ims.ImsCall;
import com.android.internal.telephony.Call;
@@ -70,9 +74,6 @@
Context mMockContext;
@Mock
- ContentResolver mMockContentResolver;
-
- @Mock
Resources mMockResources;
@Mock
@@ -96,6 +97,7 @@
@Mock
CarrierConfigManager mCarrierConfigManager;
+ private MockContentResolver mMockContentResolver;
private boolean mIsImsConnection;
private boolean mIsImsExternalConnection;
private boolean mIsConferenceSupported = true;
@@ -136,6 +138,14 @@
mMockContext = mock(Context.class);
mMockTelephonyManager = mock(TelephonyManager.class);
mOriginalConnection = mMockRadioConnection;
+
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+ doReturn(applicationInfo).when(mMockContext).getApplicationInfo();
+ mMockContentResolver = new MockContentResolver(mMockContext);
+ mMockContentResolver.addProvider(Settings.AUTHORITY,
+ new EmptyContentProvider(mMockContext));
+
// Set up mMockRadioConnection and mMockPhone to contain an active call
when(mMockRadioConnection.getState()).thenReturn(Call.State.ACTIVE);
when(mOriginalConnection.getState()).thenReturn(Call.State.ACTIVE);
@@ -159,8 +169,7 @@
when(mMockContext.getSystemService(Context.TELEPHONY_SERVICE))
.thenReturn(mMockTelephonyManager);
when(mMockContext.getAttributionSource()).thenReturn(attributionSource);
- when(mMockContentResolver.getUserId()).thenReturn(UserHandle.USER_CURRENT);
- when(mMockContentResolver.getAttributionSource()).thenReturn(attributionSource);
+ when(mMockContext.getUserId()).thenReturn(UserHandle.USER_CURRENT);
when(mMockResources.getBoolean(anyInt())).thenReturn(false);
when(mMockPhone.getDefaultPhone()).thenReturn(mMockPhone);
when(mMockPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_IMS);
@@ -320,4 +329,15 @@
public void setMockImsPhoneConnection(ImsPhoneConnection connection) {
mImsPhoneConnection = connection;
}
+
+ static class EmptyContentProvider extends MockContentProvider {
+ EmptyContentProvider(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Bundle call(String method, String request, Bundle args) {
+ return new Bundle();
+ }
+ }
}
diff --git a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
index 07c9fd0..649d3dd 100644
--- a/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/RcsFeatureControllerTest.java
@@ -45,6 +45,7 @@
import com.android.ims.FeatureConnector;
import com.android.ims.RcsFeatureManager;
import com.android.internal.telephony.imsphone.ImsRegistrationCallbackHelper;
+import com.android.phone.ImsStateCallbackController;
import org.junit.After;
import org.junit.Before;
@@ -84,6 +85,9 @@
@Before
public void setUp() throws Exception {
super.setUp();
+
+ replaceInstance(ImsStateCallbackController.class, "sInstance", null,
+ mock(ImsStateCallbackController.class));
}
@After
diff --git a/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
index 42a45f4..df7a37e 100644
--- a/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
+++ b/tests/src/com/android/services/telephony/rcs/SipTransportControllerTest.java
@@ -147,12 +147,16 @@
@After
public void tearDown() throws Exception {
- super.tearDown();
- boolean isShutdown = mExecutorService == null || mExecutorService.isShutdown();
- if (!isShutdown) {
+ var monitor = RcsProvisioningMonitor.getInstance();
+ if (monitor != null) {
+ monitor.overrideImsFeatureValidation(TEST_SUB_ID, null);
+ }
+
+ if (mExecutorService != null && !mExecutorService.isShutdown()) {
mExecutorService.shutdownNow();
}
- RcsProvisioningMonitor.getInstance().overrideImsFeatureValidation(TEST_SUB_ID, null);
+
+ super.tearDown();
}
@SmallTest
diff --git a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
index 4cabf95..34ed5c6 100644
--- a/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
+++ b/tests/src/com/android/services/telephony/rcs/TelephonyRcsServiceTest.java
@@ -20,6 +20,7 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -40,6 +41,7 @@
import com.android.ims.RcsFeatureManager;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.phone.ImsStateCallbackController;
import org.junit.After;
import org.junit.Before;
@@ -103,6 +105,9 @@
eq(1), anyInt());
doReturn(true).when(mResourceProxy).getDeviceUceEnabled(any());
+ replaceInstance(ImsStateCallbackController.class, "sInstance", null,
+ mock(ImsStateCallbackController.class));
+
replaceInstance(TelephonyManager.class, "sInstance", null, mTelephonyManager);
doReturn(2).when(mTelephonyManager).getActiveModemCount();
}
diff --git a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/HeaderBlock.java b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/HeaderBlock.java
index 9895d1a..9592e1e 100644
--- a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/HeaderBlock.java
+++ b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/HeaderBlock.java
@@ -40,10 +40,26 @@
int suffixBitCount = blockData.getUnsignedByte(offset++);
int suffixRecordBitCount = blockData.getUnsignedByte(offset++);
int suffixTableBlockIdOffset = blockData.getUnsignedByte(offset++);
- boolean isAllowedList = (blockData.getUnsignedByte(offset) == TRUE);
- mFileFormat = new SatS2RangeFileFormat(
- dataS2Level, prefixBitCount, suffixBitCount, suffixTableBlockIdOffset,
- suffixRecordBitCount, isAllowedList);
+ boolean isAllowedList = (blockData.getUnsignedByte(offset++) == TRUE);
+
+
+ // Check if the block is in the original format or the enhanced format.
+ // If the offset is equal to the block data size, this block is in the original format.
+ // If the offset is less than the block data size, this block is an enhanced block, which
+ // has additional fields:
+ // - the size of an entry value in bytes
+ // - version number of header block
+ if (offset < blockData.getSize()) {
+ int entryValueSizeInBytes = blockData.getUnsignedByte(offset++);
+ int versionNumber = blockData.getInt(offset);
+ mFileFormat = new SatS2RangeFileFormat(
+ dataS2Level, prefixBitCount, suffixBitCount, suffixTableBlockIdOffset,
+ suffixRecordBitCount, isAllowedList, entryValueSizeInBytes, versionNumber);
+ } else {
+ mFileFormat = new SatS2RangeFileFormat(
+ dataS2Level, prefixBitCount, suffixBitCount, suffixTableBlockIdOffset,
+ suffixRecordBitCount, isAllowedList);
+ }
}
/** Creates a {@link HeaderBlock} from low-level block data from a block file. */
diff --git a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/PopulatedSuffixTableBlock.java b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/PopulatedSuffixTableBlock.java
index 2feccbf..8cb9d1d 100644
--- a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/PopulatedSuffixTableBlock.java
+++ b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/PopulatedSuffixTableBlock.java
@@ -58,7 +58,8 @@
SatS2RangeFileFormat fileFormat, IntValueTypedPackedTable packedTable) {
mFileFormat = Objects.requireNonNull(fileFormat);
mPackedTable = Objects.requireNonNull(packedTable);
- mSuffixTableSharedData = SuffixTableSharedData.fromBytes(packedTable.getSharedData());
+ mSuffixTableSharedData = SuffixTableSharedData.fromTypedData(
+ packedTable.getSharedDataAsTyped(), fileFormat);
// Obtain the prefix. All cellIds in this table will share the same prefix except for end
// range values (which are exclusive so can be for mPrefix + 1 with a suffix value of 0).
@@ -189,7 +190,8 @@
endCellIdSuffix = 0;
}
long endCellId = mFileFormat.createCellId(endCellPrefixValue, endCellIdSuffix);
- mSuffixTableRange = new SuffixTableRange(startCellId, endCellId);
+ int entryValue = getEntryValue();
+ mSuffixTableRange = new SuffixTableRange(startCellId, endCellId, entryValue);
}
return mSuffixTableRange;
}
@@ -217,5 +219,9 @@
+ "mSuffixTableEntry=" + mSuffixTableEntry
+ '}';
}
+
+ private int getEntryValue() {
+ return mSuffixTableSharedData.getEntryValue(mSuffixTableEntry.getIndex());
+ }
}
}
diff --git a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SatS2RangeFileFormat.java b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SatS2RangeFileFormat.java
index 39507aa..a335766 100644
--- a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SatS2RangeFileFormat.java
+++ b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SatS2RangeFileFormat.java
@@ -53,6 +53,10 @@
/** The format version of the satellite S2 data file, read and written. */
public static final int VERSION = 1;
+ private static final int DEFAULT_ENTRY_VALUE_SIZE_IN_BYTES = 0;
+ private static final int DEFAULT_VERSION_NUMBER = 0;
+ private static final int MAX_ENTRY_BYTE_COUNT = 4;
+
private final int mDataS2Level;
private final int mPrefixBitCount;
@@ -87,11 +91,28 @@
private final boolean mIsAllowedList;
/**
+ * Entry value size in bytes
+ */
+ private final int mEntryValueSizeInBytes;
+
+ /**
+ * Version number
+ */
+ private final int mVersionNumber;
+
+ public SatS2RangeFileFormat(int s2Level, int prefixBitCount, int suffixBitCount,
+ int suffixTableBlockIdOffset, int tableEntryBitCount, boolean isAllowedList) {
+ this(s2Level, prefixBitCount, suffixBitCount, suffixTableBlockIdOffset, tableEntryBitCount,
+ isAllowedList, DEFAULT_ENTRY_VALUE_SIZE_IN_BYTES, DEFAULT_VERSION_NUMBER);
+ }
+
+ /**
* Creates a new file format. This constructor validates the values against various hard-coded
* constraints and will throw an {@link IllegalArgumentException} if they are not satisfied.
*/
public SatS2RangeFileFormat(int s2Level, int prefixBitCount, int suffixBitCount,
- int suffixTableBlockIdOffset, int tableEntryBitCount, boolean isAllowedList) {
+ int suffixTableBlockIdOffset, int tableEntryBitCount, boolean isAllowedList,
+ int entryValueSizeInBytes, int versionNumber) {
Conditions.checkArgInRange("s2Level", s2Level, 0, MAX_S2_LEVEL);
@@ -180,6 +201,12 @@
mSuffixTableBlockIdOffset = suffixTableBlockIdOffset;
mIsAllowedList = isAllowedList;
+
+ Conditions.checkArgInRange("entryValueSizeInBytes", entryValueSizeInBytes, 0,
+ MAX_ENTRY_BYTE_COUNT);
+ mEntryValueSizeInBytes = entryValueSizeInBytes;
+
+ mVersionNumber = versionNumber;
}
/** Returns the S2 level of all geo data stored in the file. */
@@ -345,6 +372,18 @@
+ "}";
}
+ /**
+ * Returns the length of entry value in Bytes.
+ * @return the length of entry value
+ */
+ public int getEntryValueSizeInBytes() {
+ return mEntryValueSizeInBytes;
+ }
+
+ public int getVersionNumber() {
+ return mVersionNumber;
+ }
+
@Override
public String toString() {
return "SatS2RangeFileFormat{"
@@ -359,6 +398,8 @@
+ ", mSuffixTableBlockIdOffset=" + mSuffixTableBlockIdOffset
+ ", mUnusedCellIdBitCount=" + mUnusedCellIdBitCount
+ ", mIsAllowedList=" + mIsAllowedList
+ + ", mEntryValueSizeInBytes=" + mEntryValueSizeInBytes
+ + ", mVersionNumber=" + mVersionNumber
+ '}';
}
@@ -381,7 +422,9 @@
&& mTableEntryMaxRangeLengthValue == that.mTableEntryMaxRangeLengthValue
&& mSuffixTableBlockIdOffset == that.mSuffixTableBlockIdOffset
&& mIsAllowedList == that.mIsAllowedList
- && mUnusedCellIdBitCount == that.mUnusedCellIdBitCount;
+ && mUnusedCellIdBitCount == that.mUnusedCellIdBitCount
+ && mEntryValueSizeInBytes == that.mEntryValueSizeInBytes
+ && mVersionNumber == that.mVersionNumber;
}
@Override
@@ -389,7 +432,7 @@
return Objects.hash(mDataS2Level, mPrefixBitCount, mMaxPrefixValue, mSuffixBitCount,
mMaxSuffixValue, mTableEntryBitCount, mTableEntryRangeLengthBitCount,
mTableEntryMaxRangeLengthValue, mSuffixTableBlockIdOffset, mIsAllowedList,
- mUnusedCellIdBitCount);
+ mUnusedCellIdBitCount, mEntryValueSizeInBytes, mVersionNumber);
}
private void checkS2Level(String name, long cellId) {
diff --git a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SuffixTableRange.java b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SuffixTableRange.java
index 88f1b2e..8c1466f 100644
--- a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SuffixTableRange.java
+++ b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SuffixTableRange.java
@@ -23,12 +23,12 @@
import java.util.Objects;
public final class SuffixTableRange extends S2LevelRange {
- private static final int DEAFAULT_ENTRY_VALUE = -1;
+ private static final int DEFAULT_ENTRY_VALUE = -1;
private final int mEntryValue;
// For backward compatibility
public SuffixTableRange(long startCellId, long endCellId) {
- this(startCellId, endCellId, DEAFAULT_ENTRY_VALUE);
+ this(startCellId, endCellId, DEFAULT_ENTRY_VALUE);
}
public SuffixTableRange(long startCellId, long endCellId, int entryValue) {
diff --git a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SuffixTableSharedData.java b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SuffixTableSharedData.java
index 2221b2c..14cb92f 100644
--- a/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SuffixTableSharedData.java
+++ b/utils/satellite/s2storage/src/readonly/java/com/android/telephony/sats2range/read/SuffixTableSharedData.java
@@ -16,11 +16,13 @@
package com.android.telephony.sats2range.read;
+import com.android.storage.block.read.TypedData;
import com.android.storage.io.read.TypedInputStream;
import com.android.storage.table.reader.Table;
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.util.List;
import java.util.Objects;
/**
@@ -28,14 +30,98 @@
* entries in the table and is required when interpreting the table's block data.
*/
public final class SuffixTableSharedData {
-
+ public static final int INVALID_ENTRY_VALUE = -1;
private final int mTablePrefix;
+ private final int mEntryValueSizeInBytes;
+ private final int mNumberOfEntryValues;
+ private final int mHeaderByteOffsetToRead;
+ private List<Integer> mEntryValuesToWrite = List.of(); // This is used for write path
+ private final TypedData mSharedDataToRead; // This is used for read path
/**
* Creates a {@link SuffixTableSharedData}. See also {@link #fromBytes(byte[])}.
*/
public SuffixTableSharedData(int tablePrefix) {
mTablePrefix = tablePrefix;
+ mEntryValueSizeInBytes = 0;
+ mNumberOfEntryValues = 0;
+ mHeaderByteOffsetToRead = 0;
+ mSharedDataToRead = null;
+ }
+
+ /**
+ * This constructor is used for write path
+ */
+ public SuffixTableSharedData(int tablePrefix, List<Integer> entryValues,
+ SatS2RangeFileFormat fileFormat) {
+ mSharedDataToRead = null;
+ mTablePrefix = tablePrefix;
+ mNumberOfEntryValues = entryValues.size();
+ mEntryValuesToWrite = entryValues;
+ mEntryValueSizeInBytes = fileFormat.getEntryValueSizeInBytes();
+ mHeaderByteOffsetToRead = 0;
+ }
+
+ /**
+ * This constructor is used for read path
+ */
+ public SuffixTableSharedData(TypedData sharedDataToRead, SatS2RangeFileFormat fileFormat) {
+ mSharedDataToRead = Objects.requireNonNull(sharedDataToRead);
+ int offset = 0;
+ // extract prefix value
+ mTablePrefix = mSharedDataToRead.getInt(offset);
+ offset += Integer.BYTES;
+
+ // If the size of shared data is greater than the offset, extract the number of entry
+ // values.
+ if ((offset + Integer.BYTES) < mSharedDataToRead.getSize()) {
+ mNumberOfEntryValues = mSharedDataToRead.getInt(offset);
+ mHeaderByteOffsetToRead = offset + Integer.BYTES;
+ mEntryValueSizeInBytes = fileFormat.getEntryValueSizeInBytes();
+ } else {
+ mNumberOfEntryValues = 0;
+ mHeaderByteOffsetToRead = offset;
+ mEntryValueSizeInBytes = 0;
+ }
+ }
+
+ /**
+ * This is used for read path
+ */
+ public static SuffixTableSharedData fromTypedData(TypedData sharedData,
+ SatS2RangeFileFormat fileFormat) {
+ return new SuffixTableSharedData(sharedData, fileFormat);
+ }
+
+ /**
+ * Reads the entry value at a specific position in the byte buffer and returns it.
+ *
+ * @param entryIndex The index of entry to be read.
+ * @return entry value (integer) read from the byte buffer.
+ */
+ public int getEntryValue(int entryIndex) {
+ if (mSharedDataToRead == null || entryIndex < 0 || mNumberOfEntryValues == 0) {
+ return INVALID_ENTRY_VALUE;
+ }
+
+ if (mNumberOfEntryValues == 1) {
+ entryIndex = 0;
+ }
+
+ int offset;
+ if (entryIndex < mNumberOfEntryValues) {
+ // offset = table prefix(4) + entry value count(4) + size of entry * entry index
+ offset = mHeaderByteOffsetToRead + (mEntryValueSizeInBytes * entryIndex);
+ } else {
+ return INVALID_ENTRY_VALUE;
+ }
+
+ return getValueInternal(mSharedDataToRead, mEntryValueSizeInBytes, offset);
+ }
+
+ // Entry lists to be written to a byte buffer.
+ public List<Integer> getEntryValuesToWrite() {
+ return mEntryValuesToWrite;
}
/**
@@ -46,6 +132,20 @@
return mTablePrefix;
}
+ /**
+ * Returns the number of entry values.
+ */
+ public int getNumberOfEntryValues() {
+ return mNumberOfEntryValues;
+ }
+
+ /**
+ * Returns the size of entry value in Bytes.
+ */
+ public int getEntryValueSizeInBytes() {
+ return mEntryValueSizeInBytes;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
@@ -55,18 +155,22 @@
return false;
}
SuffixTableSharedData that = (SuffixTableSharedData) o;
- return mTablePrefix == that.mTablePrefix;
+ return mTablePrefix == that.mTablePrefix
+ && mNumberOfEntryValues == that.mNumberOfEntryValues
+ && mEntryValuesToWrite.equals(that.mEntryValuesToWrite);
}
@Override
public int hashCode() {
- return Objects.hash(mTablePrefix);
+ return Objects.hash(mTablePrefix, mNumberOfEntryValues, mEntryValuesToWrite);
}
@Override
public String toString() {
return "SuffixTableSharedData{"
+ "mTablePrefix=" + mTablePrefix
+ + "mNumberOfEntries=" + mNumberOfEntryValues
+ + "mEntryValuesToWrite=" + mEntryValuesToWrite
+ '}';
}
@@ -82,4 +186,21 @@
throw new RuntimeException(e);
}
}
+
+ private int getValueInternal(TypedData buffer, int valueSizeBytes, int byteOffset) {
+ if (byteOffset < 0) {
+ throw new IllegalArgumentException(
+ "byteOffset=" + byteOffset + " must not be negative");
+ }
+
+ // High bytes read first.
+ int value = 0;
+ int bytesRead = 0;
+ while (bytesRead++ < valueSizeBytes) {
+ value <<= Byte.SIZE;
+ value |= buffer.getUnsignedByte(byteOffset++);
+ }
+
+ return value;
+ }
}
diff --git a/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SatS2RangeFileFormatTest.java b/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SatS2RangeFileFormatTest.java
index 80ef467..65da1e4 100644
--- a/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SatS2RangeFileFormatTest.java
+++ b/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SatS2RangeFileFormatTest.java
@@ -67,10 +67,12 @@
int suffixBitCount = 16;
int suffixTableBlockIdOffset = 5;
int suffixTableEntryBitCount = 24;
+ int suffixTableEntryValueSizeInBytes = 4;
+ int versionNumber = 2;
boolean isAllowedList = false;
SatS2RangeFileFormat satS2RangeFileFormat = new SatS2RangeFileFormat(s2Level,
prefixBitCount, suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
- isAllowedList);
+ isAllowedList, suffixTableEntryValueSizeInBytes, versionNumber);
assertEquals(2, satS2RangeFileFormat.calculateRangeLength(
cellId(s2Level, 0, 0), cellId(s2Level, 0, 2)));
@@ -92,9 +94,11 @@
int suffixTableBlockIdOffset = 5;
int suffixTableEntryBitCount = 24;
boolean isAllowedList = true;
+ int suffixTableEntryValueSizeInBytes = 4;
+ int versionNumber = 2;
SatS2RangeFileFormat satS2RangeFileFormat = new SatS2RangeFileFormat(s2Level,
prefixBitCount, suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
- isAllowedList);
+ isAllowedList, suffixTableEntryValueSizeInBytes, versionNumber);
// Too many bits for prefixValue
assertThrows(IllegalArgumentException.class,
@@ -127,9 +131,11 @@
int suffixTableBlockIdOffset = 5;
int suffixTableEntryBitCount = 24;
boolean isAllowedList = true;
+ int suffixTableEntryValueSizeInBytes = 4;
+ int versionNumber = 2;
SatS2RangeFileFormat satS2RangeFileFormat = new SatS2RangeFileFormat(s2Level,
prefixBitCount, suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
- isAllowedList);
+ isAllowedList, suffixTableEntryValueSizeInBytes, versionNumber);
assertEquals(0, satS2RangeFileFormat.extractFaceIdFromPrefix(0b00000000000));
assertEquals(5, satS2RangeFileFormat.extractFaceIdFromPrefix(0b10100000000));
@@ -147,9 +153,11 @@
int suffixTableBlockIdOffset = 5;
int suffixTableEntryBitCount = 24;
boolean isAllowedList = true;
+ int suffixTableEntryValueSizeInBytes = 4;
+ int versionNumber = 2;
SatS2RangeFileFormat satS2RangeFileFormat = new SatS2RangeFileFormat(s2Level,
prefixBitCount, suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
- isAllowedList);
+ isAllowedList, suffixTableEntryValueSizeInBytes, versionNumber);
// Too many bits for rangeLength
assertThrows(IllegalArgumentException.class,
@@ -161,6 +169,33 @@
assertTrue(satS2RangeFileFormat.isAllowedList());
}
+ @Test
+ public void extractEntryValueByteCount() {
+ int s2Level = 12;
+ int prefixBitCount = 11;
+ int suffixBitCount = 16;
+ int suffixTableBlockIdOffset = 5;
+ int suffixTableEntryBitCount = 24;
+ boolean isAllowedList = true;
+ final int[] suffixTableEntryValueSizeInBytes = {5};
+ int versionNumber = 1;
+
+ // Table entry byte count exceeds BYTE range.
+ assertThrows(IllegalArgumentException.class,
+ () -> new SatS2RangeFileFormat(s2Level, prefixBitCount, suffixBitCount,
+ suffixTableBlockIdOffset, suffixTableEntryBitCount, isAllowedList,
+ suffixTableEntryValueSizeInBytes[0], versionNumber));
+
+ suffixTableEntryValueSizeInBytes[0] = 1;
+ SatS2RangeFileFormat satS2RangeFileFormat = new SatS2RangeFileFormat(s2Level,
+ prefixBitCount, suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
+ isAllowedList, suffixTableEntryValueSizeInBytes[0], versionNumber);
+
+ assertEquals(suffixTableEntryValueSizeInBytes[0],
+ satS2RangeFileFormat.getEntryValueSizeInBytes());
+ assertEquals(versionNumber, satS2RangeFileFormat.getVersionNumber());
+ }
+
private static int maxValForBits(int bits) {
return intPow2(bits) - 1;
}
diff --git a/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SatS2RangeFileReaderTest.java b/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SatS2RangeFileReaderTest.java
index 2797b77..6de40e1 100644
--- a/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SatS2RangeFileReaderTest.java
+++ b/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SatS2RangeFileReaderTest.java
@@ -17,6 +17,7 @@
package com.android.telephony.sats2range;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import com.android.telephony.sats2range.read.SatS2RangeFileFormat;
import com.android.telephony.sats2range.read.SatS2RangeFileReader;
@@ -78,4 +79,67 @@
assertEquals(expectedRange3, range3);
}
}
+
+ @Test
+ public void findEntryByCellIdWithEntryValue() throws IOException {
+ final boolean isAllowedList = true;
+ final int entryValueSizeInBytes = 4;
+ final int versionNumber = 0;
+ final int entryValue1 = 1;
+ final int entryValue2 = 2;
+ final int entryValue3 = 3;
+
+ File file = File.createTempFile("test", ".dat");
+ SatS2RangeFileFormat fileFormat;
+
+ SuffixTableRange expectedRange1, expectedRange2, expectedRange3;
+ try (SatS2RangeFileWriter satS2RangeFileWriter = SatS2RangeFileWriter.open(file,
+ TestUtils.createS2RangeFileFormat(isAllowedList, entryValueSizeInBytes,
+ versionNumber))) {
+ fileFormat = satS2RangeFileWriter.getFileFormat();
+
+ // Two ranges that share a prefix.
+ expectedRange1 = new SuffixTableRange(
+ TestUtils.createCellId(fileFormat, 1, 1000, 1000),
+ TestUtils.createCellId(fileFormat, 1, 1000, 2000),
+ entryValue1);
+ expectedRange2 = new SuffixTableRange(
+ TestUtils.createCellId(fileFormat, 1, 1000, 2000),
+ TestUtils.createCellId(fileFormat, 1, 1000, 3000),
+ entryValue2);
+ // This range has a different prefix, so will be in a different suffix table.
+ expectedRange3 = new SuffixTableRange(
+ TestUtils.createCellId(fileFormat, 1, 1001, 1000),
+ TestUtils.createCellId(fileFormat, 1, 1001, 2000),
+ entryValue3);
+
+ List<SuffixTableRange> ranges = new ArrayList<>();
+ ranges.add(expectedRange1);
+ ranges.add(expectedRange2);
+ ranges.add(expectedRange3);
+ satS2RangeFileWriter.createSortedSuffixBlocks(ranges.iterator());
+ }
+
+ try (SatS2RangeFileReader satS2RangeFileReader = SatS2RangeFileReader.open(file)) {
+ assertEquals(isAllowedList, satS2RangeFileReader.isAllowedList());
+
+ SuffixTableRange range1 = satS2RangeFileReader.findEntryByCellId(
+ TestUtils.createCellId(fileFormat, 1, 1000, 1500));
+ assertNotNull(range1);
+ assertEquals(expectedRange1, range1);
+ assertEquals(entryValue1, range1.getEntryValue());
+
+ SuffixTableRange range2 = satS2RangeFileReader.findEntryByCellId(
+ TestUtils.createCellId(fileFormat, 1, 1000, 2500));
+ assertNotNull(range2);
+ assertEquals(expectedRange2, range2);
+ assertEquals(entryValue2, range2.getEntryValue());
+
+ SuffixTableRange range3 = satS2RangeFileReader.findEntryByCellId(
+ TestUtils.createCellId(fileFormat, 1, 1001, 1500));
+ assertNotNull(range3);
+ assertEquals(expectedRange3, range3);
+ assertEquals(entryValue3, range3.getEntryValue());
+ }
+ }
}
diff --git a/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SuffixTableSharedDataTest.java b/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SuffixTableSharedDataTest.java
index 2baefa9..ee21626 100644
--- a/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SuffixTableSharedDataTest.java
+++ b/utils/satellite/s2storage/src/test/java/com/android/telephony/sats2range/SuffixTableSharedDataTest.java
@@ -18,11 +18,18 @@
import static org.junit.Assert.assertEquals;
+import com.android.storage.block.read.BlockData;
+import com.android.telephony.sats2range.read.SatS2RangeFileFormat;
import com.android.telephony.sats2range.read.SuffixTableSharedData;
import com.android.telephony.sats2range.write.SuffixTableSharedDataWriter;
import org.junit.Test;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
/** Tests for {@link SuffixTableSharedData} and {@link SuffixTableSharedDataWriter}. */
public class SuffixTableSharedDataTest {
@Test
@@ -33,5 +40,106 @@
assertEquals(sharedData, SuffixTableSharedData.fromBytes(bytes));
}
-}
+ @Test
+ public void testSuffixTableSharedDataWithEntryValues() {
+ int prefix = 321;
+ int entryValueSizeInBytes = 1;
+ List<Integer> entryValues = new ArrayList<>(Arrays.asList(0x01, 0x7F, 0xFF));
+ int versionNumber = 1;
+
+ // Verify whether fromTypedData returns correct SuffixTableSharedData when entryByte is 1
+ verifySharedData(prefix, entryValueSizeInBytes, entryValues.size(), entryValues,
+ versionNumber);
+
+ // Verify when entryValueSizeInBytes is 2
+ entryValueSizeInBytes = 2;
+ entryValues = new ArrayList<>(Arrays.asList(0x001, 0x5FFF, 0xAFFF, 0xFFFF));
+ verifySharedData(prefix, entryValueSizeInBytes, entryValues.size(), entryValues,
+ versionNumber);
+
+ // Verify when entryValueSizeInBytes is 3
+ entryValueSizeInBytes = 3;
+ entryValues = new ArrayList<>(
+ Arrays.asList(0x000001, 0x4FFFFF, 0x8FFFFF, 0xBFFFFF, 0xFFFFFF));
+ verifySharedData(prefix, entryValueSizeInBytes, entryValues.size(), entryValues,
+ versionNumber);
+
+ // Verify when entryValueSizeInBytes is 4, max int value is 0x7FFFFFFF.
+ // ConfigID is supported up to 0x7FFFFFFF for now.
+ entryValueSizeInBytes = 4;
+ entryValues = new ArrayList<>(
+ Arrays.asList(0x00000001, 0x2FFFFFFF, 0x3FFFFFFF, 0x4FFFFFFF, 0x5FFFFFFF,
+ 0x6FFFFFFF, 0x7FFFFFFF));
+ verifySharedData(prefix, entryValueSizeInBytes, entryValues.size(), entryValues,
+ versionNumber);
+
+ // Verify when every entry has same value.
+ entryValues = new ArrayList<>(
+ Arrays.asList(0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF,
+ 0x3FFFFFFF, 0x3FFFFFFF));
+ verifySharedData(prefix, entryValueSizeInBytes, entryValues.size(), entryValues,
+ versionNumber);
+
+ // Verify when entry is empty
+ // entryValueSizeInBytes is set as 4, but there is no entry list
+ entryValues = new ArrayList<>(List.of());
+ verifySharedData(prefix, entryValueSizeInBytes, entryValues.size(), entryValues,
+ versionNumber);
+ // entryValueSizeInBytes is 0, no entry list
+ entryValueSizeInBytes = 0;
+ verifySharedData(prefix, entryValueSizeInBytes, entryValues.size(), entryValues,
+ versionNumber);
+ }
+
+ private BlockData createBlockedDataFromByteBuffer(int prefix,
+ List<Integer> entryValues, SatS2RangeFileFormat fileFormat) {
+ SuffixTableSharedData sharedDataToWrite = new SuffixTableSharedData(prefix, entryValues,
+ fileFormat);
+ ByteBuffer byteBuffer = ByteBuffer.wrap(
+ SuffixTableSharedDataWriter.toBytes(sharedDataToWrite));
+ return new BlockData(byteBuffer.asReadOnlyBuffer());
+ }
+
+ private void verifySharedData(int expectedTablePrefix, int expectedEntryValueSizeInBytes,
+ int expectedNumberOfEntryValues, List<Integer> expectedEntryValues, int versionNumber) {
+ SatS2RangeFileFormat fileFormat = createSatS2RangeFileFormat(expectedEntryValueSizeInBytes,
+ versionNumber);
+ BlockData blockData = createBlockedDataFromByteBuffer(
+ expectedTablePrefix, expectedEntryValues, fileFormat);
+ SuffixTableSharedData sharedData = SuffixTableSharedData.fromTypedData(blockData,
+ fileFormat);
+
+ assertEquals(expectedTablePrefix, sharedData.getTablePrefix());
+ if (!expectedEntryValues.isEmpty()) {
+ assertEquals(expectedEntryValueSizeInBytes, sharedData.getEntryValueSizeInBytes());
+ } else {
+ assertEquals(0, sharedData.getEntryValueSizeInBytes());
+ }
+
+ // If every entry has same value, block data contains only 1 entry info
+ if (expectedEntryValues.stream().distinct().count() == 1) {
+ assertEquals(3 * Integer.BYTES, blockData.getSize());
+ // Verify whether the entry value count has been set to 1.
+ assertEquals(1, sharedData.getNumberOfEntryValues());
+ } else {
+ assertEquals(expectedNumberOfEntryValues, sharedData.getNumberOfEntryValues());
+ }
+ for (int i = 0; i < expectedNumberOfEntryValues; i++) {
+ assertEquals((int) expectedEntryValues.get(i), sharedData.getEntryValue(i));
+ }
+ }
+
+ private SatS2RangeFileFormat createSatS2RangeFileFormat(int entryByteCount, int versionNumber) {
+ int s2Level = 12;
+ int prefixBitCount = 11;
+ int suffixBitCount = 16;
+ int suffixTableBlockIdOffset = 5;
+ int suffixTableEntryBitCount = 24;
+ boolean isAllowedList = true;
+
+ return new SatS2RangeFileFormat(s2Level,
+ prefixBitCount, suffixBitCount, suffixTableBlockIdOffset, suffixTableEntryBitCount,
+ isAllowedList, entryByteCount, versionNumber);
+ }
+}
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 3dfc720..ca0b754 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
@@ -38,6 +38,14 @@
/** Returns a valid {@link SatS2RangeFileFormat}. */
public static SatS2RangeFileFormat createS2RangeFileFormat(boolean isAllowedList) {
+ return createS2RangeFileFormat(isAllowedList,
+ /* entryValueSizeInBytes */0,
+ /* versionNumber */0);
+ }
+
+ /** Returns a valid {@link SatS2RangeFileFormat}. */
+ public static SatS2RangeFileFormat createS2RangeFileFormat(boolean isAllowedList,
+ int entryValueSizeInBytes, int versionNumber) {
int dataS2Level = TEST_S2_LEVEL;
int faceIdBits = 3;
int bitCountPerLevel = 2;
@@ -48,7 +56,8 @@
int suffixTableEntryBitCount = 4 * Byte.SIZE;
int suffixTableBlockIdOffset = 5;
return new SatS2RangeFileFormat(dataS2Level, prefixBitCount, suffixBitCount,
- suffixTableBlockIdOffset, suffixTableEntryBitCount, isAllowedList);
+ suffixTableBlockIdOffset, suffixTableEntryBitCount, isAllowedList,
+ entryValueSizeInBytes, versionNumber);
}
/** Create an S2 cell ID */
diff --git a/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/HeaderBlockWriter.java b/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/HeaderBlockWriter.java
index d4e9310..0435922 100644
--- a/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/HeaderBlockWriter.java
+++ b/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/HeaderBlockWriter.java
@@ -63,6 +63,8 @@
tos.writeUnsignedByte(mFileFormat.getSuffixTableBlockIdOffset());
tos.writeUnsignedByte(mFileFormat.isAllowedList()
? HeaderBlock.TRUE : HeaderBlock.FALSE);
+ tos.writeUnsignedByte(mFileFormat.getEntryValueSizeInBytes());
+ tos.writeInt(mFileFormat.getVersionNumber());
}
FileChannel fileChannel = FileChannel.open(mFile.toPath(), StandardOpenOption.READ);
diff --git a/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/SatS2RangeFileWriter.java b/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/SatS2RangeFileWriter.java
index 3018aec..375707a 100644
--- a/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/SatS2RangeFileWriter.java
+++ b/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/SatS2RangeFileWriter.java
@@ -168,36 +168,16 @@
// Add an empty block.
blockWriter = SuffixTableWriter.createEmptyBlockWriter();
} else {
+ List<SuffixTableRange> suffixTableRanges = convertSamePrefixRangesToSuffixTableRanges(
+ samePrefixRanges);
+ List<Integer> entryValues = getEntryValues(suffixTableRanges);
// Create a suffix table block.
- SuffixTableSharedData sharedData = new SuffixTableSharedData(currentPrefix);
+ SuffixTableSharedData sharedData = new SuffixTableSharedData(currentPrefix, entryValues,
+ mFileFormat);
SuffixTableWriter suffixTableWriter =
SuffixTableWriter.createPopulated(mFileFormat, sharedData);
- SuffixTableRange lastRange = null;
- for (SuffixTableRange currentRange : samePrefixRanges) {
- // Validate ranges don't overlap.
- if (lastRange != null) {
- if (lastRange.overlaps(currentRange)) {
- throw new IllegalStateException("lastRange=" + lastRange + " overlaps"
- + " currentRange=" + currentRange);
- }
- }
- lastRange = currentRange;
-
- // Split the range so it fits.
- final int maxRangeLength = mFileFormat.getTableEntryMaxRangeLengthValue();
- long startCellId = currentRange.getStartCellId();
- long endCellId = currentRange.getEndCellId();
- int rangeLength = mFileFormat.calculateRangeLength(startCellId, endCellId);
- while (rangeLength > maxRangeLength) {
- long newEndCellId = S2Support.offsetCellId(startCellId, maxRangeLength);
- SuffixTableRange suffixTableRange = new SuffixTableRange(startCellId,
- newEndCellId);
- suffixTableWriter.addRange(suffixTableRange);
- startCellId = newEndCellId;
- rangeLength = mFileFormat.calculateRangeLength(startCellId, endCellId);
- }
- SuffixTableRange suffixTableRange = new SuffixTableRange(startCellId, endCellId);
- suffixTableWriter.addRange(suffixTableRange);
+ for (SuffixTableRange range : suffixTableRanges) {
+ suffixTableWriter.addRange(range);
}
blockWriter = suffixTableWriter;
}
@@ -237,4 +217,48 @@
public SatS2RangeFileFormat getFileFormat() {
return mFileFormat;
}
+
+ private List<SuffixTableRange> convertSamePrefixRangesToSuffixTableRanges(
+ List<SuffixTableRange> samePrefixRanges) {
+ List<SuffixTableRange> suffixTableRanges = new ArrayList<>();
+ SuffixTableRange lastRange = null;
+ for (SuffixTableRange currentRange : samePrefixRanges) {
+ // Validate ranges don't overlap.
+ if (lastRange != null) {
+ if (lastRange.overlaps(currentRange)) {
+ throw new IllegalStateException("lastRange=" + lastRange + " overlaps"
+ + " currentRange=" + currentRange);
+ }
+ }
+ lastRange = currentRange;
+ int entryValue = currentRange.getEntryValue();
+
+ // Split the range so it fits.
+ final int maxRangeLength = mFileFormat.getTableEntryMaxRangeLengthValue();
+ long startCellId = currentRange.getStartCellId();
+ long endCellId = currentRange.getEndCellId();
+ int rangeLength = mFileFormat.calculateRangeLength(startCellId, endCellId);
+ while (rangeLength > maxRangeLength) {
+ long newEndCellId = S2Support.offsetCellId(startCellId, maxRangeLength);
+ SuffixTableRange suffixTableRange =
+ new SuffixTableRange(startCellId, newEndCellId, entryValue);
+ suffixTableRanges.add(suffixTableRange);
+ startCellId = newEndCellId;
+ rangeLength = mFileFormat.calculateRangeLength(startCellId, endCellId);
+ }
+ SuffixTableRange suffixTableRange =
+ new SuffixTableRange(startCellId, endCellId, entryValue);
+ suffixTableRanges.add(suffixTableRange);
+ }
+ return suffixTableRanges;
+ }
+
+ private List<Integer> getEntryValues(List<SuffixTableRange> suffixTableRanges) {
+ List<Integer> entryValues = new ArrayList<>();
+ for (SuffixTableRange suffixTableRange : suffixTableRanges) {
+ entryValues.add(suffixTableRange.getEntryValue());
+ }
+ return entryValues;
+ }
+
}
diff --git a/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/SuffixTableSharedDataWriter.java b/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/SuffixTableSharedDataWriter.java
index 5499148..a739e5e 100644
--- a/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/SuffixTableSharedDataWriter.java
+++ b/utils/satellite/s2storage/src/write/java/com/android/telephony/sats2range/write/SuffixTableSharedDataWriter.java
@@ -21,21 +21,37 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.List;
/**
* Converts a {@link SuffixTableSharedData} to a byte[] for writing.
* See also {@link SuffixTableSharedData#fromBytes(byte[])}.
*/
public final class SuffixTableSharedDataWriter {
-
+ private static final int BUFFER_SIZE = (int) Math.pow(2, 20);
private SuffixTableSharedDataWriter() {
}
/** Returns the byte[] for the supplied {@link SuffixTableSharedData} */
public static byte[] toBytes(SuffixTableSharedData suffixTableSharedData) {
+ int entryValueSizeInBytes = suffixTableSharedData.getEntryValueSizeInBytes();
+ List<Integer> entryValues = suffixTableSharedData.getEntryValuesToWrite();
+ // If every entry has same value, compress to save memory
+ int numberOfEntryValues =
+ entryValues.stream().distinct().count() == 1 ? 1 : entryValues.size();
+
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
- TypedOutputStream tos = new TypedOutputStream(baos)) {
+ TypedOutputStream tos = new TypedOutputStream(baos, BUFFER_SIZE)) {
tos.writeInt(suffixTableSharedData.getTablePrefix());
+
+ if (entryValueSizeInBytes > 0 && !entryValues.isEmpty()) {
+ tos.writeInt(numberOfEntryValues);
+ for (int i = 0; i < numberOfEntryValues; i++) {
+ // ConfigId is supported up to 0x7FFFFFFF
+ tos.writeVarByteValue(entryValueSizeInBytes, entryValues.get(i));
+ }
+ }
+
tos.flush();
return baos.toByteArray();
} catch (IOException e) {