[automerger skipped] Merge "Merge Android 14 QPR3 to AOSP main" into main am: 319dd9f607 -s ours am: 4a25608c64 -s ours
am skip reason: Merged-In I684660ce44e8a71706c915543c69c21481829699 with SHA-1 d8ea43539e is already in history
Original change: https://android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/3131843
Change-Id: I28a42cec90ca645a22ea19a9864043f45fb46a76
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/flags/Android.bp b/flags/Android.bp
index 4646649..1885032 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -33,7 +33,6 @@
"subscription.aconfig",
"uicc.aconfig",
"satellite.aconfig",
- "iwlan.aconfig",
- "telephony.aconfig",
+ "iwlan.aconfig"
],
}
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index c18fa1a..c1dc7e7 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -1,16 +1,31 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=breadley TARGET=24Q3
flag {
name: "simultaneous_calling_indications"
+ is_exported: true
namespace: "telephony"
description: "APIs that are used to notify simultaneous calling changes to other applications."
bug: "297446980"
+ is_exported: true
}
+# OWNER=yomna TARGET=24Q3
flag {
name: "show_call_fail_notification_for_2g_toggle"
namespace: "telephony"
description: "Used in DisconnectCause and TelephonyConnection if a non-emergency call fails on a device with no 2G, to guard whether a user can see an updated error message reminding the 2G is disabled and potentially disrupting their call connectivity"
bug: "300142897"
-}
\ No newline at end of file
+}
+
+# OWNER=stevestatia TARGET=24Q4
+flag {
+ name: "remove_country_code_from_local_singapore_calls"
+ namespace: "telephony"
+ description: "Fix bug where the country code is being shown when merging in local Singapore numbers to conference calls."
+ bug:"284416645"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 87fbede..d956104 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -1,6 +1,18 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=linggm TARGET=24Q4
+flag {
+ name: "keep_empty_requests_network"
+ namespace: "telephony"
+ description: "Don't tear down network even if no requests attached to it."
+ bug: "331301784"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=linggm TARGET=24Q3
flag {
name: "auto_data_switch_allow_roaming"
namespace: "telephony"
@@ -11,13 +23,18 @@
}
}
+# OWNER=linggm TARGET=24Q3
flag {
- name: "auto_data_switch_rat_ss"
+ name: "auto_data_switch_uses_data_enabled"
namespace: "telephony"
- description: "Whether switch for better rat and signal strength"
- bug:"260928808"
+ description: "Separately consider the backup phone's data allowed and data enabled."
+ bug: "338552223"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
+# OWNER=linggm TARGET=24Q2
flag {
name: "use_alarm_callback"
namespace: "telephony"
@@ -25,6 +42,7 @@
bug: "311476875"
}
+# OWNER=linggm TARGET=24Q2
flag {
name: "refine_preferred_data_profile_selection"
namespace: "telephony"
@@ -32,6 +50,7 @@
bug: "311476883"
}
+# OWNER=linggm TARGET=24Q2
flag {
name: "unthrottle_check_transport"
namespace: "telephony"
@@ -39,6 +58,7 @@
bug: "303922311"
}
+# OWNER=linggm TARGET=24Q1
flag {
name: "relax_ho_teardown"
namespace: "telephony"
@@ -46,6 +66,7 @@
bug: "270895912"
}
+# OWNER=linggm TARGET=24Q2
flag {
name: "allow_mmtel_in_non_vops"
namespace: "telephony"
@@ -53,6 +74,7 @@
bug: "241198464"
}
+# OWNER=jackyu TARGET=24Q2
flag {
name: "metered_embb_urlcc"
namespace: "telephony"
@@ -60,27 +82,34 @@
bug: "301310451"
}
+# OWNER=sarahchin TARGET=24Q3
flag {
name: "slicing_additional_error_codes"
+ is_exported: true
namespace: "telephony"
description: "Support additional slicing error codes and functionality."
bug: "307378699"
}
+# OWNER=nagendranb TARGET=24Q3
flag {
name: "apn_setting_field_support_flag"
+ is_exported: true
namespace: "telephony"
description: "Expose apn setting supporting field"
bug: "307038091"
}
+# OWNER=sangyun TARGET=24Q3
flag {
name: "network_validation"
+ is_exported: true
namespace: "telephony"
description: "Request network validation for data networks and response status."
bug:"286171724"
}
+# OWNER=nagendranb TARGET=24Q2
flag {
name: "notify_data_activity_changed_with_slot"
namespace: "telephony"
@@ -88,6 +117,7 @@
bug: "309896936"
}
+# OWNER=qingqi TARGET=24Q3
flag {
name: "vonr_enabled_metric"
namespace: "telephony"
@@ -95,6 +125,7 @@
bug:"288449751"
}
+# OWNER=willycwhu TARGET=24Q2
flag {
name: "ignore_existing_networks_for_internet_allowed_checking"
namespace: "telephony"
@@ -102,6 +133,7 @@
bug: "284420611"
}
+# OWNER=apsankar TARGET=24Q3
flag {
name: "data_call_session_stats_captures_cross_sim_calling"
namespace: "telephony"
@@ -109,6 +141,7 @@
bug: "313956117"
}
+# OWNER=jackyu TARGET=24Q2
flag {
name: "force_iwlan_mms"
namespace: "telephony"
@@ -116,6 +149,7 @@
bug: "316211526"
}
+# OWNER=sewook TARGET=24Q3
flag {
name: "reconnect_qualified_network"
namespace: "telephony"
@@ -123,9 +157,18 @@
bug: "319520561"
}
+# OWNER=jackyu TARGET=24Q3
flag {
name: "dsrs_diagnostics_enabled"
namespace: "telephony"
description: "Enable DSRS diagnostics."
bug: "319601607"
-}
\ No newline at end of file
+}
+
+# OWNER=jackyu TARGET=24Q3
+flag {
+ name: "data_rat_metric_enabled"
+ namespace: "telephony"
+ description: "Write DataRatStateChanged atom"
+ bug:"318519337"
+}
diff --git a/flags/domainselection.aconfig b/flags/domainselection.aconfig
index 8ca6bd3..623c3b6 100644
--- a/flags/domainselection.aconfig
+++ b/flags/domainselection.aconfig
@@ -1,6 +1,7 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=forestchoi TARGET=24Q3
flag {
name: "ap_domain_selection_enabled"
namespace: "telephony"
@@ -8,6 +9,7 @@
bug:"258112541"
}
+# OWNER=forestchoi TARGET=24Q3
flag {
name: "use_aosp_domain_selection_service"
namespace: "telephony"
@@ -15,13 +17,16 @@
bug:"258112541"
}
+# OWNER=forestchoi TARGET=24Q3
flag {
name: "use_oem_domain_selection_service"
+ is_exported: true
namespace: "telephony"
description: "This flag controls OEMs' domain selection service supported."
bug:"258112541"
}
+# OWNER=forestchoi TARGET=24Q3
flag {
name: "domain_selection_metrics_enabled"
namespace: "telephony"
diff --git a/flags/ims.aconfig b/flags/ims.aconfig
index ca03e51..4eff505 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -1,6 +1,7 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=hyosunkim TARGET=24Q2
flag {
name: "conference_hold_unhold_changed_to_send_message"
namespace: "telephony"
@@ -8,6 +9,7 @@
bug:"288002989"
}
+# OWNER=joonhunshin TARGET=24Q2
flag {
name: "ignore_already_terminated_incoming_call_before_registering_listener"
namespace: "telephony"
@@ -15,6 +17,7 @@
bug:"289461637"
}
+# OWNER=joonhunshin TARGET=24Q2
flag {
name: "clear_cached_ims_phone_number_when_device_lost_ims_registration"
namespace: "telephony"
@@ -22,6 +25,7 @@
bug:"288002989"
}
+# OWNER=sangyun TARGET=24Q2
flag {
name: "update_ims_service_by_gathering_provisioning_changes"
namespace: "telephony"
@@ -29,13 +33,16 @@
bug:"302281114"
}
+# OWNER=shmun TARGET=24Q3
flag {
name: "add_rat_related_suggested_action_to_ims_registration"
+ is_exported: true
namespace: "telephony"
description: "This flag is for adding suggested actions related to RAT to ims registration"
bug:"290573256"
}
+# OWNER=joonhunshin TARGET=24Q3
flag {
name: "terminate_active_video_call_when_accepting_second_video_call_as_audio_only"
namespace: "telephony"
@@ -43,13 +50,16 @@
bug:"309548300"
}
+# OWNER=sewookseo TARGET=24Q3
flag {
name: "emergency_registration_state"
+ is_exported: true
namespace: "telephony"
description: "This flag is created to notify emergency registration state changed."
bug:"312101946"
}
+# OWNER=apsankar TARGET=24Q3
flag {
name: "call_extra_for_non_hold_supported_carriers"
namespace: "telephony"
@@ -57,9 +67,51 @@
bug:"315993953"
}
+# OWNER=joonhunshin TARGET=24Q3
flag {
name: "update_roaming_state_to_set_wfc_mode"
namespace: "telephony"
description: "This flag updates roaming state to set wfc mode"
bug:"317298331"
}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "enable_sip_subscribe_retry"
+ namespace: "telephony"
+ description: "This flag controls whether framework supports SIP subscribe retry or not"
+ bug:"297023230"
+}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "answer_audio_only_when_answering_via_mmi_code"
+ namespace: "telephony"
+ description: "This flag changes the media type when answering incoming call via MMI code"
+ bug:"286499659"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "notify_initial_ims_provisioning_status"
+ namespace: "telephony"
+ description: "This flag allows to notify initial IMS provisioning status when IFeatureProvisioningCallback registered or ImsService connected"
+ bug:"330082572"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "set_number_of_sim_for_ims_enable"
+ namespace: "telephony"
+ description: "This flag allows to set number of SIM for IMS enable/disable for each slot when the eSIM is added while the binding with ImsService exists"
+ bug:"331971397"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/iwlan.aconfig b/flags/iwlan.aconfig
index 472baba..f16ee38 100644
--- a/flags/iwlan.aconfig
+++ b/flags/iwlan.aconfig
@@ -1,14 +1,19 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=jmunikrishna TARGET=24Q3
flag {
name: "enable_aead_algorithms"
+ is_exported: true
namespace: "telephony"
description: "Add AEAD algorithms AES-GCM-8, AES-GCM-12 and AES-GCM-16 to IWLAN"
bug:"306119890"
}
+
+# OWNER=jmunikrishna TARGET=24Q3
flag {
name: "enable_multiple_sa_proposals"
+ is_exported: true
namespace: "telephony"
description: "Add multiple proposals of cipher suites in IKE SA and Child SA"
bug:"287296642"
diff --git a/flags/messaging.aconfig b/flags/messaging.aconfig
index 52c6213..1030ba7 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -1,13 +1,7 @@
package: "com.android.internal.telephony.flags"
container: "system"
-flag {
- name: "reject_bad_sub_id_interaction"
- namespace: "telephony"
- description: "Previously, the DB allows insertion of a random sub Id, but doesn't allow query it. This change rejects such interaction."
- bug: "294125411"
-}
-
+# OWNER=hwangoo TARGET=24Q2
flag {
name: "sms_domain_selection_enabled"
namespace: "telephony"
@@ -15,9 +9,33 @@
bug: "262804071"
}
+# OWNER=tnd TARGET=24Q3
flag {
name: "mms_disabled_error"
+ is_exported: true
namespace: "telephony"
description: "This flag controls the support of the new MMS error code MMS_ERROR_MMS_DISABLED."
bug: "305062594"
}
+
+# OWNER=linggm TARGET=24Q4
+flag {
+ name: "mms_get_apn_from_pdsc"
+ namespace: "telephony"
+ description: "This flag controls get APN details from PDSC instead of telephony provider."
+ bug: "324280016"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=stevestatia TARGET=24Q3
+flag {
+ name: "unregister_sms_broadcast_receiver_from_cat_service"
+ namespace: "telephony"
+ description: "This flag will unregister the sms broadcast receiver in the CatService when the process is disposed."
+ bug: "338936403"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
\ No newline at end of file
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index a11ed3d..9d5cbd6 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -1,6 +1,18 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=linggm TARGET=24Q3
+flag {
+ name: "combine_ril_death_handle"
+ namespace: "telephony"
+ description: "Upon radio service death, combine its handling to prevent race condition"
+ bug:"319612362"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=tjstuart TARGET=24Q3
flag {
name: "do_not_override_precise_label"
namespace: "telephony"
@@ -9,6 +21,7 @@
is_fixed_read_only: true
}
+# OWNER=tnd TARGET=24Q1
flag {
name: "log_mms_sms_database_access_info"
namespace: "telephony"
@@ -16,6 +29,7 @@
bug: "275225402"
}
+# OWNER=tjstuart TARGET=24Q3
flag {
name: "stop_spamming_emergency_notification"
namespace: "telephony"
@@ -23,13 +37,16 @@
bug: "275225402"
}
+# OWNER=avinashmp TARGET=24Q3
flag {
name: "enable_wps_check_api_flag"
+ is_exported: true
namespace: "telephony"
description: "Enable system api isWpsCallNumber. Its an utility api to check if the dialed number is for Wireless Priority Service call."
bug: "304272356"
}
+# OWNER=grantmenke TARGET=24Q3
flag {
name: "ensure_access_to_call_settings_is_restricted"
namespace: "telephony"
@@ -37,6 +54,7 @@
bug: "309655251"
}
+# OWNER=sangyun TARGET=24Q2
flag {
name: "reorganize_roaming_notification"
namespace: "telephony"
@@ -44,6 +62,7 @@
bug: "310594087"
}
+# OWNER=sangyun TARGET=24Q2
flag {
name: "dismiss_network_selection_notification_on_sim_disable"
namespace: "telephony"
@@ -51,6 +70,7 @@
bug: "310594186"
}
+# OWNER=nagendranb TARGET=24Q3
flag {
name: "enable_telephony_analytics"
namespace: "telephony"
@@ -58,20 +78,25 @@
bug: "309896524"
}
+# OWNER=rambowang TARGET=24Q3
flag {
name: "show_call_id_and_call_waiting_in_additional_settings_menu"
+ is_exported: true
namespace: "telephony"
description: "Expose carrier config KEY_ADDITIONAL_SETTINGS_CALLER_ID_VISIBILITY_BOOL and KEY_ADDITIONAL_SETTINGS_CALL_WAITING_VISIBILITY_BOOL."
bug: "310264981"
}
+# OWNER=rambowang TARGET=24Q3
flag {
name: "reset_mobile_network_settings"
+ is_exported: true
namespace: "telephony"
description: "Allows applications to launch Reset Mobile Network Settings page in Settings app."
bug:"271921464"
}
+# OWNER=rambowang TARGET=24Q3
flag {
name: "fix_crash_on_getting_config_when_phone_is_gone"
namespace: "telephony"
@@ -82,6 +107,7 @@
}
}
+# OWNER=rambowang TARGET=24Q3
flag {
name: "add_anomaly_when_notify_config_changed_with_invalid_phone"
namespace: "telephony"
@@ -91,3 +117,103 @@
purpose: PURPOSE_BUGFIX
}
}
+
+# OWNER=rambowang TARGET=24Q3
+flag {
+ name: "hide_preinstalled_carrier_app_at_most_once"
+ namespace: "telephony"
+ description: "Fix bug when preloaded carrier app is uninstalled and lose provisioning data"
+ bug:"158028151"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=sangyun TARGET=24Q3
+flag {
+ name: "roaming_notification_for_single_data_network"
+ namespace: "telephony"
+ description: "Fix bug where roaming notification was not shown on a single data network."
+ bug:"249908996"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "enforce_telephony_feature_mapping"
+ namespace: "telephony"
+ description: "This flag controls telephony feature flags mapping."
+ bug:"297989574"
+}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "enforce_telephony_feature_mapping_for_public_apis"
+ namespace: "telephony"
+ description: "This flag controls telephony feature flags mapping for public APIs and CTS."
+ bug:"297989574"
+}
+
+# OWNER=stevestatia TARGET=24Q3
+flag {
+ name: "prevent_system_server_and_phone_deadlock"
+ namespace: "telephony"
+ description: "This flag controls the order of the binder to prevent deadlock in system_server"
+ bug: "315973270"
+}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "prevent_invocation_repeat_of_ril_call_when_device_does_not_support_voice"
+ namespace: "telephony"
+ description: "This flag prevents repeat invocation of call related APIs in RIL when the device is not voice capable"
+ bug: "290833783"
+}
+
+# OWNER=jackyu TARGET=24Q3
+flag {
+ name: "minimal_telephony_cdm_check"
+ namespace: "telephony"
+ description: "This flag disables Calling/Data/Messaging features if their respective feature is missing"
+ bug: "310710841"
+}
+
+# OWNER=jackyu TARGET=24Q3
+flag {
+ name: "minimal_telephony_managers_conditional_on_features"
+ namespace: "telephony"
+ description: "This flag enables checking for telephony features before initializing corresponding managers"
+ bug: "310710841"
+}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "set_no_reply_timer_for_cfnry"
+ namespace: "telephony"
+ description: "This flag supports setting the no reply timer for CFNRy based on carrier config"
+ bug:"314732435"
+}
+
+# OWNER=joonhunshin TARGET=24Q3
+flag {
+ name: "change_method_of_obtaining_ims_registration_radio_tech"
+ namespace: "telephony"
+ description: "This flag changes the method of obtaining IMS registration radio technology"
+ bug:"330120237"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=sasindran TARGET=24Q3
+flag {
+ name: "use_relaxed_id_match"
+ namespace: "telephony"
+ description: "This flag supports relaxed id match for radio state changes"
+ bug:"336916327"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/network.aconfig b/flags/network.aconfig
index 8d6c4ac..7c09ba3 100644
--- a/flags/network.aconfig
+++ b/flags/network.aconfig
@@ -1,6 +1,7 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=nharold TARGET=24Q1
flag {
name: "enable_carrier_config_n1_control_attempt2"
namespace: "telephony"
@@ -12,20 +13,25 @@
}
}
+# OWNER=sarahchin TARGET=24Q1
flag {
name: "hide_roaming_icon"
+ is_exported: true
namespace: "telephony"
description: "Allow carriers to hide the roaming (R) icon when roaming."
bug: "301467052"
}
+# OWNER=cukie TARGET=24Q3
flag {
name: "enable_identifier_disclosure_transparency"
+ is_exported: true
namespace: "telephony"
description: "Guards APIs for enabling and disabling identifier disclosure transparency"
bug: "276752426"
}
+# OWNER=cukie TARGET=24Q3
flag {
name: "enable_identifier_disclosure_transparency_unsol_events"
namespace: "telephony"
@@ -33,13 +39,16 @@
bug: "276752426"
}
+# OWNER=cukie TARGET=24Q3
flag {
name: "enable_modem_cipher_transparency"
+ is_exported: true
namespace: "telephony"
description: "Guards APIs for enabling and disabling modem cipher transparency."
bug: "283336425"
}
+# OWNER=cukie TARGET=24Q3
flag {
name: "enable_modem_cipher_transparency_unsol_events"
namespace: "telephony"
@@ -47,13 +56,16 @@
bug: "283336425"
}
+# OWNER=songferngwang TARGET=24Q3
flag {
name: "hide_prefer_3g_item"
+ is_exported: true
namespace: "telephony"
description: "Used in the Preferred Network Types menu to determine if the 3G option is displayed."
bug: "310639009"
}
+# OWNER=sarahchin TARGET=24Q2
flag {
name: "support_nr_sa_rrc_idle"
namespace: "telephony"
@@ -61,9 +73,23 @@
bug: "298233308"
}
+# OWNER=nharold TARGET=24Q3
flag {
name: "network_registration_info_reject_cause"
+ is_exported: true
namespace: "telephony"
description: "Elevate NRI#getRejectCause from System to Public"
bug: "239730435"
}
+
+# OWNER=sangyun TARGET=24Q3
+flag {
+ name: "backup_and_restore_for_enable_2g"
+ namespace: "telephony"
+ description: "Support backup & restore for allow 2g (setting) option."
+ bug:"314734614"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 4a02854..2eea80a 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -1,16 +1,36 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=amallampati TARGET=24Q3
flag {
name: "oem_enabled_satellite_flag"
+ is_exported: true
namespace: "telephony"
description: "This flag controls satellite communication supported by OEMs."
bug:"291811962"
}
+# OWNER=amallampati TARGET=24Q3
flag {
name: "carrier_enabled_satellite_flag"
+ is_exported: true
namespace: "telephony"
description: "This flag controls satellite communication supported by carriers."
bug:"296437388"
}
+
+# OWNER=nagendranb TARGET=24Q3
+flag {
+ name: "satellite_internet"
+ namespace: "telephony"
+ description: "This flag enables satellite internet support."
+ bug:"326972202"
+}
+
+# OWNER=xalle TARGET=24Q3
+flag {
+ name: "satellite_persistent_logging"
+ namespace: "telephony"
+ description: "This flag enables satellite persistent logging"
+ bug:"339877723"
+}
\ No newline at end of file
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index fa48fd4..9a5dabc 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -1,27 +1,34 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=linggm TARGET=24Q3
flag {
name: "work_profile_api_split"
+ is_exported: true
namespace: "telephony"
description: "To support separation between personal and work from TelephonyManager and SubscriptionManager API perspective."
bug: "296076674"
}
+# OWNER=linggm TARGET=24Q3
flag {
name: "enforce_subscription_user_filter"
+ is_exported: true
namespace: "telephony"
description: "Enabled flag means subscriptions enforce filtering result base on calling user handle. It marks the telephony completion of user filtering."
bug: "296076674"
}
+# OWNER=rambowang TARGET=24Q3
flag {
name: "data_only_cellular_service"
+ is_exported: true
namespace: "telephony"
description: "Supports customized cellular service capabilities per subscription."
bug: "296097429"
}
+# OWNER=rambowang TARGET=24Q3
flag {
name: "data_only_service_allow_emergency_call_only"
namespace: "telephony"
@@ -29,16 +36,44 @@
bug: "296097429"
}
+# OWNER=hhshin TARGET=24Q3
flag {
name: "support_psim_to_esim_conversion"
+ is_exported: true
namespace: "telephony"
description: "Support the psim to esim conversion."
bug: "315073761"
}
+# OWNER=bookatz TARGET=24Q3
flag {
name: "subscription_user_association_query"
+ is_exported: true
namespace: "telephony"
description: "Supports querying if a subscription is associated with the caller"
bug: "325045841"
}
+
+# OWNER=nharold TARGET=24Q3
+flag {
+ name: "safer_get_phone_number"
+ namespace: "telephony"
+ description: "Safety and performance improvements for getPhoneNumber()"
+ bug: "317673478"
+
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+# OWNER=songferngwang TARGET=24Q3
+flag {
+ name: "reset_primary_sim_default_values"
+ namespace: "telephony"
+ description: "Reset the default values to the remaining sim"
+ bug: "339394518"
+
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/flags/telephony.aconfig b/flags/telephony.aconfig
deleted file mode 100644
index d8a290d..0000000
--- a/flags/telephony.aconfig
+++ /dev/null
@@ -1,44 +0,0 @@
-package: "com.android.internal.telephony.flags"
-container: "system"
-
-flag {
- name: "enforce_telephony_feature_mapping"
- namespace: "telephony"
- description: "This flag controls telephony feature flags mapping."
- bug:"297989574"
-}
-
-flag {
- name: "enforce_telephony_feature_mapping_for_public_apis"
- namespace: "telephony"
- description: "This flag controls telephony feature flags mapping for public APIs and CTS."
- bug:"297989574"
-}
-
-flag {
- name: "prevent_system_server_and_phone_deadlock"
- namespace: "telephony"
- description: "This flag controls the order of the binder to prevent deadlock in system_server"
- bug: "315973270"
-}
-
-flag {
- name: "prevent_invocation_repeat_of_ril_call_when_device_does_not_support_voice"
- namespace: "telephony"
- description: "This flag prevents repeat invocation of call related APIs in RIL when the device is not voice capable"
- bug: "290833783"
-}
-
-flag {
- name: "minimal_telephony_cdm_check"
- namespace: "telephony"
- description: "This flag disables Calling/Data/Messaging features if their respective feature is missing"
- bug: "310710841"
-}
-
-flag {
- name: "minimal_telephony_managers_conditional_on_features"
- namespace: "telephony"
- description: "This flag enables checking for telephony features before initializing corresponding managers"
- bug: "310710841"
-}
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index a50f83e..2679cfe 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -1,33 +1,60 @@
package: "com.android.internal.telephony.flags"
container: "system"
+# OWNER=jayachandranc TARGET=24Q3
flag {
name: "esim_bootstrap_provisioning_flag"
namespace: "telephony"
description: "This flag controls eSIM Bootstrap provisioning feature support."
bug:"298567545"
}
+
+# OWNER=arunvoddu TARGET=24Q3
flag {
name: "imsi_key_retry_download_on_phone_unlock"
namespace: "telephony"
description: "This flag controls to download the IMSI encryption keys after user unlocks the phone."
bug:"303780982"
}
+
+# OWNER=arunvoddu TARGET=24Q4
flag {
name: "carrier_restriction_status"
+ is_exported: true
namespace: "telephony"
description: "This flag controls the visibility of the getCarrierRestrictionStatus in carrierRestrictionRules class."
bug:"313553044"
}
+
+# OWNER=arunvoddu TARGET=24Q3
flag {
name: "carrier_restriction_rules_enhancement"
namespace: "telephony"
description: "This flag controls the new enhancements to the existing carrier restrictions rules"
bug:"317226653"
}
+
+# OWNER=rafahs TARGET=24Q3
flag {
name: "esim_available_memory"
+ is_exported: true
namespace: "telephony"
description: "This flag controls eSIM available memory feature."
bug:"318348580"
}
+
+# OWNER=rambowang TARGET=24Q3
+flag {
+ name: "cleanup_open_logical_channel_record_on_dispose"
+ namespace: "telephony"
+ description: "This flag cleans up the OpenLogicalChannelRecord once SIM is removed"
+ bug:"335046531"
+}
+
+# OWNER=arunvoddu TARGET=24Q4
+flag {
+ name: "set_carrier_restriction_status"
+ namespace: "telephony"
+ description: "This flag controls the visibility of the setCarrierRestrictionStatus API in carrierRestrictionRules class."
+ bug:"342411308"
+}
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index c07c797..48e7b0d 100644
--- a/proto/src/persist_atoms.proto
+++ b/proto/src/persist_atoms.proto
@@ -23,7 +23,7 @@
// Holds atoms to store on persist storage in case of power cycle or process crash.
// NOTE: using int64 rather than google.protobuf.Timestamp for timestamps simplifies implementation.
-// Next id: 70
+// Next id: 82
message PersistAtoms {
/* Aggregated RAT usage during the call. */
repeated VoiceCallRatUsage voice_call_rat_usage = 1;
@@ -231,6 +231,42 @@
/* Timestamp of last satellite_sos_message_recommender pull. */
optional int64 satellite_sos_message_recommender_pull_timestamp_millis = 69;
+
+ /* Data Network Validation statistics and information. */
+ repeated DataNetworkValidation data_network_validation = 70;
+
+ /* Timestamp of last data_network_validation pull. */
+ optional int64 data_network_validation_pull_timestamp_millis = 71;
+
+ /* Snapshot of carrier roaming satellite session. */
+ repeated CarrierRoamingSatelliteSession carrier_roaming_satellite_session = 72;
+
+ /* Timestamp of last carrier_roaming_satellite_session pull. */
+ optional int64 carrier_roaming_satellite_session_pull_timestamp_millis = 73;
+
+ /* Snapshot of carrier roaming satellite controller stats. */
+ repeated CarrierRoamingSatelliteControllerStats carrier_roaming_satellite_controller_stats = 74;
+
+ /* Timestamp of last carrier_roaming_satellite_controller_stats pull. */
+ optional int64 carrier_roaming_satellite_controller_stats_pull_timestamp_millis = 75;
+
+ /* Snapshot of satellite entitlement. */
+ repeated SatelliteEntitlement satellite_entitlement = 76;
+
+ /* Timestamp of last satellite_entitlement pull. */
+ optional int64 satellite_entitlement_pull_timestamp_millis = 77;
+
+ /* Snapshot of satellite config updater. */
+ repeated SatelliteConfigUpdater satellite_config_updater = 78;
+
+ /* Timestamp of last satellite_config_updater pull. */
+ optional int64 satellite_config_updater_pull_timestamp_millis = 79;
+
+ /** Snapshot of satellite access controller. */
+ repeated SatelliteAccessController satellite_access_controller = 80;
+
+ /* Timestamp of last satellite access controller pull. */
+ optional int64 satellite_access_controller_pull_timestamp_millis = 81;
}
// The canonical versions of the following enums live in:
@@ -281,6 +317,9 @@
optional bool is_iwlan_cross_sim_at_end = 38;
optional bool is_iwlan_cross_sim_at_connected = 39;
optional bool vonr_enabled = 40;
+ optional bool is_ntn = 41;
+ optional bool supports_business_call_composer = 42;
+ optional int32 call_composer_status = 43;
// Internal use only
optional int64 setup_begin_millis = 10001;
@@ -310,6 +349,8 @@
optional int64 message_id = 14;
optional int32 count = 15;
optional bool is_managed_profile = 16;
+ optional bool is_ntn = 17;
+ optional bool is_emergency = 18;
// Internal use only
optional int32 hashCode = 10001;
@@ -334,6 +375,8 @@
optional int32 send_error_code = 16;
optional int32 network_error_code = 17;
optional bool is_managed_profile = 18;
+ optional bool is_emergency = 19;
+ optional bool is_ntn = 20;
// Internal use only
optional int32 hashCode = 10001;
@@ -370,6 +413,9 @@
repeated int32 handover_failure_rat = 21;
optional bool is_non_dds = 22;
optional bool is_iwlan_cross_sim = 23;
+ optional bool is_ntn = 24;
+ optional bool is_satellite_transport = 25;
+ optional bool is_provisioning_profile = 26;
}
message CellularServiceState {
@@ -388,6 +434,7 @@
optional bool override_voice_service = 13;
optional bool isDataEnabled = 14;
optional bool is_iwlan_cross_sim = 15;
+ optional bool is_ntn = 16;
// Internal use only
optional int64 last_used_millis = 10001;
@@ -458,6 +505,12 @@
PRIORITIZE_BANDWIDTH = 2;
CBS = 3;
ENTERPRISE = 4;
+ SATELLITE_INTERNET_RESTRICTED = 5;
+ SATELLITE_MMS_RESTRICTED = 6;
+ SATELLITE_IMS_RESTRICTED = 7;
+ SATELLITE_XCAP_RESTRICTED = 8;
+ SATELLITE_EIMS_RESTRICTED = 9;
+ SATELLITE_SUPL_RESTRICTED =10;
}
optional int32 carrier_id = 1;
optional NetworkCapability capability = 2;
@@ -653,18 +706,40 @@
optional int32 total_service_uptime_sec = 15;
optional int32 total_battery_consumption_percent = 16;
optional int32 total_battery_charged_time_sec = 17;
+ optional int32 count_of_demo_mode_satellite_service_enablements_success = 18;
+ optional int32 count_of_demo_mode_satellite_service_enablements_fail = 19;
+ optional int32 count_of_demo_mode_outgoing_datagram_success = 20;
+ optional int32 count_of_demo_mode_outgoing_datagram_fail = 21;
+ optional int32 count_of_demo_mode_incoming_datagram_success = 22;
+ optional int32 count_of_demo_mode_incoming_datagram_fail = 23;
+ optional int32 count_of_datagram_type_keep_alive_success = 24;
+ optional int32 count_of_datagram_type_keep_alive_fail = 25;
+ optional int32 count_of_allowed_satellite_access = 26;
+ optional int32 count_of_disallowed_satellite_access = 27;
+ optional int32 count_of_satellite_access_check_fail = 28;
}
message SatelliteSession {
optional int32 satellite_service_initialization_result = 1;
optional int32 satellite_technology = 2;
optional int32 count = 3;
+ optional int32 satellite_service_termination_result = 4;
+ optional int64 initialization_processing_time_millis = 5;
+ optional int64 termination_processing_time_millis = 6;
+ optional int32 session_duration_seconds = 7;
+ optional int32 count_of_outgoing_datagram_success = 8;
+ optional int32 count_of_outgoing_datagram_failed = 9;
+ optional int32 count_of_incoming_datagram_success = 10;
+ optional int32 count_of_incoming_datagram_failed = 11;
+ optional bool is_demo_mode = 12;
+ optional int32 max_ntn_signal_strength_level = 13;
}
message SatelliteIncomingDatagram {
optional int32 result_code = 1;
optional int32 datagram_size_bytes = 2;
optional int64 datagram_transfer_time_millis = 3;
+ optional bool is_demo_mode = 4;
}
message SatelliteOutgoingDatagram {
@@ -672,6 +747,7 @@
optional int32 result_code = 2;
optional int32 datagram_size_bytes = 3;
optional int64 datagram_transfer_time_millis = 4;
+ optional bool is_demo_mode = 5;
}
message SatelliteProvision {
@@ -691,3 +767,69 @@
optional int32 recommending_handover_type = 7;
optional bool is_satellite_allowed_in_current_location = 8;
}
+
+message DataNetworkValidation {
+ optional int32 network_type = 1;
+ optional int32 apn_type_bitmask = 2;
+ optional int32 signal_strength = 3;
+ optional int32 validation_result = 4;
+ optional int64 elapsed_time_in_millis = 5;
+ optional bool handover_attempted = 6;
+ optional int32 network_validation_count = 7;
+}
+
+message CarrierRoamingSatelliteSession {
+ optional int32 carrier_id = 1;
+ optional bool is_ntn_roaming_in_home_country = 2;
+ optional int32 total_satellite_mode_time_sec = 3;
+ optional int32 number_of_satellite_connections = 4;
+ optional int32 avg_duration_of_satellite_connection_sec = 5;
+ optional int32 satellite_connection_gap_min_sec = 6;
+ optional int32 satellite_connection_gap_avg_sec = 7;
+ optional int32 satellite_connection_gap_max_sec = 8;
+ optional int32 rsrp_avg = 9;
+ optional int32 rsrp_median = 10;
+ optional int32 rssnr_avg = 11;
+ optional int32 rssnr_median = 12;
+ optional int32 count_of_incoming_sms = 13;
+ optional int32 count_of_outgoing_sms = 14;
+ optional int32 count_of_incoming_mms = 15;
+ optional int32 count_of_outgoing_mms = 16;
+}
+
+message CarrierRoamingSatelliteControllerStats {
+ optional int32 config_data_source = 1;
+ optional int32 count_of_entitlement_status_query_request = 2;
+ optional int32 count_of_satellite_config_update_request = 3;
+ optional int32 count_of_satellite_notification_displayed = 4;
+ optional int32 satellite_session_gap_min_sec = 5;
+ optional int32 satellite_session_gap_avg_sec = 6;
+ optional int32 satellite_session_gap_max_sec = 7;
+}
+
+message SatelliteEntitlement {
+ optional int32 carrier_id = 1;
+ optional int32 result = 2;
+ optional int32 entitlement_status = 3;
+ optional bool is_retry = 4;
+ optional int32 count = 5;
+}
+
+message SatelliteConfigUpdater {
+ optional int32 config_version = 1;
+ optional int32 oem_config_result = 2;
+ optional int32 carrier_config_result = 3;
+ optional int32 count = 4;
+}
+
+message SatelliteAccessController {
+ optional int32 access_control_type = 1;
+ optional int64 location_query_time_millis = 2;
+ optional int64 on_device_lookup_time_millis = 3;
+ optional int64 total_checking_time_millis = 4;
+ optional bool is_allowed = 5;
+ optional bool is_emergency = 6;
+ optional int32 result_code = 7;
+ repeated string country_codes = 8;
+ optional int32 config_data_source = 9;
+}
diff --git a/src/java/com/android/internal/telephony/CarrierInfoManager.java b/src/java/com/android/internal/telephony/CarrierInfoManager.java
index 863db93..8364c0a 100644
--- a/src/java/com/android/internal/telephony/CarrierInfoManager.java
+++ b/src/java/com/android/internal/telephony/CarrierInfoManager.java
@@ -33,6 +33,7 @@
import android.util.Log;
import android.util.Pair;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import java.security.PublicKey;
@@ -297,7 +298,12 @@
final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
.createForSubscriptionId(subId);
int carrierId = telephonyManager.getSimCarrierId();
- deleteCarrierInfoForImsiEncryption(context, subId, carrierId);
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ String simOperator = telephonyManager.getSimOperator();
+ deleteCarrierInfoForImsiEncryption(context, subId, carrierId, simOperator);
+ } else {
+ deleteCarrierInfoForImsiEncryption(context, subId, carrierId);
+ }
Intent resetIntent = new Intent(TelephonyIntents.ACTION_CARRIER_CERTIFICATE_DOWNLOAD);
SubscriptionManager.putPhoneIdAndSubIdExtra(resetIntent, mPhoneId);
context.sendBroadcastAsUser(resetIntent, UserHandle.ALL);
@@ -312,13 +318,29 @@
*/
public static void deleteCarrierInfoForImsiEncryption(Context context, int subId,
int carrierId) {
+ deleteCarrierInfoForImsiEncryption(context, subId, carrierId, null);
+ }
+
+ /**
+ * Deletes all the keys for a given Carrier from the device keystore.
+ * @param context Context
+ * @param subId SubscriptionId
+ * @param carrierId delete the key which matches the carrierId
+ * @param simOperator delete the key which matches the MCCMNC
+ *
+ */
+ public static void deleteCarrierInfoForImsiEncryption(Context context, int subId,
+ int carrierId, String simOperator) {
Log.i(LOG_TAG, "deleting carrier key from db for subId=" + subId);
String mcc = "";
String mnc = "";
- final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class)
- .createForSubscriptionId(subId);
- String simOperator = telephonyManager.getSimOperator();
+ if (TextUtils.isEmpty(simOperator)) {
+ final TelephonyManager telephonyManager = context.getSystemService(
+ TelephonyManager.class)
+ .createForSubscriptionId(subId);
+ simOperator = telephonyManager.getSimOperator();
+ }
if (!TextUtils.isEmpty(simOperator)) {
mcc = simOperator.substring(0, 3);
mnc = simOperator.substring(3);
diff --git a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
index 9143f21..10a3a32 100644
--- a/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
+++ b/src/java/com/android/internal/telephony/CarrierKeyDownloadManager.java
@@ -18,6 +18,7 @@
import static java.nio.charset.StandardCharsets.UTF_8;
+import android.annotation.NonNull;
import android.app.AlarmManager;
import android.app.DownloadManager;
import android.app.KeyguardManager;
@@ -27,6 +28,8 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.Network;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
@@ -34,19 +37,22 @@
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
import android.telephony.ImsiEncryptionInfo;
+import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
+
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
@@ -57,6 +63,7 @@
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Date;
+import java.util.List;
import java.util.Random;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipException;
@@ -99,6 +106,8 @@
private static final int EVENT_ALARM_OR_CONFIG_CHANGE = 0;
private static final int EVENT_DOWNLOAD_COMPLETE = 1;
+ private static final int EVENT_NETWORK_AVAILABLE = 2;
+ private static final int EVENT_SCREEN_UNLOCKED = 3;
private static final int[] CARRIER_KEY_TYPES = {TelephonyManager.KEY_TYPE_EPDG,
@@ -111,47 +120,77 @@
private boolean mAllowedOverMeteredNetwork = false;
private boolean mDeleteOldKeyAfterDownload = false;
private boolean mIsRequiredToHandleUnlock;
- private TelephonyManager mTelephonyManager;
+ private final TelephonyManager mTelephonyManager;
private UserManager mUserManager;
-
@VisibleForTesting
- public String mMccMncForDownload;
- public int mCarrierId;
+ public String mMccMncForDownload = "";
+ public int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
@VisibleForTesting
public long mDownloadId;
- private final FeatureFlags mFeatureFlags;
+ private DefaultNetworkCallback mDefaultNetworkCallback;
+ private ConnectivityManager mConnectivityManager;
+ private KeyguardManager mKeyguardManager;
- public CarrierKeyDownloadManager(Phone phone, FeatureFlags featureFlags) {
+ public CarrierKeyDownloadManager(Phone phone) {
mPhone = phone;
- mFeatureFlags = featureFlags;
mContext = phone.getContext();
IntentFilter filter = new IntentFilter();
filter.addAction(INTENT_KEY_RENEWAL_ALARM_PREFIX);
filter.addAction(TelephonyIntents.ACTION_CARRIER_CERTIFICATE_DOWNLOAD);
- filter.addAction(Intent.ACTION_USER_PRESENT);
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ filter.addAction(Intent.ACTION_USER_UNLOCKED);
+ }
mContext.registerReceiver(mBroadcastReceiver, filter, null, phone);
mDownloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
.createForSubscriptionId(mPhone.getSubId());
- mUserManager = mContext.getSystemService(UserManager.class);
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
+ } else {
+ mUserManager = mContext.getSystemService(UserManager.class);
+ }
CarrierConfigManager carrierConfigManager = mContext.getSystemService(
CarrierConfigManager.class);
// Callback which directly handle config change should be executed on handler thread
carrierConfigManager.registerCarrierConfigChangeListener(this::post,
(slotIndex, subId, carrierId, specificCarrierId) -> {
- boolean isUserUnlocked = mUserManager.isUserUnlocked();
-
- if (isUserUnlocked && slotIndex == mPhone.getPhoneId()) {
- Log.d(LOG_TAG, "Carrier Config changed: slotIndex=" + slotIndex);
- handleAlarmOrConfigChange();
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ logd("CarrierConfig changed slotIndex = " + slotIndex + " subId = " + subId
+ + " CarrierId = " + carrierId + " phoneId = "
+ + mPhone.getPhoneId());
+ // Below checks are necessary to optimise the logic.
+ if ((slotIndex == mPhone.getPhoneId()) && (carrierId > 0
+ || !TextUtils.isEmpty(
+ mMccMncForDownload))) {
+ mCarrierId = carrierId;
+ updateSimOperator();
+ // If device is screen locked do not proceed to handle
+ // EVENT_ALARM_OR_CONFIG_CHANGE
+ if (mKeyguardManager.isDeviceLocked()) {
+ logd("Device is Locked");
+ mIsRequiredToHandleUnlock = true;
+ } else {
+ logd("Carrier Config changed: slotIndex=" + slotIndex);
+ sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+ }
+ }
} else {
- Log.d(LOG_TAG, "User is locked");
- mContext.registerReceiver(mUserUnlockedReceiver, new IntentFilter(
- Intent.ACTION_USER_UNLOCKED));
+ boolean isUserUnlocked = mUserManager.isUserUnlocked();
+
+ if (isUserUnlocked && slotIndex == mPhone.getPhoneId()) {
+ Log.d(LOG_TAG, "Carrier Config changed: slotIndex=" + slotIndex);
+ handleAlarmOrConfigChange();
+ } else {
+ Log.d(LOG_TAG, "User is locked");
+ mContext.registerReceiver(mUserUnlockedReceiver, new IntentFilter(
+ Intent.ACTION_USER_UNLOCKED));
+ }
}
});
+ mConnectivityManager = mContext.getSystemService(ConnectivityManager.class);
}
+ // TODO remove this method upon imsiKeyRetryDownloadOnPhoneUnlock enabled.
private final BroadcastReceiver mUserUnlockedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -167,7 +206,7 @@
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
- Log.d(LOG_TAG, "Download Complete");
+ logd("Download Complete");
sendMessage(obtainMessage(EVENT_DOWNLOAD_COMPLETE,
intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0)));
}
@@ -180,27 +219,36 @@
String action = intent.getAction();
int slotIndex = SubscriptionManager.getSlotIndex(mPhone.getSubId());
int phoneId = mPhone.getPhoneId();
- if (action.equals(INTENT_KEY_RENEWAL_ALARM_PREFIX)) {
- int slotIndexExtra = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX, -1);
- if (slotIndexExtra == slotIndex) {
- Log.d(LOG_TAG, "Handling key renewal alarm: " + action);
- sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+ switch (action) {
+ case INTENT_KEY_RENEWAL_ALARM_PREFIX -> {
+ int slotIndexExtra = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX,
+ -1);
+ if (slotIndexExtra == slotIndex) {
+ logd("Handling key renewal alarm: " + action);
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ updateSimOperator();
+ }
+ sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+ }
}
- } else if (action.equals(TelephonyIntents.ACTION_CARRIER_CERTIFICATE_DOWNLOAD)) {
- if (phoneId == intent.getIntExtra(PhoneConstants.PHONE_KEY,
- SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
- Log.d(LOG_TAG, "Handling reset intent: " + action);
- sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+ case TelephonyIntents.ACTION_CARRIER_CERTIFICATE_DOWNLOAD -> {
+ if (phoneId == intent.getIntExtra(PhoneConstants.PHONE_KEY,
+ SubscriptionManager.INVALID_SIM_SLOT_INDEX)) {
+ logd("Handling reset intent: " + action);
+ sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+ }
}
- } else if (action.equals(Intent.ACTION_USER_PRESENT)) {
- // The Carrier key download fails when SIM is inserted while device is locked
- // hence adding a retry logic when device is unlocked.
- Log.d(LOG_TAG,
- "device unlocked, isRequiredToHandleUnlock = " + mIsRequiredToHandleUnlock
- + ", slotIndex = " + slotIndex);
- if (mIsRequiredToHandleUnlock) {
- mIsRequiredToHandleUnlock = false;
- sendEmptyMessage(EVENT_ALARM_OR_CONFIG_CHANGE);
+ case Intent.ACTION_USER_UNLOCKED -> {
+ // The Carrier key download fails when SIM is inserted while device is locked
+ // hence adding a retry logic when device is unlocked.
+ logd("device fully unlocked, isRequiredToHandleUnlock = "
+ + mIsRequiredToHandleUnlock
+ + ", slotIndex = " + slotIndex + " hasActiveDataNetwork = " + (
+ mConnectivityManager.getActiveNetwork() != null));
+ if (mIsRequiredToHandleUnlock) {
+ mIsRequiredToHandleUnlock = false;
+ sendEmptyMessage(EVENT_SCREEN_UNLOCKED);
+ }
}
}
}
@@ -209,76 +257,124 @@
@Override
public void handleMessage (Message msg) {
switch (msg.what) {
- case EVENT_ALARM_OR_CONFIG_CHANGE:
- handleAlarmOrConfigChange();
- break;
- case EVENT_DOWNLOAD_COMPLETE:
+ case EVENT_ALARM_OR_CONFIG_CHANGE, EVENT_NETWORK_AVAILABLE, EVENT_SCREEN_UNLOCKED ->
+ handleAlarmOrConfigChange();
+ case EVENT_DOWNLOAD_COMPLETE -> {
long carrierKeyDownloadIdentifier = (long) msg.obj;
- String currentMccMnc = getSimOperator();
- int carrierId = getSimCarrierId();
+ String currentMccMnc = Flags.imsiKeyRetryDownloadOnPhoneUnlock()
+ ? mTelephonyManager.getSimOperator(mPhone.getSubId()) : getSimOperator();
+ int carrierId = Flags.imsiKeyRetryDownloadOnPhoneUnlock()
+ ? mTelephonyManager.getSimCarrierId() : getSimCarrierId();
if (isValidDownload(currentMccMnc, carrierKeyDownloadIdentifier, carrierId)) {
onDownloadComplete(carrierKeyDownloadIdentifier, currentMccMnc, carrierId);
- onPostDownloadProcessing(carrierKeyDownloadIdentifier);
+ onPostDownloadProcessing();
}
- break;
+ }
}
}
- private void onPostDownloadProcessing(long carrierKeyDownloadIdentifier) {
+ private void onPostDownloadProcessing() {
resetRenewalAlarm();
- cleanupDownloadInfo();
-
+ if(Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ mDownloadId = -1;
+ } else {
+ cleanupDownloadInfo();
+ }
// unregister from DOWNLOAD_COMPLETE
mContext.unregisterReceiver(mDownloadReceiver);
}
private void handleAlarmOrConfigChange() {
- if (carrierUsesKeys()) {
- if (areCarrierKeysAbsentOrExpiring()) {
- boolean downloadStartedSuccessfully = downloadKey();
- // if the download was attempted, but not started successfully, and if carriers uses
- // keys, we'll still want to renew the alarms, and try downloading the key a day
- // later.
- if (!downloadStartedSuccessfully) {
- // If download fails due to the device lock, we will reattempt once the device
- // is unlocked.
- if (mFeatureFlags.imsiKeyRetryDownloadOnPhoneUnlock()) {
- KeyguardManager keyguardManager = mContext.getSystemService(
- KeyguardManager.class);
- if (keyguardManager.isKeyguardSecure()) {
- Log.e(LOG_TAG, "Key download failed in device lock state");
- mIsRequiredToHandleUnlock = true;
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ if (carrierUsesKeys()) {
+ if (areCarrierKeysAbsentOrExpiring()) {
+ boolean hasActiveDataNetwork =
+ (mConnectivityManager.getActiveNetwork() != null);
+ boolean downloadStartedSuccessfully = hasActiveDataNetwork && downloadKey();
+ // if the download was attempted, but not started successfully, and if
+ // carriers uses keys, we'll still want to renew the alarms, and try
+ // downloading the key a day later.
+ int slotIndex = SubscriptionManager.getSlotIndex(mPhone.getSubId());
+ if (downloadStartedSuccessfully) {
+ unregisterDefaultNetworkCb(slotIndex);
+ } else {
+ // If download fails due to the device lock, we will reattempt once the
+ // device is unlocked.
+ mIsRequiredToHandleUnlock = mKeyguardManager.isDeviceLocked();
+ loge("hasActiveDataConnection = " + hasActiveDataNetwork
+ + " isDeviceLocked = " + mIsRequiredToHandleUnlock);
+ if (!hasActiveDataNetwork) {
+ registerDefaultNetworkCb(slotIndex);
}
+ resetRenewalAlarm();
}
- resetRenewalAlarm();
}
+ logd("handleAlarmOrConfigChange :: areCarrierKeysAbsentOrExpiring returned false");
} else {
- return;
+ cleanupRenewalAlarms();
+ if (!isOtherSlotHasCarrier()) {
+ // delete any existing alarms.
+ mPhone.deleteCarrierInfoForImsiEncryption(getSimCarrierId(), getSimOperator());
+ }
+ cleanupDownloadInfo();
}
} else {
- // delete any existing alarms.
- cleanupRenewalAlarms();
- mPhone.deleteCarrierInfoForImsiEncryption(getSimCarrierId());
-
+ if (carrierUsesKeys()) {
+ if (areCarrierKeysAbsentOrExpiring()) {
+ boolean downloadStartedSuccessfully = downloadKey();
+ // if the download was attempted, but not started successfully, and if
+ // carriers uses keys, we'll still want to renew the alarms, and try
+ // downloading the key a day later.
+ if (!downloadStartedSuccessfully) {
+ resetRenewalAlarm();
+ }
+ }
+ } else {
+ // delete any existing alarms.
+ cleanupRenewalAlarms();
+ mPhone.deleteCarrierInfoForImsiEncryption(getSimCarrierId());
+ }
}
}
+ private boolean isOtherSlotHasCarrier() {
+ SubscriptionManager subscriptionManager = mPhone.getContext().getSystemService(
+ SubscriptionManager.class);
+ List<SubscriptionInfo> subscriptionInfoList =
+ subscriptionManager.getActiveSubscriptionInfoList();
+ loge("handleAlarmOrConfigChange ActiveSubscriptionInfoList = " + (
+ (subscriptionInfoList != null) ? subscriptionInfoList.size() : null));
+ for (SubscriptionInfo subInfo : subscriptionInfoList) {
+ if (mPhone.getSubId() != subInfo.getSubscriptionId()
+ && subInfo.getCarrierId() == mPhone.getCarrierId()) {
+ // We do not proceed to remove the Key from the DB as another slot contains
+ // same operator sim which is in active state.
+ loge("handleAlarmOrConfigChange same operator sim in another slot");
+ return true;
+ }
+ }
+ return false;
+ }
+
private void cleanupDownloadInfo() {
- Log.d(LOG_TAG, "Cleaning up download info");
+ logd("Cleaning up download info");
mDownloadId = -1;
- mMccMncForDownload = null;
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ mMccMncForDownload = "";
+ } else {
+ mMccMncForDownload = null;
+ }
mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
}
private void cleanupRenewalAlarms() {
- Log.d(LOG_TAG, "Cleaning up existing renewal alarms");
+ logd("Cleaning up existing renewal alarms");
int slotIndex = SubscriptionManager.getSlotIndex(mPhone.getSubId());
Intent intent = new Intent(INTENT_KEY_RENEWAL_ALARM_PREFIX);
intent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, slotIndex);
PendingIntent carrierKeyDownloadIntent = PendingIntent.getBroadcast(mContext, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
- AlarmManager alarmManager =
- (AlarmManager) mContext.getSystemService(mContext.ALARM_SERVICE);
+ AlarmManager alarmManager =mContext.getSystemService(AlarmManager.class);
alarmManager.cancel(carrierKeyDownloadIntent);
}
@@ -331,7 +427,7 @@
cleanupRenewalAlarms();
int slotIndex = SubscriptionManager.getSlotIndex(mPhone.getSubId());
long minExpirationDate = getExpirationDate();
- Log.d(LOG_TAG, "minExpirationDate: " + new Date(minExpirationDate));
+ logd("minExpirationDate: " + new Date(minExpirationDate));
final AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(
Context.ALARM_SERVICE);
Intent intent = new Intent(INTENT_KEY_RENEWAL_ALARM_PREFIX);
@@ -339,16 +435,35 @@
PendingIntent carrierKeyDownloadIntent = PendingIntent.getBroadcast(mContext, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
alarmManager.set(AlarmManager.RTC_WAKEUP, minExpirationDate, carrierKeyDownloadIntent);
- Log.d(LOG_TAG, "setRenewalAlarm: action=" + intent.getAction() + " time="
+ logd("setRenewalAlarm: action=" + intent.getAction() + " time="
+ new Date(minExpirationDate));
}
/**
+ * Read the store the sim operetor value and update the value in case of change in the sim
+ * operetor.
+ */
+ public void updateSimOperator() {
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ String simOperator = mPhone.getOperatorNumeric();
+ if (!TextUtils.isEmpty(simOperator) && !simOperator.equals(mMccMncForDownload)) {
+ mMccMncForDownload = simOperator;
+ logd("updateSimOperator, Initialized mMccMncForDownload = " + mMccMncForDownload);
+ }
+ }
+ }
+
+ /**
* Returns the sim operator.
**/
@VisibleForTesting
public String getSimOperator() {
- return mTelephonyManager.getSimOperator(mPhone.getSubId());
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ updateSimOperator();
+ return mMccMncForDownload;
+ } else {
+ return mTelephonyManager.getSimOperator(mPhone.getSubId());
+ }
}
/**
@@ -356,7 +471,11 @@
**/
@VisibleForTesting
public int getSimCarrierId() {
- return mTelephonyManager.getSimCarrierId();
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ return (mCarrierId > 0) ? mCarrierId : mPhone.getCarrierId();
+ } else {
+ return mTelephonyManager.getSimCarrierId();
+ }
}
/**
@@ -367,7 +486,7 @@
@VisibleForTesting
public boolean isValidDownload(String currentMccMnc, long currentDownloadId, int carrierId) {
if (currentDownloadId != mDownloadId) {
- Log.e(LOG_TAG, "download ID=" + currentDownloadId
+ loge( "download ID=" + currentDownloadId
+ " for completed download does not match stored id=" + mDownloadId);
return false;
}
@@ -375,12 +494,12 @@
if (TextUtils.isEmpty(currentMccMnc) || TextUtils.isEmpty(mMccMncForDownload)
|| !TextUtils.equals(currentMccMnc, mMccMncForDownload)
|| mCarrierId != carrierId) {
- Log.e(LOG_TAG, "currentMccMnc=" + currentMccMnc + " storedMccMnc =" + mMccMncForDownload
+ loge( "currentMccMnc=" + currentMccMnc + " storedMccMnc =" + mMccMncForDownload
+ "currentCarrierId = " + carrierId + " storedCarrierId = " + mCarrierId);
return false;
}
- Log.d(LOG_TAG, "Matched MccMnc = " + currentMccMnc + ", carrierId = " + carrierId
+ logd("Matched MccMnc = " + currentMccMnc + ", carrierId = " + carrierId
+ ", downloadId: " + currentDownloadId);
return true;
}
@@ -390,7 +509,7 @@
**/
private void onDownloadComplete(long carrierKeyDownloadIdentifier, String mccMnc,
int carrierId) {
- Log.d(LOG_TAG, "onDownloadComplete: " + carrierKeyDownloadIdentifier);
+ logd("onDownloadComplete: " + carrierKeyDownloadIdentifier);
String jsonStr;
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(carrierKeyDownloadIdentifier);
@@ -405,22 +524,21 @@
try {
jsonStr = convertToString(mDownloadManager, carrierKeyDownloadIdentifier);
if (TextUtils.isEmpty(jsonStr)) {
- Log.d(LOG_TAG, "fallback to no gzip");
+ logd("fallback to no gzip");
jsonStr = convertToStringNoGZip(mDownloadManager,
carrierKeyDownloadIdentifier);
}
parseJsonAndPersistKey(jsonStr, mccMnc, carrierId);
} catch (Exception e) {
- Log.e(LOG_TAG, "Error in download:" + carrierKeyDownloadIdentifier
+ loge( "Error in download:" + carrierKeyDownloadIdentifier
+ ". " + e);
} finally {
mDownloadManager.remove(carrierKeyDownloadIdentifier);
}
}
- Log.d(LOG_TAG, "Completed downloading keys");
+ logd("Completed downloading keys");
}
cursor.close();
- return;
}
/**
@@ -442,7 +560,7 @@
CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING,
CarrierConfigManager.KEY_ALLOW_METERED_NETWORK_FOR_CERT_DOWNLOAD_BOOL);
} catch (RuntimeException e) {
- Log.e(LOG_TAG, "CarrierConfigLoader is not available.");
+ loge( "CarrierConfigLoader is not available.");
}
if (b == null || b.isEmpty()) {
return false;
@@ -452,10 +570,10 @@
mURL = b.getString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING);
mAllowedOverMeteredNetwork = b.getBoolean(
CarrierConfigManager.KEY_ALLOW_METERED_NETWORK_FOR_CERT_DOWNLOAD_BOOL);
+
if (mKeyAvailability == 0 || TextUtils.isEmpty(mURL)) {
- Log.d(LOG_TAG,
- "Carrier not enabled or invalid values. mKeyAvailability=" + mKeyAvailability
- + " mURL=" + mURL);
+ logd("Carrier not enabled or invalid values. mKeyAvailability=" + mKeyAvailability
+ + " mURL=" + mURL);
return false;
}
for (int key_type : CARRIER_KEY_TYPES) {
@@ -469,7 +587,7 @@
private static String convertToStringNoGZip(DownloadManager downloadManager, long downloadId) {
StringBuilder sb = new StringBuilder();
try (InputStream source = new FileInputStream(
- downloadManager.openDownloadedFile(downloadId).getFileDescriptor())) {
+ downloadManager.openDownloadedFile(downloadId).getFileDescriptor())) {
// If the carrier does not have the data gzipped, fallback to assuming it is not zipped.
// parseJsonAndPersistKey may still fail if the data is malformed, so we won't be
// persisting random bogus strings thinking it's the cert
@@ -488,8 +606,8 @@
private static String convertToString(DownloadManager downloadManager, long downloadId) {
try (InputStream source = new FileInputStream(
- downloadManager.openDownloadedFile(downloadId).getFileDescriptor());
- InputStream gzipIs = new GZIPInputStream(source)) {
+ downloadManager.openDownloadedFile(downloadId).getFileDescriptor());
+ InputStream gzipIs = new GZIPInputStream(source)) {
BufferedReader reader = new BufferedReader(new InputStreamReader(gzipIs, UTF_8));
StringBuilder sb = new StringBuilder();
@@ -523,7 +641,7 @@
public void parseJsonAndPersistKey(String jsonStr, String mccMnc, int carrierId) {
if (TextUtils.isEmpty(jsonStr) || TextUtils.isEmpty(mccMnc)
|| carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
- Log.e(LOG_TAG, "jsonStr or mcc, mnc: is empty or carrierId is UNKNOWN_CARRIER_ID");
+ loge( "jsonStr or mcc, mnc: is empty or carrierId is UNKNOWN_CARRIER_ID");
return;
}
try {
@@ -548,22 +666,28 @@
if (typeString.equals(JSON_TYPE_VALUE_EPDG)) {
type = TelephonyManager.KEY_TYPE_EPDG;
} else if (!typeString.equals(JSON_TYPE_VALUE_WLAN)) {
- Log.e(LOG_TAG, "Invalid key-type specified: " + typeString);
+ loge( "Invalid key-type specified: " + typeString);
}
}
String identifier = key.getString(JSON_IDENTIFIER);
Pair<PublicKey, Long> keyInfo =
getKeyInformation(cleanCertString(cert).getBytes());
if (mDeleteOldKeyAfterDownload) {
- mPhone.deleteCarrierInfoForImsiEncryption(TelephonyManager.UNKNOWN_CARRIER_ID);
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ mPhone.deleteCarrierInfoForImsiEncryption(
+ TelephonyManager.UNKNOWN_CARRIER_ID, null);
+ } else {
+ mPhone.deleteCarrierInfoForImsiEncryption(
+ TelephonyManager.UNKNOWN_CARRIER_ID);
+ }
mDeleteOldKeyAfterDownload = false;
}
savePublicKey(keyInfo.first, type, identifier, keyInfo.second, mcc, mnc, carrierId);
}
} catch (final JSONException e) {
- Log.e(LOG_TAG, "Json parsing error: " + e.getMessage());
+ loge( "Json parsing error: " + e.getMessage());
} catch (final Exception e) {
- Log.e(LOG_TAG, "Exception getting certificate: " + e);
+ loge( "Exception getting certificate: " + e);
}
}
@@ -584,7 +708,7 @@
public static boolean isKeyEnabled(int keyType, int keyAvailability) {
// since keytype has values of 1, 2.... we need to subtract 1 from the keytype.
int returnValue = (keyAvailability >> (keyType - 1)) & 1;
- return (returnValue == 1) ? true : false;
+ return returnValue == 1;
}
/**
@@ -603,31 +727,42 @@
ImsiEncryptionInfo imsiEncryptionInfo =
mPhone.getCarrierInfoForImsiEncryption(key_type, false);
if (imsiEncryptionInfo == null) {
- Log.d(LOG_TAG, "Key not found for: " + key_type);
+ logd("Key not found for: " + key_type);
return true;
} else if (imsiEncryptionInfo.getCarrierId() == TelephonyManager.UNKNOWN_CARRIER_ID) {
- Log.d(LOG_TAG, "carrier key is unknown carrier, so prefer to reDownload");
+ logd("carrier key is unknown carrier, so prefer to reDownload");
mDeleteOldKeyAfterDownload = true;
return true;
}
Date imsiDate = imsiEncryptionInfo.getExpirationTime();
long timeToExpire = imsiDate.getTime() - System.currentTimeMillis();
- return (timeToExpire < START_RENEWAL_WINDOW_DAYS * DAY_IN_MILLIS) ? true : false;
+ return timeToExpire < START_RENEWAL_WINDOW_DAYS * DAY_IN_MILLIS;
}
return false;
}
private boolean downloadKey() {
- Log.d(LOG_TAG, "starting download from: " + mURL);
- String mccMnc = getSimOperator();
- int carrierId = getSimCarrierId();
- if (!TextUtils.isEmpty(mccMnc) || carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
- Log.d(LOG_TAG, "downloading key for mccmnc : " + mccMnc + ", carrierId : "
- + carrierId);
+ logd("starting download from: " + mURL);
+ String mccMnc = null;
+ int carrierId = -1;
+ if (Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ if (TextUtils.isEmpty(mMccMncForDownload)
+ || mCarrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
+ loge("mccmnc or carrierId is UnKnown");
+ return false;
+ }
} else {
- Log.e(LOG_TAG, "mccmnc or carrierId is UnKnown");
- return false;
+ mccMnc = getSimOperator();
+ carrierId = getSimCarrierId();
+ if (!TextUtils.isEmpty(mccMnc) || carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) {
+ Log.d(LOG_TAG, "downloading key for mccmnc : " + mccMnc + ", carrierId : "
+ + carrierId);
+ } else {
+ Log.e(LOG_TAG, "mccmnc or carrierId is UnKnown");
+ return false;
+ }
}
+
try {
// register the broadcast receiver to listen for download complete
IntentFilter filter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
@@ -641,15 +776,16 @@
request.setAllowedOverMetered(mAllowedOverMeteredNetwork);
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.addRequestHeader("Accept-Encoding", "gzip");
- Long carrierKeyDownloadRequestId = mDownloadManager.enqueue(request);
-
- Log.d(LOG_TAG, "saving values mccmnc: " + mccMnc + ", downloadId: "
- + carrierKeyDownloadRequestId + ", carrierId: " + carrierId);
- mMccMncForDownload = mccMnc;
- mCarrierId = carrierId;
+ long carrierKeyDownloadRequestId = mDownloadManager.enqueue(request);
+ if (!Flags.imsiKeyRetryDownloadOnPhoneUnlock()) {
+ mMccMncForDownload = mccMnc;
+ mCarrierId = carrierId;
+ }
mDownloadId = carrierKeyDownloadRequestId;
+ logd("saving values mccmnc: " + mMccMncForDownload + ", downloadId: "
+ + carrierKeyDownloadRequestId + ", carrierId: " + mCarrierId);
} catch (Exception e) {
- Log.e(LOG_TAG, "exception trying to download key from url: " + mURL + ", Exception = "
+ loge( "exception trying to download key from url: " + mURL + ", Exception = "
+ e.getMessage());
return false;
}
@@ -667,7 +803,7 @@
CertificateFactory cf = CertificateFactory.getInstance("X.509");
X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream);
Pair<PublicKey, Long> keyInformation =
- new Pair(cert.getPublicKey(), cert.getNotAfter().getTime());
+ new Pair<>(cert.getPublicKey(), cert.getNotAfter().getTime());
return keyInformation;
}
@@ -699,4 +835,59 @@
cert.indexOf(CERT_BEGIN_STRING),
cert.indexOf(CERT_END_STRING) + CERT_END_STRING.length());
}
+
+ /**
+ * Registering the callback to listen on data connection availability.
+ *
+ * @param slotId Sim slotIndex that tries to download the key.
+ */
+ private void registerDefaultNetworkCb(int slotId) {
+ logd("RegisterDefaultNetworkCb for slotId = " + slotId);
+ if (mDefaultNetworkCallback == null
+ && slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
+ mDefaultNetworkCallback = new DefaultNetworkCallback(slotId);
+ mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this);
+ }
+ }
+
+ /**
+ * Unregister the data connection monitor listener.
+ */
+ private void unregisterDefaultNetworkCb(int slotId) {
+ logd("unregisterDefaultNetworkCb for slotId = " + slotId);
+ if (mDefaultNetworkCallback != null) {
+ mConnectivityManager.unregisterNetworkCallback(mDefaultNetworkCallback);
+ mDefaultNetworkCallback = null;
+ }
+ }
+
+ final class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback {
+ final int mSlotIndex;
+
+ public DefaultNetworkCallback(int slotId) {
+ mSlotIndex = slotId;
+ }
+
+ /** Called when the framework connects and has declared a new network ready for use. */
+ @Override
+ public void onAvailable(@NonNull Network network) {
+ logd("Data network connected, slotId = " + mSlotIndex);
+ if (mConnectivityManager.getActiveNetwork() != null && SubscriptionManager.getSlotIndex(
+ mPhone.getSubId()) == mSlotIndex) {
+ mIsRequiredToHandleUnlock = false;
+ unregisterDefaultNetworkCb(mSlotIndex);
+ sendEmptyMessage(EVENT_NETWORK_AVAILABLE);
+ }
+ }
+ }
+
+ private void loge(String logStr) {
+ String TAG = LOG_TAG + " [" + mPhone.getPhoneId() + "]";
+ Log.e(TAG, logStr);
+ }
+
+ private void logd(String logStr) {
+ String TAG = LOG_TAG + " [" + mPhone.getPhoneId() + "]";
+ Log.d(TAG, logStr);
+ }
}
diff --git a/src/java/com/android/internal/telephony/Connection.java b/src/java/com/android/internal/telephony/Connection.java
index 68fd6ab..82b4c2b8e 100644
--- a/src/java/com/android/internal/telephony/Connection.java
+++ b/src/java/com/android/internal/telephony/Connection.java
@@ -33,6 +33,7 @@
import com.android.ims.internal.ConferenceParticipant;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.domainselection.DomainSelectionResolver;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.telephony.Rlog;
@@ -634,7 +635,7 @@
*
* @hide
*/
- public void setEmergencyCallInfo(CallTracker ct) {
+ public void setEmergencyCallInfo(CallTracker ct, Phone.DialArgs dialArgs) {
if (ct != null) {
Phone currentPhone = ct.getPhone();
if (currentPhone != null) {
@@ -677,20 +678,52 @@
} else {
Rlog.e(TAG, "setEmergencyCallInfo: call tracker is null");
}
+
+ if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
+ if (mEmergencyNumberInfo == null) {
+ Rlog.d(TAG, "setEmergencyCallInfo: create EmergencyNumber");
+ setNonDetectableEmergencyCallInfo((dialArgs != null) ? dialArgs.eccCategory
+ : EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED,
+ new ArrayList<String>());
+ }
+ if (dialArgs != null && dialArgs.intentExtras != null
+ && dialArgs.intentExtras.getBoolean(
+ PhoneConstants.EXTRA_USE_EMERGENCY_ROUTING, false)
+ && mEmergencyNumberInfo.getEmergencyCallRouting()
+ != EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY) {
+ int eccCategory = dialArgs.intentExtras.getInt(
+ PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
+ mEmergencyNumberInfo.getEmergencyServiceCategoryBitmask());
+ Rlog.d(TAG, "setEmergencyCallInfo: enforce emergency routing eccCategory="
+ + eccCategory);
+ List<String> emergencyUrns = dialArgs.intentExtras.getStringArrayList(
+ PhoneConstants.EXTRA_EMERGENCY_URNS);
+ if (emergencyUrns == null || emergencyUrns.isEmpty()) {
+ emergencyUrns = mEmergencyNumberInfo.getEmergencyUrns();
+ }
+ mEmergencyNumberInfo = new EmergencyNumber(mEmergencyNumberInfo.getNumber(),
+ mEmergencyNumberInfo.getCountryIso(),
+ mEmergencyNumberInfo.getMnc(),
+ eccCategory,
+ emergencyUrns,
+ mEmergencyNumberInfo.getEmergencyNumberSourceBitmask(),
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+ }
+ }
}
/**
* Set the non-detectable emergency number information.
*/
- public void setNonDetectableEmergencyCallInfo(int eccCategory) {
- if (!mIsEmergencyCall) {
- mIsEmergencyCall = true;
- mEmergencyNumberInfo = new EmergencyNumber(mAddress, ""/*countryIso*/,
- ""/*mnc*/, eccCategory,
- new ArrayList<String>(),
- EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
- EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
- }
+ public void setNonDetectableEmergencyCallInfo(int eccCategory,
+ @NonNull List<String> emergencyUrns) {
+ Rlog.d(TAG, "setNonDetectableEmergencyCallInfo: eccCategory=" + eccCategory
+ + ", emergencyUrns=" + emergencyUrns);
+ mIsEmergencyCall = true;
+ mEmergencyNumberInfo = new EmergencyNumber(mAddress, ""/*countryIso*/, ""/*mnc*/,
+ eccCategory, emergencyUrns,
+ EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_UNKNOWN);
}
/**
diff --git a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
index e81d0f1..9c7993b 100644
--- a/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/DefaultPhoneNotifier.java
@@ -318,6 +318,12 @@
mTelephonyRegistryMgr.notifyCallbackModeStopped(sender.getPhoneId(),
sender.getSubId(), type, reason);
}
+
+ @Override
+ public void notifyCarrierRoamingNtnModeChanged(Phone sender, boolean active) {
+ mTelephonyRegistryMgr.notifyCarrierRoamingNtnModeChanged(sender.getSubId(), active);
+ }
+
/**
* Convert the {@link Call.State} enum into the PreciseCallState.PRECISE_CALL_STATE_* constants
* for the public API.
diff --git a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
index 9113514..26d4e1b 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java
@@ -160,7 +160,7 @@
public GsmCdmaCallTracker(GsmCdmaPhone phone, FeatureFlags featureFlags) {
super(featureFlags);
- if (mFeatureFlags.minimalTelephonyCdmCheck()
+ if (TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)
&& !phone.getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_CALLING)) {
throw new UnsupportedOperationException("GsmCdmaCallTracker requires calling");
diff --git a/src/java/com/android/internal/telephony/GsmCdmaConnection.java b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
index e06520a..cc07047 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaConnection.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaConnection.java
@@ -139,7 +139,7 @@
mHandler = new MyHandler(mOwner.getLooper());
mAddress = dc.number;
- setEmergencyCallInfo(mOwner);
+ setEmergencyCallInfo(mOwner, null);
String forwardedNumber = TextUtils.isEmpty(dc.forwardedNumber) ? null : dc.forwardedNumber;
Rlog.i(LOG_TAG, "create, forwardedNumber=" + Rlog.pii(LOG_TAG, forwardedNumber));
@@ -186,13 +186,13 @@
mAddress = PhoneNumberUtils.extractNetworkPortionAlt(dialString);
if (dialArgs.isEmergency) {
- setEmergencyCallInfo(mOwner);
+ setEmergencyCallInfo(mOwner, null);
// There was no emergency number info found for this call, however it is
// still marked as an emergency number. This may happen if it was a redialed
// non-detectable emergency call from IMS.
if (getEmergencyNumberInfo() == null) {
- setNonDetectableEmergencyCallInfo(dialArgs.eccCategory);
+ setNonDetectableEmergencyCallInfo(dialArgs.eccCategory, new ArrayList<String>());
}
}
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 4c7a3d3..93a0c2f 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -411,7 +411,7 @@
mLinkBandwidthEstimator = mTelephonyComponentFactory
.inject(LinkBandwidthEstimator.class.getName())
- .makeLinkBandwidthEstimator(this);
+ .makeLinkBandwidthEstimator(this, getLooper());
mCallWaitingController = new CallWaitingController(this);
@@ -470,7 +470,7 @@
};
private boolean hasCalling() {
- if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
return mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_CALLING);
}
@@ -539,7 +539,7 @@
mContext.registerReceiver(mBroadcastReceiver, filter,
android.Manifest.permission.MODIFY_PHONE_STATE, null, Context.RECEIVER_EXPORTED);
- mCDM = new CarrierKeyDownloadManager(this, mFeatureFlags);
+ mCDM = new CarrierKeyDownloadManager(this);
mCIM = new CarrierInfoManager();
mCi.registerForImeiMappingChanged(this, EVENT_IMEI_MAPPING_CHANGED, null);
@@ -2124,8 +2124,13 @@
@Override
public void deleteCarrierInfoForImsiEncryption(int carrierId) {
+ CarrierInfoManager.deleteCarrierInfoForImsiEncryption(mContext, getSubId(), carrierId);
+ }
+
+ @Override
+ public void deleteCarrierInfoForImsiEncryption(int carrierId, String simOperator) {
CarrierInfoManager.deleteCarrierInfoForImsiEncryption(mContext, getSubId(),
- carrierId);
+ carrierId, simOperator);
}
@Override
@@ -2298,6 +2303,11 @@
}
@Override
+ protected void onSetNetworkSelectionModeCompleted() {
+ mSST.pollState();
+ }
+
+ @Override
public String getCdmaPrlVersion() {
return mSST.getPrlVersion();
}
@@ -3029,12 +3039,12 @@
@Override
public void registerForCallWaiting(Handler h, int what, Object obj) {
- mCT.registerForCallWaiting(h, what, obj);
+ if (mCT != null) mCT.registerForCallWaiting(h, what, obj);
}
@Override
public void unregisterForCallWaiting(Handler h) {
- mCT.unregisterForCallWaiting(h);
+ if (mCT != null) mCT.unregisterForCallWaiting(h);
}
/**
@@ -3669,6 +3679,7 @@
case EVENT_SUBSCRIPTIONS_CHANGED:
logd("EVENT_SUBSCRIPTIONS_CHANGED");
updateUsageSetting();
+ updateNullCipherNotifier();
break;
case EVENT_SET_NULL_CIPHER_AND_INTEGRITY_DONE:
logd("EVENT_SET_NULL_CIPHER_AND_INTEGRITY_DONE");
@@ -3769,7 +3780,8 @@
&& mNullCipherNotifier != null) {
ar = (AsyncResult) msg.obj;
SecurityAlgorithmUpdate update = (SecurityAlgorithmUpdate) ar.result;
- mNullCipherNotifier.onSecurityAlgorithmUpdate(mContext, getSubId(), update);
+ mNullCipherNotifier.onSecurityAlgorithmUpdate(mContext, getPhoneId(),
+ getSubId(), update);
}
break;
@@ -4175,6 +4187,10 @@
Rlog.d(LOG_TAG, "exitEmergencyCallbackMode: mImsPhone=" + mImsPhone
+ " isPhoneTypeGsm=" + isPhoneTypeGsm());
}
+ if (DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
+ EmergencyStateTracker.getInstance().exitEmergencyCallbackMode();
+ return;
+ }
if (mImsPhone != null && mImsPhone.isInImsEcm()) {
mImsPhone.exitEmergencyCallbackMode();
} else {
@@ -5440,6 +5456,25 @@
obtainMessage(EVENT_SET_SECURITY_ALGORITHMS_UPDATED_ENABLED_DONE));
}
+ /**
+ * Update the phoneId -> subId mapping of the null cipher notifier.
+ */
+ @VisibleForTesting
+ public void updateNullCipherNotifier() {
+ if (!mFeatureFlags.enableModemCipherTransparencyUnsolEvents()) {
+ return;
+ }
+
+ SubscriptionInfoInternal subInfo = mSubscriptionManagerService
+ .getSubscriptionInfoInternal(getSubId());
+ boolean active = false;
+ if (subInfo != null) {
+ active = subInfo.isActive();
+ }
+ mNullCipherNotifier.setSubscriptionMapping(mContext, getPhoneId(),
+ active ? subInfo.getSubscriptionId() : -1);
+ }
+
@Override
public boolean isNullCipherAndIntegritySupported() {
return mIsNullCipherAndIntegritySupported;
diff --git a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
index 4146c24..1a6bf2b 100644
--- a/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
+++ b/src/java/com/android/internal/telephony/ImsSmsDispatcher.java
@@ -203,7 +203,8 @@
mTrackers.remove(token);
mPhone.notifySmsSent(tracker.mDestAddress);
mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, true);
+ tracker.mDestAddress, tracker.mMessageId, true,
+ tracker.isSinglePartOrLastPart());
break;
case ImsSmsImplBase.SEND_STATUS_ERROR:
tracker.onFailed(mContext, reason, networkReasonCode);
@@ -247,7 +248,8 @@
networkReasonCode,
tracker.mMessageId,
tracker.isFromDefaultSmsApplication(mContext),
- tracker.getInterval());
+ tracker.getInterval(),
+ mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -664,7 +666,8 @@
SmsManager.RESULT_SYSTEM_ERROR,
tracker.mMessageId,
tracker.isFromDefaultSmsApplication(mContext),
- tracker.getInterval());
+ tracker.getInterval(),
+ mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
diff --git a/src/java/com/android/internal/telephony/InboundSmsHandler.java b/src/java/com/android/internal/telephony/InboundSmsHandler.java
index eafb4ba..49d1adc 100644
--- a/src/java/com/android/internal/telephony/InboundSmsHandler.java
+++ b/src/java/com/android/internal/telephony/InboundSmsHandler.java
@@ -74,6 +74,7 @@
import com.android.internal.telephony.analytics.TelephonyAnalytics;
import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics;
import com.android.internal.telephony.metrics.TelephonyMetrics;
+import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats;
import com.android.internal.telephony.util.NotificationChannelController;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.HexDump;
@@ -746,7 +747,9 @@
// data will be tracked when the message is processed (processMessagePart).
if (result != Intents.RESULT_SMS_HANDLED && result != Activity.RESULT_OK) {
mMetrics.writeIncomingSmsError(mPhone.getPhoneId(), is3gpp2(), smsSource, result);
- mPhone.getSmsStats().onIncomingSmsError(is3gpp2(), smsSource, result);
+ mPhone.getSmsStats().onIncomingSmsError(is3gpp2(), smsSource, result,
+ TelephonyManager.from(mContext)
+ .isEmergencyNumber(smsb.getOriginatingAddress()));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1019,7 +1022,8 @@
+ (pduList.size() == 0 ? "pduList.size() == 0" : "pduList.contains(null)");
logeWithLocalLog(errorMsg, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsError(
- is3gpp2(), tracker.getSource(), RESULT_SMS_NULL_PDU);
+ is3gpp2(), tracker.getSource(), RESULT_SMS_NULL_PDU,
+ TelephonyManager.from(mContext).isEmergencyNumber(tracker.getAddress()));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1048,7 +1052,9 @@
SmsConstants.FORMAT_3GPP, timestamps, false,
tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsWapPush(tracker.getSource(),
- messageCount, RESULT_SMS_NULL_MESSAGE, tracker.getMessageId());
+ messageCount, RESULT_SMS_NULL_MESSAGE, tracker.getMessageId(),
+ TelephonyManager.from(mContext)
+ .isEmergencyNumber(tracker.getAddress()));
return false;
}
}
@@ -1083,7 +1089,8 @@
mMetrics.writeIncomingWapPush(mPhone.getPhoneId(), tracker.getSource(),
format, timestamps, wapPushResult, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsWapPush(tracker.getSource(), messageCount,
- result, tracker.getMessageId());
+ result, tracker.getMessageId(), TelephonyManager.from(mContext)
+ .isEmergencyNumber(tracker.getAddress()));
// result is Activity.RESULT_OK if an ordered broadcast was sent
if (result == Activity.RESULT_OK) {
return true;
@@ -1103,7 +1110,11 @@
mMetrics.writeIncomingSmsSession(mPhone.getPhoneId(), tracker.getSource(),
format, timestamps, block, tracker.getMessageId());
mPhone.getSmsStats().onIncomingSmsSuccess(is3gpp2(), tracker.getSource(),
- messageCount, block, tracker.getMessageId());
+ messageCount, block, tracker.getMessageId(),
+ TelephonyManager.from(mContext).isEmergencyNumber(tracker.getAddress()));
+ CarrierRoamingSatelliteSessionStats sessionStats =
+ CarrierRoamingSatelliteSessionStats.getInstance(mPhone.getSubId());
+ sessionStats.onIncomingSms(mPhone.getSubId());
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
diff --git a/src/java/com/android/internal/telephony/MultiSimSettingController.java b/src/java/com/android/internal/telephony/MultiSimSettingController.java
index aaeba23..a14ae89 100644
--- a/src/java/com/android/internal/telephony/MultiSimSettingController.java
+++ b/src/java/com/android/internal/telephony/MultiSimSettingController.java
@@ -17,6 +17,8 @@
package com.android.internal.telephony;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+import static android.telephony.SubscriptionManager.PROFILE_CLASS_PROVISIONING;
+import static android.telephony.SubscriptionManager.TRANSFER_STATUS_CONVERTED;
import static android.telephony.TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED;
import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE;
import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL;
@@ -54,6 +56,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.ArrayUtils;
@@ -157,6 +160,11 @@
/** The number of active modem count. */
private int mActiveModemCount;
+ private boolean mNeedSetDefaultVoice;
+ private boolean mNeedSetDefaultSms;
+ private boolean mNeedSetDefaultData;
+ private int mConvertedPsimSubId;
+
private static final String SETTING_USER_PREF_DATA_SUB = "user_preferred_data_sub";
private static class DataSettingsControllerCallback extends DataSettingsManagerCallback {
@@ -242,22 +250,24 @@
ccm.registerCarrierConfigChangeListener(this::post,
(slotIndex, subId, carrierId, specificCarrierId) ->
onCarrierConfigChanged(slotIndex, subId));
+
+ mConvertedPsimSubId = getConvertedPsimSubscriptionId();
}
private boolean hasCalling() {
- if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
return mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_CALLING);
}
private boolean hasData() {
- if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
return mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_DATA);
}
private boolean hasMessaging() {
- if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
return mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_MESSAGING);
}
@@ -402,6 +412,7 @@
if (DBG) log("onAllSubscriptionsLoaded: mSubInfoInitialized=" + mSubInfoInitialized);
if (!mSubInfoInitialized) {
mSubInfoInitialized = true;
+ mConvertedPsimSubId = getConvertedPsimSubscriptionId();
for (Phone phone : PhoneFactory.getPhones()) {
phone.mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
}
@@ -443,12 +454,13 @@
return;
}
- CarrierConfigManager cm = mContext.getSystemService(CarrierConfigManager.class);
- if (cm != null) {
- if (CarrierConfigManager.isConfigForIdentifiedCarrier(cm.getConfigForSubId(subId))) {
- mCarrierConfigLoadedSubIds[phoneId] = subId;
- reEvaluateAll();
- }
+ CarrierConfigManager cm;
+ if (!SubscriptionManager.isValidSubscriptionId(subId) // record SIM absent.
+ || ((cm = mContext.getSystemService(CarrierConfigManager.class)) != null
+ && CarrierConfigManager.isConfigForIdentifiedCarrier(
+ cm.getConfigForSubId(subId)))) {
+ mCarrierConfigLoadedSubIds[phoneId] = subId;
+ reEvaluateAll();
}
}
@@ -495,11 +507,20 @@
*/
private boolean isReadyToReevaluate() {
boolean carrierConfigsLoaded = isCarrierConfigLoadedForAllSub();
+ SatelliteController satelliteController = SatelliteController.getInstance();
+ boolean isSatelliteEnabledOrBeingEnabled = false;
+ if (satelliteController != null) {
+ isSatelliteEnabledOrBeingEnabled = satelliteController.isSatelliteEnabled()
+ || satelliteController.isSatelliteBeingEnabled();
+ }
+
if (DBG) {
log("isReadyToReevaluate: subInfoInitialized=" + mSubInfoInitialized
- + ", carrierConfigsLoaded=" + carrierConfigsLoaded);
+ + ", carrierConfigsLoaded=" + carrierConfigsLoaded
+ + ", satelliteEnabledOrBeingEnabled=" + isSatelliteEnabledOrBeingEnabled);
}
- return mSubInfoInitialized && carrierConfigsLoaded;
+ return mSubInfoInitialized && carrierConfigsLoaded
+ && !isSatelliteEnabledOrBeingEnabled;
}
private void reEvaluateAll() {
@@ -597,7 +618,6 @@
*/
protected void updateDefaults() {
if (DBG) log("updateDefaults");
-
if (!isReadyToReevaluate()) return;
List<SubscriptionInfo> activeSubInfos = mSubscriptionManagerService
@@ -625,14 +645,19 @@
// Otherwise, if user just inserted their first SIM, or there's one primary and one
// opportunistic subscription active (activeSubInfos.size() > 1), we automatically
// set the primary to be default SIM and return.
- if (mPrimarySubList.size() == 1 && (change != PRIMARY_SUB_REMOVED
- || mActiveModemCount == 1)) {
+ boolean conditionForOnePrimarySim =
+ mFeatureFlags.resetPrimarySimDefaultValues() ? mPrimarySubList.size() == 1
+ : mPrimarySubList.size() == 1
+ && (change != PRIMARY_SUB_REMOVED || mActiveModemCount == 1);
+ if (conditionForOnePrimarySim) {
int subId = mPrimarySubList.get(0);
if (DBG) log("updateDefaultValues: to only primary sub " + subId);
if (hasData()) mSubscriptionManagerService.setDefaultDataSubId(subId);
if (hasCalling()) mSubscriptionManagerService.setDefaultVoiceSubId(subId);
if (hasMessaging()) mSubscriptionManagerService.setDefaultSmsSubId(subId);
- sendDefaultSubConfirmedNotification(subId);
+ if (!mSubscriptionManagerService.isEsimBootStrapProvisioningActivated()) {
+ sendDefaultSubConfirmedNotification(subId);
+ }
return;
}
@@ -674,7 +699,12 @@
// preference auto selection logic or display notification for end used to
// select voice/data/SMS preferences.
if (!autoFallbackEnabled) {
- sendSubChangeNotificationIfNeeded(change, dataSelected, voiceSelected, smsSelected);
+ // Hide the dialog for preferred SIM/data pick if the primary subscription change is
+ // due to the pSIM conversion.
+ if (!setDefaultForPsimConversionChanged(change, dataSelected, voiceSelected,
+ smsSelected)) {
+ sendSubChangeNotificationIfNeeded(change, dataSelected, voiceSelected, smsSelected);
+ }
} else {
updateUserPreferences(mPrimarySubList, dataSelected, voiceSelected, smsSelected);
}
@@ -685,7 +715,9 @@
// Update mPrimarySubList. Opportunistic subscriptions can't be default
// data / voice / sms subscription.
List<Integer> prevPrimarySubList = mPrimarySubList;
- mPrimarySubList = activeSubList.stream().filter(info -> !info.isOpportunistic())
+ mPrimarySubList = activeSubList.stream()
+ .filter(info -> !info.isOpportunistic())
+ .filter(info -> info.getProfileClass() != PROFILE_CLASS_PROVISIONING)
.map(info -> info.getSubscriptionId())
.collect(Collectors.toList());
@@ -751,6 +783,12 @@
private void sendSubChangeNotificationIfNeeded(int change, boolean dataSelected,
boolean voiceSelected, boolean smsSelected) {
+
+ if (mSubscriptionManagerService.isEsimBootStrapProvisioningActivated()) {
+ log("esim bootstrap activation in progress, skip notification");
+ return;
+ }
+
@TelephonyManager.DefaultSubscriptionSelectType
int simSelectDialogType = getSimSelectDialogType(
change, dataSelected, voiceSelected, smsSelected);
@@ -782,6 +820,119 @@
}
}
+ /**
+ * Check that the primary subscription has changed due to the pSIM conversion.
+ * @param change Whether to update the mPrimarySubList.
+ * @param dataSelected Whether the default data subscription is updated
+ * @param voiceSelected Whether the default voice subscription is updated
+ * @param smsSelected Whether the default sms subscription is updated
+ * @return {@code true} if the primary subscription has changed due to the pSIM conversion,
+ * {@code false} otherwise.
+ */
+ private boolean setDefaultForPsimConversionChanged(int change, boolean dataSelected,
+ boolean voiceSelected, boolean smsSelected) {
+ if (!mFeatureFlags.supportPsimToEsimConversion()) {
+ log("pSIM to eSIM conversion is not supported");
+ return false;
+ }
+ if (mSubscriptionManagerService.isEsimBootStrapProvisioningActivated()) {
+ log("esim bootstrap activation in progress, skip notification");
+ return false;
+ }
+
+ @TelephonyManager.DefaultSubscriptionSelectType
+ int simSelectDialogType = getSimSelectDialogType(
+ change, dataSelected, voiceSelected, smsSelected);
+ SimCombinationWarningParams simCombinationParams = getSimCombinationWarningParams(change);
+ log("[setDefaultForPsimConversionChanged]showing dialog type:" + simSelectDialogType);
+ if (simSelectDialogType != EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE
+ || simCombinationParams.mWarningType != EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE) {
+ log("[setDefaultForPsimConversionChanged]Converted pSIM:" + mConvertedPsimSubId);
+ int subId = getConvertedPsimSubscriptionId();
+ if (subId != INVALID_SUBSCRIPTION_ID && subId != mConvertedPsimSubId) {
+ // If a primary subscription is removed and only one is left active, ask user
+ // for preferred sub selection if any default setting is not set.
+ if (simSelectDialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL) {
+ // check if pSIM's preference is voice.
+ if (mSubscriptionManagerService.getDefaultVoiceSubId()
+ == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ mNeedSetDefaultVoice = true;
+ }
+ // check if pSIM's preference is sms.
+ if (mSubscriptionManagerService.getDefaultSmsSubId()
+ == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ mNeedSetDefaultSms = true;
+ }
+ // check if pSIM's preference is data.
+ if (mSubscriptionManagerService.getDefaultDataSubId()
+ == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ mNeedSetDefaultData = true;
+ }
+ log("select type all, set preferred SIM :" + mPrimarySubList.get(0));
+ mSubscriptionManagerService.setDefaultVoiceSubId(mPrimarySubList.get(0));
+ mSubscriptionManagerService.setDefaultSmsSubId(mPrimarySubList.get(0));
+ mSubscriptionManagerService.setDefaultDataSubId(mPrimarySubList.get(0));
+ return true;
+ } else if (simSelectDialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA) {
+ // If another primary subscription is added or default data is not selected, ask
+ // user to select default for data as it's most important.
+ int newSubId = mPrimarySubList.get(0);
+ log("need to set voice:" + mNeedSetDefaultVoice
+ + ", sms:" + mNeedSetDefaultSms
+ + ", data:" + mNeedSetDefaultData);
+ // if the converted pSIM's preference is voice, set the default
+ // setting for the changed primary subscription to voice.
+ if (mNeedSetDefaultVoice) {
+ log("set preferred call, subId:" + newSubId);
+ mSubscriptionManagerService.setDefaultVoiceSubId(newSubId);
+ mNeedSetDefaultVoice = false;
+ }
+ // if the converted pSIM's preference is sms, set the default
+ // setting for the changed primary subscription to sms.
+ if (mNeedSetDefaultSms) {
+ log("set preferred sms, subId:" + newSubId);
+ mSubscriptionManagerService.setDefaultSmsSubId(newSubId);
+ mNeedSetDefaultSms = false;
+ }
+ // if the converted pSIM's preference is data, set the default
+ // setting for the changed primary subscription to data.
+ if (mNeedSetDefaultData) {
+ log("set preferred data, subId:" + newSubId);
+ mSubscriptionManagerService.setDefaultDataSubId(newSubId);
+ mNeedSetDefaultData = false;
+ }
+ mConvertedPsimSubId = subId;
+ log("set converted pSIM subId:" + mConvertedPsimSubId);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private int getConvertedPsimSubscriptionId() {
+ // Check to see if any subscription has been converted due to the pSIM conversion.
+ // When the primary subscription is changed, if it is the same subscription as
+ // the previously converted subscription, it is not due to the pSIM conversion.
+ // So the dialog for preferred SIM/data pick should show.
+ // TODO(b/332261793): On Android W, we need to add CONVERTING status.
+ // The CONVERTING status allows us to determine if pSIM is in the process of converting,
+ // so we don't need to check for information about previously converted subscriptions.
+ int convertedSubId = INVALID_SUBSCRIPTION_ID;
+ if (mFeatureFlags.supportPsimToEsimConversion()) {
+ List<SubscriptionInfo> infos =
+ mSubscriptionManagerService.getAvailableSubscriptionInfoList(
+ mContext.getOpPackageName(), mContext.getAttributionTag());
+ for (SubscriptionInfo info : infos) {
+ if (!info.isEmbedded() && info.getTransferStatus() == TRANSFER_STATUS_CONVERTED) {
+ convertedSubId = info.getSubscriptionId();
+ }
+ }
+ }
+ log("getConvertedPsimSubscriptionId: convertedSubId=" + convertedSubId);
+ return convertedSubId;
+ }
+
private int getSimSelectDialogType(int change, boolean dataSelected,
boolean voiceSelected, boolean smsSelected) {
int dialogType = EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE;
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index c088406..aa62acb 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -150,10 +150,10 @@
*/
public abstract class Phone extends Handler implements PhoneInternalInterface {
- private static final String LOG_TAG = "Phone";
protected final static Object lockForRadioTechnologyChange = new Object();
+ private final String mLogTag;
protected final int USSD_MAX_QUEUE = 10;
// Key used to read and write the saved network selection numeric value
@@ -597,6 +597,7 @@
boolean unitTestMode, int phoneId,
TelephonyComponentFactory telephonyComponentFactory,
FeatureFlags featureFlags) {
+ mLogTag = "Phone-" + phoneId;
mPhoneId = phoneId;
mName = name;
mNotifier = notifier;
@@ -638,10 +639,10 @@
*/
mDoesRilSendMultipleCallRing = TelephonyProperties.ril_sends_multiple_call_ring()
.orElse(true);
- Rlog.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
+ Rlog.d(mLogTag, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
mCallRingDelay = TelephonyProperties.call_ring_delay().orElse(3000);
- Rlog.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
+ Rlog.d(mLogTag, "mCallRingDelay=" + mCallRingDelay);
// Initialize SMS stats
mSmsStats = new SmsStats(this);
@@ -779,12 +780,13 @@
case EVENT_SET_NETWORK_MANUAL_COMPLETE:
case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
handleSetSelectNetwork((AsyncResult) msg.obj);
+ onSetNetworkSelectionModeCompleted();
return;
}
switch(msg.what) {
case EVENT_CALL_RING:
- Rlog.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
+ Rlog.d(mLogTag, "Event EVENT_CALL_RING Received state=" + getState());
ar = (AsyncResult)msg.obj;
if (ar.exception == null) {
PhoneConstants.State state = getState();
@@ -800,7 +802,7 @@
break;
case EVENT_CALL_RING_CONTINUE:
- Rlog.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received state=" + getState());
+ Rlog.d(mLogTag, "Event EVENT_CALL_RING_CONTINUE Received state=" + getState());
if (getState() == PhoneConstants.State.RINGING) {
sendIncomingCallRingNotification(msg.arg1);
}
@@ -813,7 +815,7 @@
case EVENT_INITIATE_SILENT_REDIAL:
// This is an ImsPhone -> GsmCdmaPhone redial
// See ImsPhone#initiateSilentRedial
- Rlog.d(LOG_TAG, "Event EVENT_INITIATE_SILENT_REDIAL Received");
+ Rlog.d(mLogTag, "Event EVENT_INITIATE_SILENT_REDIAL Received");
ar = (AsyncResult) msg.obj;
if ((ar.exception == null) && (ar.result != null)) {
SilentRedialParam result = (SilentRedialParam) ar.result;
@@ -827,13 +829,13 @@
// one with a callback registered to TelephonyConnection. Notify the
// redial happened over that Phone so that it can be replaced with the
// new GSM/CDMA Connection.
- Rlog.d(LOG_TAG, "Notify redial connection changed cn: " + cn);
+ Rlog.d(mLogTag, "Notify redial connection changed cn: " + cn);
if (mImsPhone != null) {
// Don't care it is null or not.
mImsPhone.notifyRedialConnectionChanged(cn);
}
} catch (CallStateException e) {
- Rlog.e(LOG_TAG, "silent redial failed: " + e);
+ Rlog.e(mLogTag, "silent redial failed: " + e);
if (mImsPhone != null) {
mImsPhone.notifyRedialConnectionChanged(null);
}
@@ -846,7 +848,7 @@
if (ar.exception == null) {
handleSrvccStateChanged((int[]) ar.result);
} else {
- Rlog.e(LOG_TAG, "Srvcc exception: " + ar.exception);
+ Rlog.e(mLogTag, "Srvcc exception: " + ar.exception);
}
break;
@@ -865,7 +867,7 @@
try {
mUsageSettingFromModem = ((int[]) ar.result)[0];
} catch (NullPointerException | ClassCastException e) {
- Rlog.e(LOG_TAG, "Invalid response for usage setting " + ar.result);
+ Rlog.e(mLogTag, "Invalid response for usage setting " + ar.result);
break;
}
@@ -880,9 +882,9 @@
if (ce.getCommandError() == CommandException.Error.REQUEST_NOT_SUPPORTED) {
mIsUsageSettingSupported = false;
}
- Rlog.w(LOG_TAG, "Unexpected failure to retrieve usage setting " + ce);
+ Rlog.w(mLogTag, "Unexpected failure to retrieve usage setting " + ce);
} catch (ClassCastException unused) {
- Rlog.e(LOG_TAG, "Invalid Exception for usage setting " + ar.exception);
+ Rlog.e(mLogTag, "Invalid Exception for usage setting " + ar.exception);
break; // technically extraneous, but good hygiene
}
}
@@ -895,9 +897,9 @@
if (ce.getCommandError() == CommandException.Error.REQUEST_NOT_SUPPORTED) {
mIsUsageSettingSupported = false;
}
- Rlog.w(LOG_TAG, "Unexpected failure to set usage setting " + ce);
+ Rlog.w(mLogTag, "Unexpected failure to set usage setting " + ce);
} catch (ClassCastException unused) {
- Rlog.e(LOG_TAG, "Invalid Exception for usage setting " + ar.exception);
+ Rlog.e(mLogTag, "Invalid Exception for usage setting " + ar.exception);
break; // technically extraneous, but good hygiene
}
}
@@ -931,7 +933,7 @@
}
private void handleSrvccStateChanged(int[] ret) {
- Rlog.d(LOG_TAG, "handleSrvccStateChanged");
+ Rlog.d(mLogTag, "handleSrvccStateChanged");
ArrayList<Connection> conn = null;
Phone imsPhone = mImsPhone;
@@ -948,7 +950,7 @@
conn = imsPhone.getHandoverConnection();
migrateFrom(imsPhone);
} else {
- Rlog.d(LOG_TAG, "HANDOVER_STARTED: mImsPhone null");
+ Rlog.d(mLogTag, "HANDOVER_STARTED: mImsPhone null");
}
break;
case TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED:
@@ -1186,7 +1188,7 @@
to.add((Registrant) from.get(i));
}
} else {
- Rlog.d(LOG_TAG, "msg is null");
+ Rlog.d(mLogTag, "msg is null");
}
}
}
@@ -1483,7 +1485,7 @@
*/
@UnsupportedAppUsage
public void setNetworkSelectionModeAutomatic(Message response) {
- Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic, querying current mode");
+ Rlog.d(mLogTag, "setNetworkSelectionModeAutomatic, querying current mode");
// we don't want to do this unnecessarily - it actually causes
// the radio to repeat network selection and is costly
// first check if we're already in automatic mode
@@ -1518,11 +1520,11 @@
nsm.operatorAlphaShort = "";
if (doAutomatic) {
- Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic - set network selection auto");
+ Rlog.d(mLogTag, "setNetworkSelectionModeAutomatic - set network selection auto");
Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
mCi.setNetworkSelectionModeAutomatic(msg);
} else {
- Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic - already auto, ignoring");
+ Rlog.d(mLogTag, "setNetworkSelectionModeAutomatic - already auto, ignoring");
// let the calling application know that the we are ignoring automatic mode switch.
if (nsm.message != null) {
nsm.message.arg1 = ALREADY_IN_AUTO_SELECTION;
@@ -1536,6 +1538,12 @@
}
/**
+ * Called when setting network selection mode is complete.
+ */
+ protected void onSetNetworkSelectionModeCompleted() {
+ }
+
+ /**
* Query the radio for the current network selection mode.
*
* Return values:
@@ -1610,10 +1618,10 @@
// commit and log the result.
if (!editor.commit()) {
- Rlog.e(LOG_TAG, "failed to commit network selection preference");
+ Rlog.e(mLogTag, "failed to commit network selection preference");
}
} else {
- Rlog.e(LOG_TAG, "Cannot update network selection preference due to invalid subId " +
+ Rlog.e(mLogTag, "Cannot update network selection preference due to invalid subId " +
subId);
}
}
@@ -1624,7 +1632,7 @@
* @param nsm PLMN info of the selected network
*/
protected void updateManualNetworkSelection(NetworkSelectMessage nsm) {
- Rlog.e(LOG_TAG, "updateManualNetworkSelection() should be overridden");
+ Rlog.e(mLogTag, "updateManualNetworkSelection() should be overridden");
}
/**
@@ -1634,7 +1642,7 @@
// look for our wrapper within the asyncresult, skip the rest if it
// is null.
if (!(ar.userObj instanceof NetworkSelectMessage)) {
- Rlog.e(LOG_TAG, "unexpected result from user object.");
+ Rlog.e(mLogTag, "unexpected result from user object.");
return;
}
@@ -1698,12 +1706,12 @@
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sp.edit();
editor.putInt(CLIR_KEY + getSubId(), commandInterfaceCLIRMode);
- Rlog.i(LOG_TAG, "saveClirSetting: " + CLIR_KEY + getSubId() + "="
+ Rlog.i(mLogTag, "saveClirSetting: " + CLIR_KEY + getSubId() + "="
+ commandInterfaceCLIRMode);
// Commit and log the result.
if (!editor.commit()) {
- Rlog.e(LOG_TAG, "Failed to commit CLIR preference");
+ Rlog.e(mLogTag, "Failed to commit CLIR preference");
}
}
@@ -1925,13 +1933,13 @@
IccFileHandler fh;
if (uiccApplication == null) {
- Rlog.d(LOG_TAG, "getIccFileHandler: uiccApplication == null, return null");
+ Rlog.d(mLogTag, "getIccFileHandler: uiccApplication == null, return null");
fh = null;
} else {
fh = uiccApplication.getIccFileHandler();
}
- Rlog.d(LOG_TAG, "getIccFileHandler: fh=" + fh);
+ Rlog.d(mLogTag, "getIccFileHandler: fh=" + fh);
return fh;
}
@@ -2018,7 +2026,7 @@
* Retrieves the SignalStrengthController of the phone instance.
*/
public SignalStrengthController getSignalStrengthController() {
- Log.wtf(LOG_TAG, "getSignalStrengthController return null.");
+ Log.wtf(mLogTag, "getSignalStrengthController return null.");
return null;
}
@@ -2052,7 +2060,7 @@
* Update voice mail count related fields and notify listeners
*/
public void updateVoiceMail() {
- Rlog.e(LOG_TAG, "updateVoiceMail() should be overridden");
+ Rlog.e(mLogTag, "updateVoiceMail() should be overridden");
}
public AppType getCurrentUiccAppType() {
@@ -2178,7 +2186,7 @@
if (SubscriptionManager.isValidSubscriptionId(subId)) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
status = sp.getInt(CF_STATUS + subId, IccRecords.CALL_FORWARDING_STATUS_UNKNOWN);
- Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: for subId " + subId + "= " +
+ Rlog.d(mLogTag, "getCallForwardingIndicatorFromSharedPref: for subId " + subId + "= " +
status);
// Check for old preference if status is UNKNOWN for current subId. This part of the
// code is needed only when upgrading from M to N.
@@ -2192,9 +2200,9 @@
status = sp.getInt(CF_STATUS, IccRecords.CALL_FORWARDING_STATUS_DISABLED);
setCallForwardingIndicatorInSharedPref(
status == IccRecords.CALL_FORWARDING_STATUS_ENABLED ? true : false);
- Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: " + status);
+ Rlog.d(mLogTag, "getCallForwardingIndicatorFromSharedPref: " + status);
} else {
- Rlog.d(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: returning " +
+ Rlog.d(mLogTag, "getCallForwardingIndicatorFromSharedPref: returning " +
"DISABLED as status for matching subscriberId not found");
}
@@ -2206,7 +2214,7 @@
}
}
} else {
- Rlog.e(LOG_TAG, "getCallForwardingIndicatorFromSharedPref: invalid subId " + subId);
+ Rlog.e(mLogTag, "getCallForwardingIndicatorFromSharedPref: invalid subId " + subId);
}
return status;
}
@@ -2215,7 +2223,7 @@
int status = enable ? IccRecords.CALL_FORWARDING_STATUS_ENABLED :
IccRecords.CALL_FORWARDING_STATUS_DISABLED;
int subId = getSubId();
- Rlog.i(LOG_TAG, "setCallForwardingIndicatorInSharedPref: Storing status = " + status +
+ Rlog.i(mLogTag, "setCallForwardingIndicatorInSharedPref: Storing status = " + status +
" in pref " + CF_STATUS + subId);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
@@ -2258,7 +2266,7 @@
*/
public boolean getCallForwardingIndicator() {
if (getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
- Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
+ Rlog.e(mLogTag, "getCallForwardingIndicator: not possible in CDMA");
return false;
}
IccRecords r = getIccRecords();
@@ -2269,7 +2277,7 @@
if (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_UNKNOWN) {
callForwardingIndicator = getCallForwardingIndicatorFromSharedPref();
}
- Rlog.v(LOG_TAG, "getCallForwardingIndicator: iccForwardingFlag=" + (r != null
+ Rlog.v(mLogTag, "getCallForwardingIndicator: iccForwardingFlag=" + (r != null
? r.getVoiceCallForwardingFlag() : "null") + ", sharedPrefFlag="
+ getCallForwardingIndicatorFromSharedPref());
return (callForwardingIndicator == IccRecords.CALL_FORWARDING_STATUS_ENABLED);
@@ -2466,7 +2474,7 @@
for (String pair : result.trim().split(",")) {
String[] networkTypesValues = (pair.trim().toLowerCase(Locale.ROOT)).split("=");
if (networkTypesValues.length != 2) {
- Rlog.e(LOG_TAG, "Invalid ALLOWED_NETWORK_TYPES from DB, value = " + pair);
+ Rlog.e(mLogTag, "Invalid ALLOWED_NETWORK_TYPES from DB, value = " + pair);
continue;
}
int key = convertAllowedNetworkTypeDbNameToMapIndex(networkTypesValues[0]);
@@ -2486,7 +2494,7 @@
}
}
} catch (NumberFormatException e) {
- Rlog.e(LOG_TAG, "allowedNetworkTypes NumberFormat exception" + e);
+ Rlog.e(mLogTag, "allowedNetworkTypes NumberFormat exception" + e);
}
for (int key : oldAllowedNetworkTypes.keySet()) {
@@ -2605,7 +2613,7 @@
protected void updateAllowedNetworkTypes(Message response) {
int modemRaf = getRadioAccessFamily();
if (modemRaf == RadioAccessFamily.RAF_UNKNOWN) {
- Rlog.d(LOG_TAG, "setPreferredNetworkType: Abort, unknown RAF: "
+ Rlog.d(mLogTag, "setPreferredNetworkType: Abort, unknown RAF: "
+ modemRaf);
if (response != null) {
CommandException ex;
@@ -2714,7 +2722,7 @@
* @param onComplete a callback message when the action is completed
*/
public void setUiTTYMode(int uiTtyMode, Message onComplete) {
- Rlog.d(LOG_TAG, "unexpected setUiTTYMode method call");
+ Rlog.d(mLogTag, "unexpected setUiTTYMode method call");
}
/**
@@ -2841,7 +2849,7 @@
public boolean eraseDataInSharedPreferences() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = sp.edit();
- Rlog.d(LOG_TAG, "Erase all data saved in SharedPreferences");
+ Rlog.d(mLogTag, "Erase all data saved in SharedPreferences");
editor.clear();
return editor.commit();
}
@@ -3087,7 +3095,7 @@
isVideoCallOrConference(mImsPhone.getBackgroundCall()) ||
isVideoCallOrConference(mImsPhone.getRingingCall());
}
- Rlog.d(LOG_TAG, "isImsVideoCallOrConferencePresent: " + isPresent);
+ Rlog.d(mLogTag, "isImsVideoCallOrConferencePresent: " + isPresent);
return isPresent;
}
@@ -3112,7 +3120,7 @@
int subId = getSubId();
if (SubscriptionManager.isValidSubscriptionId(subId)) {
- Rlog.d(LOG_TAG, "setVoiceMessageCount: Storing Voice Mail Count = " + countWaiting +
+ Rlog.d(mLogTag, "setVoiceMessageCount: Storing Voice Mail Count = " + countWaiting +
" for mVmCountKey = " + VM_COUNT + subId + " in preferences.");
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
@@ -3120,16 +3128,16 @@
editor.putInt(VM_COUNT + subId, countWaiting);
editor.apply();
} else {
- Rlog.e(LOG_TAG, "setVoiceMessageCount in sharedPreference: invalid subId " + subId);
+ Rlog.e(mLogTag, "setVoiceMessageCount in sharedPreference: invalid subId " + subId);
}
// store voice mail count in SIM
IccRecords records = UiccController.getInstance().getIccRecords(
mPhoneId, UiccController.APP_FAM_3GPP);
if (records != null) {
- Rlog.d(LOG_TAG, "setVoiceMessageCount: updating SIM Records");
+ Rlog.d(mLogTag, "setVoiceMessageCount: updating SIM Records");
records.setVoiceMessageWaiting(1, countWaiting);
} else {
- Rlog.d(LOG_TAG, "setVoiceMessageCount: SIM Records not found");
+ Rlog.d(mLogTag, "setVoiceMessageCount: SIM Records not found");
}
// notify listeners of voice mail
notifyMessageWaitingIndicator();
@@ -3145,7 +3153,7 @@
int countFromSP = sp.getInt(VM_COUNT + subId, invalidCount);
if (countFromSP != invalidCount) {
countVoiceMessages = countFromSP;
- Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: from preference for subId " + subId +
+ Rlog.d(mLogTag, "getStoredVoiceMessageCount: from preference for subId " + subId +
"= " + countVoiceMessages);
} else {
// Check for old preference if count not found for current subId. This part of the
@@ -3158,10 +3166,10 @@
// get voice mail count from preferences
countVoiceMessages = sp.getInt(VM_COUNT, 0);
setVoiceMessageCount(countVoiceMessages);
- Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: from preference = " +
+ Rlog.d(mLogTag, "getStoredVoiceMessageCount: from preference = " +
countVoiceMessages);
} else {
- Rlog.d(LOG_TAG, "getStoredVoiceMessageCount: returning 0 as count for " +
+ Rlog.d(mLogTag, "getStoredVoiceMessageCount: returning 0 as count for " +
"matching subscriberId not found");
}
@@ -3173,7 +3181,7 @@
}
}
} else {
- Rlog.e(LOG_TAG, "getStoredVoiceMessageCount: invalid subId " + subId);
+ Rlog.e(mLogTag, "getStoredVoiceMessageCount: invalid subId " + subId);
}
return countVoiceMessages;
}
@@ -3706,17 +3714,17 @@
}
}
} catch (NumberFormatException e) {
- Rlog.e(LOG_TAG, "Exception in getProvisioningUrlBaseFromFile: " + e);
+ Rlog.e(mLogTag, "Exception in getProvisioningUrlBaseFromFile: " + e);
}
}
}
return null;
} catch (FileNotFoundException e) {
- Rlog.e(LOG_TAG, "Carrier Provisioning Urls file not found");
+ Rlog.e(mLogTag, "Carrier Provisioning Urls file not found");
} catch (XmlPullParserException e) {
- Rlog.e(LOG_TAG, "Xml parser exception reading Carrier Provisioning Urls file: " + e);
+ Rlog.e(mLogTag, "Xml parser exception reading Carrier Provisioning Urls file: " + e);
} catch (IOException e) {
- Rlog.e(LOG_TAG, "I/O exception reading Carrier Provisioning Urls file: " + e);
+ Rlog.e(mLogTag, "I/O exception reading Carrier Provisioning Urls file: " + e);
}
return null;
}
@@ -3728,9 +3736,9 @@
String url = getProvisioningUrlBaseFromFile();
if (TextUtils.isEmpty(url)) {
url = mContext.getResources().getString(R.string.mobile_provisioning_url);
- Rlog.d(LOG_TAG, "getMobileProvisioningUrl: url from resource =" + url);
+ Rlog.d(mLogTag, "getMobileProvisioningUrl: url from resource =" + url);
} else {
- Rlog.d(LOG_TAG, "getMobileProvisioningUrl: url from File =" + url);
+ Rlog.d(mLogTag, "getMobileProvisioningUrl: url from File =" + url);
}
// Populate the iccid, imei and phone number in the provisioning url.
if (!TextUtils.isEmpty(url)) {
@@ -3804,7 +3812,7 @@
* version scoped to their packages
*/
public void notifyNewRingingConnectionP(Connection cn) {
- Rlog.i(LOG_TAG, String.format(
+ Rlog.i(mLogTag, String.format(
"notifyNewRingingConnection: phoneId=[%d], connection=[%s], registrants=[%s]",
getPhoneId(), cn, getNewRingingConnectionRegistrantsAsString()));
if (!mIsVoiceCapable)
@@ -3860,12 +3868,12 @@
private void sendIncomingCallRingNotification(int token) {
if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
(token == mCallRingContinueToken)) {
- Rlog.d(LOG_TAG, "Sending notifyIncomingRing");
+ Rlog.d(mLogTag, "Sending notifyIncomingRing");
notifyIncomingRing();
sendMessageDelayed(
obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
} else {
- Rlog.d(LOG_TAG, "Ignoring ring notification request,"
+ Rlog.d(mLogTag, "Ignoring ring notification request,"
+ " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
+ " token=" + token
+ " mCallRingContinueToken=" + mCallRingContinueToken
@@ -3905,7 +3913,7 @@
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public IsimRecords getIsimRecords() {
- Rlog.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices");
+ Rlog.e(mLogTag, "getIsimRecords() is only supported on LTE devices");
return null;
}
@@ -3938,7 +3946,7 @@
*/
public void setVoiceMessageWaiting(int line, int countWaiting) {
// This function should be overridden by class GsmCdmaPhone.
- Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive Phone.");
+ Rlog.e(mLogTag, "Error! This function should never be executed, inactive Phone.");
}
/**
@@ -4018,6 +4026,15 @@
return;
}
+ /**
+ * Deletes all the keys for a given Carrier from the device keystore.
+ * @param carrierId : the carrier ID which needs to be matched in the delete query
+ * @param simOperator : MccMnc which needs to be matched in the delete query.
+ */
+ public void deleteCarrierInfoForImsiEncryption(int carrierId, String simOperator) {
+
+ }
+
public int getCarrierId() {
return TelephonyManager.UNKNOWN_CARRIER_ID;
}
@@ -4188,7 +4205,7 @@
isImsRegistered = sst.isImsRegistered();
}
}
- Rlog.d(LOG_TAG, "isImsRegistered =" + isImsRegistered);
+ Rlog.d(mLogTag, "isImsRegistered =" + isImsRegistered);
return isImsRegistered;
}
@@ -4202,7 +4219,7 @@
if (imsPhone != null) {
isWifiCallingEnabled = imsPhone.isWifiCallingEnabled();
}
- Rlog.d(LOG_TAG, "isWifiCallingEnabled =" + isWifiCallingEnabled);
+ Rlog.d(mLogTag, "isWifiCallingEnabled =" + isWifiCallingEnabled);
return isWifiCallingEnabled;
}
@@ -4216,7 +4233,7 @@
if (imsPhone != null) {
isAvailable = imsPhone.isImsCapabilityAvailable(capability, regTech);
}
- Rlog.d(LOG_TAG, "isImsCapabilityAvailable, capability=" + capability + ", regTech="
+ Rlog.d(mLogTag, "isImsCapabilityAvailable, capability=" + capability + ", regTech="
+ regTech + ", isAvailable=" + isAvailable);
return isAvailable;
}
@@ -4240,7 +4257,7 @@
if (imsPhone != null) {
isVolteEnabled = imsPhone.isVoiceOverCellularImsEnabled();
}
- Rlog.d(LOG_TAG, "isVoiceOverCellularImsEnabled=" + isVolteEnabled);
+ Rlog.d(mLogTag, "isVoiceOverCellularImsEnabled=" + isVolteEnabled);
return isVolteEnabled;
}
@@ -4254,7 +4271,7 @@
if (imsPhone != null) {
regTech = imsPhone.getImsRegistrationTech();
}
- Rlog.d(LOG_TAG, "getImsRegistrationTechnology =" + regTech);
+ Rlog.d(mLogTag, "getImsRegistrationTechnology =" + regTech);
return regTech;
}
@@ -4836,7 +4853,7 @@
public boolean isDeviceIdle() {
DeviceStateMonitor dsm = getDeviceStateMonitor();
if (dsm == null) {
- Rlog.e(LOG_TAG, "isDeviceIdle: DeviceStateMonitor is null");
+ Rlog.e(mLogTag, "isDeviceIdle: DeviceStateMonitor is null");
return false;
}
return !dsm.shouldEnableHighPowerConsumptionIndications();
@@ -4850,7 +4867,7 @@
public void notifyDeviceIdleStateChanged(boolean isIdle) {
SignalStrengthController ssc = getSignalStrengthController();
if (ssc == null) {
- Rlog.e(LOG_TAG, "notifyDeviceIdleStateChanged: SignalStrengthController is null");
+ Rlog.e(mLogTag, "notifyDeviceIdleStateChanged: SignalStrengthController is null");
return;
}
ssc.onDeviceIdleStateChanged(isIdle);
@@ -4899,15 +4916,15 @@
/**
* @return The data network controller
*/
- public @Nullable DataNetworkController getDataNetworkController() {
+ public @NonNull DataNetworkController getDataNetworkController() {
return mDataNetworkController;
}
/**
* @return The data settings manager
*/
- public @Nullable DataSettingsManager getDataSettingsManager() {
- if (mDataNetworkController == null) return null;
+ @NonNull
+ public DataSettingsManager getDataSettingsManager() {
return mDataNetworkController.getDataSettingsManager();
}
@@ -5282,7 +5299,7 @@
* @param type for callback mode entry.
*/
public void startCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type) {
- Rlog.d(LOG_TAG, "startCallbackMode:type=" + type);
+ Rlog.d(mLogTag, "startCallbackMode:type=" + type);
mNotifier.notifyCallbackModeStarted(this, type);
}
@@ -5293,10 +5310,22 @@
*/
public void stopCallbackMode(@TelephonyManager.EmergencyCallbackModeType int type,
@TelephonyManager.EmergencyCallbackModeStopReason int reason) {
- Rlog.d(LOG_TAG, "stopCallbackMode:type=" + type + ", reason=" + reason);
+ Rlog.d(mLogTag, "stopCallbackMode:type=" + type + ", reason=" + reason);
mNotifier.notifyCallbackModeStopped(this, type, reason);
}
+ /**
+ * Notify carrier roaming non-terrestrial network mode changed
+ * @param active {@code true} If the device is connected to carrier roaming
+ * non-terrestrial network or was connected within the
+ * {CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
+ * duration, {code false} otherwise.
+ */
+ public void notifyCarrierRoamingNtnModeChanged(boolean active) {
+ logd("notifyCarrierRoamingNtnModeChanged active:" + active);
+ mNotifier.notifyCarrierRoamingNtnModeChanged(this, active);
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Phone: subId=" + getSubId());
pw.println(" mPhoneId=" + mPhoneId);
@@ -5319,7 +5348,7 @@
pw.println(" isDnsCheckDisabled()=" + isDnsCheckDisabled());
pw.println(" getUnitTestMode()=" + getUnitTestMode());
pw.println(" getState()=" + getState());
- pw.println(" getIccSerialNumber()=" + Rlog.pii(LOG_TAG, getIccSerialNumber()));
+ pw.println(" getIccSerialNumber()=" + Rlog.pii(mLogTag, getIccSerialNumber()));
pw.println(" getIccRecordsLoaded()=" + getIccRecordsLoaded());
pw.println(" getMessageWaitingIndicator()=" + getMessageWaitingIndicator());
pw.println(" getCallForwardingIndicator()=" + getCallForwardingIndicator());
@@ -5504,18 +5533,14 @@
}
private void logd(String s) {
- Rlog.d(LOG_TAG, "[" + mPhoneId + "] " + s);
+ Rlog.d(mLogTag, "[" + mPhoneId + "] " + s);
}
private void logi(String s) {
- Rlog.i(LOG_TAG, "[" + mPhoneId + "] " + s);
+ Rlog.i(mLogTag, "[" + mPhoneId + "] " + s);
}
private void loge(String s) {
- Rlog.e(LOG_TAG, "[" + mPhoneId + "] " + s);
- }
-
- private static String pii(String s) {
- return Rlog.pii(LOG_TAG, s);
+ Rlog.e(mLogTag, "[" + mPhoneId + "] " + s);
}
}
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index ef96d89..ffa5b69 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -45,6 +45,7 @@
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Optional;
@@ -97,7 +98,9 @@
private static PhoneConfigurationManager sInstance = null;
private final Context mContext;
- private PhoneCapability mStaticCapability;
+ // Static capability retrieved from the modem - may be null in the case where no info has been
+ // retrieved yet.
+ private PhoneCapability mStaticCapability = null;
private final Set<Integer> mSlotsSupportingSimultaneousCellularCalls = new HashSet<>(3);
private final Set<Integer> mSubIdsSupportingSimultaneousCellularCalls = new HashSet<>(3);
private final HashSet<Consumer<Set<Integer>>> mSimultaneousCellularCallingListeners =
@@ -151,8 +154,6 @@
mFeatureFlags = featureFlags;
// TODO: send commands to modem once interface is ready.
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- //initialize with default, it'll get updated when RADIO is ON/AVAILABLE
- mStaticCapability = getDefaultCapability();
mRadioConfig = RadioConfig.getInstance();
mHandler = new ConfigManagerHandler();
mPhoneStatusMap = new HashMap<>();
@@ -256,7 +257,8 @@
boolean halSupportSimulCalling = mRadioConfig != null
&& mRadioConfig.getRadioConfigProxy(null).getVersion().greaterOrEqual(
RIL.RADIO_HAL_VERSION_2_2)
- && getPhoneCount() > 1 && mStaticCapability.getMaxActiveVoiceSubscriptions() > 1;
+ && getPhoneCount() > 1
+ && getCellularStaticPhoneCapability().getMaxActiveVoiceSubscriptions() > 1;
// Register for simultaneous calling support changes in the modem if the HAL supports it
if (halSupportSimulCalling) {
updateSimultaneousCallingSupport();
@@ -318,7 +320,7 @@
log("Unable to add phoneStatus to cache. "
+ "No phone object provided for event " + msg.what);
}
- getStaticPhoneCapability();
+ updateRadioCapability();
break;
case EVENT_SWITCH_DSDS_CONFIG_DONE:
ar = (AsyncResult) msg.obj;
@@ -343,7 +345,7 @@
case EVENT_GET_PHONE_CAPABILITY_DONE:
ar = (AsyncResult) msg.obj;
if (ar != null && ar.exception == null) {
- mStaticCapability = (PhoneCapability) ar.result;
+ setStaticPhoneCapability((PhoneCapability) ar.result);
notifyCapabilityChanged();
for (Listener l : mListeners) {
l.onPhoneCapabilityChanged();
@@ -376,12 +378,12 @@
}
ar = (AsyncResult) msg.obj;
if (ar != null && ar.exception == null) {
- int[] returnedIntArray = (int[]) ar.result;
+ List<Integer> returnedArrayList = (List<Integer>) ar.result;
if (!mSlotsSupportingSimultaneousCellularCalls.isEmpty()) {
mSlotsSupportingSimultaneousCellularCalls.clear();
}
int maxValidPhoneSlot = getPhoneCount() - 1;
- for (int i : returnedIntArray) {
+ for (int i : returnedArrayList) {
if (i < 0 || i > maxValidPhoneSlot) {
loge("Invalid slot supporting DSDA =" + i + ". Disabling DSDA.");
mSlotsSupportingSimultaneousCellularCalls.clear();
@@ -534,21 +536,43 @@
}
/**
- * get static overall phone capabilities for all phones.
+ * @return static overall phone capabilities for all phones, including voice overrides.
*/
public synchronized PhoneCapability getStaticPhoneCapability() {
- if (getDefaultCapability().equals(mStaticCapability)) {
- log("getStaticPhoneCapability: sending the request for getting PhoneCapability");
- Message callback = Message.obtain(
- mHandler, EVENT_GET_PHONE_CAPABILITY_DONE);
- mRadioConfig.getPhoneCapability(callback);
- }
- mStaticCapability = maybeOverrideMaxActiveVoiceSubscriptions(mStaticCapability);
- log("getStaticPhoneCapability: mStaticCapability " + mStaticCapability);
+ boolean isDefault = mStaticCapability == null;
+ PhoneCapability caps = isDefault ? getDefaultCapability() : mStaticCapability;
+ caps = maybeOverrideMaxActiveVoiceSubscriptions(caps);
+ log("getStaticPhoneCapability: isDefault=" + isDefault + ", caps=" + caps);
+ return caps;
+ }
+
+ /**
+ * @return untouched capabilities returned from the modem
+ */
+ private synchronized PhoneCapability getCellularStaticPhoneCapability() {
+ log("getCellularStaticPhoneCapability: mStaticCapability " + mStaticCapability);
return mStaticCapability;
}
/**
+ * Caches the static PhoneCapability returned by the modem
+ */
+ public synchronized void setStaticPhoneCapability(PhoneCapability capability) {
+ log("setStaticPhoneCapability: mStaticCapability " + capability);
+ mStaticCapability = capability;
+ }
+
+ /**
+ * Query the modem to return its static PhoneCapability and cache it
+ */
+ @VisibleForTesting
+ public void updateRadioCapability() {
+ log("updateRadioCapability: sending the request for getting PhoneCapability");
+ Message callback = Message.obtain(mHandler, EVENT_GET_PHONE_CAPABILITY_DONE);
+ mRadioConfig.getPhoneCapability(callback);
+ }
+
+ /**
* get configuration related status of each phone.
*/
public PhoneCapability getCurrentPhoneCapability() {
@@ -556,12 +580,11 @@
}
public int getNumberOfModemsWithSimultaneousDataConnections() {
- return mStaticCapability.getMaxActiveDataSubscriptions();
+ return getStaticPhoneCapability().getMaxActiveDataSubscriptions();
}
public int getNumberOfModemsWithSimultaneousVoiceConnections() {
- return maybeOverrideMaxActiveVoiceSubscriptions(mStaticCapability)
- .getMaxActiveVoiceSubscriptions();
+ return getStaticPhoneCapability().getMaxActiveVoiceSubscriptions();
}
public boolean isVirtualDsdaEnabled() {
@@ -591,8 +614,7 @@
}
private void notifyCapabilityChanged() {
- mNotifier.notifyPhoneCapabilityChanged(maybeOverrideMaxActiveVoiceSubscriptions(
- mStaticCapability));
+ mNotifier.notifyPhoneCapabilityChanged(getStaticPhoneCapability());
}
/**
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 803fb19..d9c5c9c 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -187,7 +187,7 @@
Rlog.i(LOG_TAG, "Network Mode set to " + Integer.toString(networkModes[i]));
sCommandsInterfaces[i] = new RIL(context,
RadioAccessFamily.getRafFromNetworkType(networkModes[i]),
- cdmaSubscription, i);
+ cdmaSubscription, i, featureFlags);
}
if (numPhones > 0) {
@@ -312,7 +312,7 @@
for (int i = prevActiveModemCount; i < activeModemCount; i++) {
sCommandsInterfaces[i] = new RIL(context, RadioAccessFamily.getRafFromNetworkType(
RILConstants.PREFERRED_NETWORK_MODE),
- cdmaSubscription, i);
+ cdmaSubscription, i, sFeatureFlags);
sPhones[i] = createPhone(context, i);
if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_IMS)) {
diff --git a/src/java/com/android/internal/telephony/PhoneNotifier.java b/src/java/com/android/internal/telephony/PhoneNotifier.java
index cb6b199..9f459f5 100644
--- a/src/java/com/android/internal/telephony/PhoneNotifier.java
+++ b/src/java/com/android/internal/telephony/PhoneNotifier.java
@@ -153,4 +153,7 @@
/** Notify that simultaneous cellular calling subscriptions have changed */
void notifySimultaneousCellularCallingSubscriptionsChanged(Set<Integer> subIds);
+
+ /** Notify carrier roaming non-terrestrial network mode changed. **/
+ void notifyCarrierRoamingNtnModeChanged(Phone sender, boolean active);
}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 8b3be1e..8abebe2 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -88,6 +88,7 @@
import com.android.internal.telephony.cdma.CdmaInformationRecords;
import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
import com.android.internal.telephony.emergency.EmergencyConstants;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import com.android.internal.telephony.imsphone.ImsCallInfo;
import com.android.internal.telephony.metrics.ModemRestartStats;
@@ -151,6 +152,15 @@
public static final HalVersion RADIO_HAL_VERSION_UNKNOWN = HalVersion.UNKNOWN;
/** @hide */
+ public static final HalVersion RADIO_HAL_VERSION_1_1 = new HalVersion(1, 1);
+
+ /** @hide */
+ public static final HalVersion RADIO_HAL_VERSION_1_2 = new HalVersion(1, 2);
+
+ /** @hide */
+ public static final HalVersion RADIO_HAL_VERSION_1_3 = new HalVersion(1, 3);
+
+ /** @hide */
public static final HalVersion RADIO_HAL_VERSION_1_4 = new HalVersion(1, 4);
/** @hide */
@@ -197,6 +207,8 @@
boolean mIsRadioProxyInitialized = false;
+ Boolean mIsRadioVersion20Cached = null;
+
// When we are testing emergency calls using ril.test.emergencynumber, this will trigger test
// ECbM when the call is ended.
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -210,6 +222,8 @@
public static final int MAX_SERVICE_IDX = HAL_SERVICE_IMS;
+ @NonNull private final FeatureFlags mFeatureFlags;
+
/**
* An array of sets that records if services are disabled in the HAL for a specific phone ID
* slot to avoid further getService requests for that service. See XXX_SERVICE for the indices.
@@ -373,12 +387,27 @@
case EVENT_AIDL_PROXY_DEAD:
int aidlService = msg.arg1;
long msgCookie = (long) msg.obj;
- riljLog("handleMessage: EVENT_AIDL_PROXY_DEAD cookie = " + msgCookie
- + ", service = " + serviceToString(aidlService) + ", cookie = "
- + mServiceCookies.get(aidlService));
- if (msgCookie == mServiceCookies.get(aidlService).get()) {
- mIsRadioProxyInitialized = false;
- resetProxyAndRequestList(aidlService);
+ if (mFeatureFlags.combineRilDeathHandle()) {
+ if (msgCookie == mServiceCookies.get(aidlService).get()) {
+ riljLog("handleMessage: EVENT_AIDL_PROXY_DEAD cookie = " + msgCookie
+ + ", service = " + serviceToString(aidlService) + ", cookie = "
+ + mServiceCookies.get(aidlService));
+ mIsRadioProxyInitialized = false;
+ resetProxyAndRequestList(aidlService);
+ // Remove duplicate death message to avoid duplicate reset.
+ mRilHandler.removeMessages(EVENT_AIDL_PROXY_DEAD);
+ } else {
+ riljLog("Ignore stale EVENT_AIDL_PROXY_DEAD for service "
+ + serviceToString(aidlService));
+ }
+ } else {
+ riljLog("handleMessage: EVENT_AIDL_PROXY_DEAD cookie = " + msgCookie
+ + ", service = " + serviceToString(aidlService) + ", cookie = "
+ + mServiceCookies.get(aidlService));
+ if (msgCookie == mServiceCookies.get(aidlService).get()) {
+ mIsRadioProxyInitialized = false;
+ resetProxyAndRequestList(aidlService);
+ }
}
break;
}
@@ -423,24 +452,33 @@
public void serviceDied(long cookie) {
// Deal with service going away
riljLog("serviceDied");
- mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_RADIO_PROXY_DEAD,
- HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie));
+ if (mFeatureFlags.combineRilDeathHandle()) {
+ mRilHandler.sendMessageAtFrontOfQueue(mRilHandler.obtainMessage(
+ EVENT_RADIO_PROXY_DEAD,
+ HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie));
+ } else {
+ mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_RADIO_PROXY_DEAD,
+ HAL_SERVICE_RADIO, 0 /* ignored arg2 */, cookie));
+ }
}
}
private final class BinderServiceDeathRecipient implements IBinder.DeathRecipient {
private IBinder mBinder;
private final int mService;
+ private long mLinkedFlags;
BinderServiceDeathRecipient(int service) {
mService = service;
+ mLinkedFlags = 0;
}
public void linkToDeath(IBinder service) throws RemoteException {
if (service != null) {
riljLog("Linked to death for service " + serviceToString(mService));
mBinder = service;
- mBinder.linkToDeath(this, (int) mServiceCookies.get(mService).incrementAndGet());
+ mLinkedFlags = mServiceCookies.get(mService).incrementAndGet();
+ mBinder.linkToDeath(this, (int) mLinkedFlags);
} else {
riljLoge("Unable to link to death for service " + serviceToString(mService));
}
@@ -448,32 +486,58 @@
public synchronized void unlinkToDeath() {
if (mBinder != null) {
- mBinder.unlinkToDeath(this, 0);
+ mBinder.unlinkToDeath(this, (int) mLinkedFlags);
mBinder = null;
+ mLinkedFlags = 0;
}
}
@Override
public void binderDied() {
riljLog("Service " + serviceToString(mService) + " has died.");
- mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_AIDL_PROXY_DEAD, mService,
- 0 /* ignored arg2 */, mServiceCookies.get(mService).get()));
+ if (mFeatureFlags.combineRilDeathHandle()) {
+ mRilHandler.sendMessageAtFrontOfQueue(mRilHandler.obtainMessage(
+ EVENT_AIDL_PROXY_DEAD, mService, 0 /* ignored arg2 */,
+ mLinkedFlags));
+ } else {
+ mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_AIDL_PROXY_DEAD, mService,
+ 0 /* ignored arg2 */, mLinkedFlags));
+ }
unlinkToDeath();
}
}
- private synchronized void resetProxyAndRequestList(int service) {
+ /**
+ * Reset services. If one of the AIDL service is reset, all the other AIDL services will be
+ * reset as well.
+ * @param service The service to reset.
+ */
+ private synchronized void resetProxyAndRequestList(@HalService int service) {
if (service == HAL_SERVICE_RADIO) {
mRadioProxy = null;
+ // Increment the cookie so that death notification can be ignored
+ mServiceCookies.get(service).incrementAndGet();
} else {
- mServiceProxies.get(service).clear();
+ if (mFeatureFlags.combineRilDeathHandle()) {
+ // Reset all aidl services.
+ for (int i = MIN_SERVICE_IDX; i <= MAX_SERVICE_IDX; i++) {
+ if (i == HAL_SERVICE_RADIO) continue;
+ if (mServiceProxies.get(i) == null) {
+ // This should only happen in tests
+ riljLoge("Null service proxy for service " + serviceToString(i));
+ continue;
+ }
+ mServiceProxies.get(i).clear();
+ // Increment the cookie so that death notification can be ignored
+ mServiceCookies.get(i).incrementAndGet();
+ }
+ } else {
+ mServiceProxies.get(service).clear();
+ // Increment the cookie so that death notification can be ignored
+ mServiceCookies.get(service).incrementAndGet();
+ }
}
- // Increment the cookie so that death notification can be ignored
- mServiceCookies.get(service).incrementAndGet();
-
- // TODO: If a service doesn't exist or is unimplemented, it shouldn't cause the radio to
- // become unavailable for all other services
setRadioState(TelephonyManager.RADIO_POWER_UNAVAILABLE, true /* forceNotifyRegistrants */);
RILRequest.resetSerial();
@@ -483,7 +547,20 @@
if (service == HAL_SERVICE_RADIO) {
getRadioProxy();
} else {
- getRadioServiceProxy(service);
+ if (mFeatureFlags.combineRilDeathHandle()) {
+ // Reset all aidl services.
+ for (int i = MIN_SERVICE_IDX; i <= MAX_SERVICE_IDX; i++) {
+ if (i == HAL_SERVICE_RADIO) continue;
+ if (mServiceProxies.get(i) == null) {
+ // This should only happen in tests
+ riljLoge("Null service proxy for service " + serviceToString(i));
+ continue;
+ }
+ getRadioServiceProxy(i);
+ }
+ } else {
+ getRadioServiceProxy(service);
+ }
}
}
@@ -501,10 +578,6 @@
mMockModem = null;
mMockModem = new MockModem(mContext, serviceName, mPhoneId);
- if (mMockModem == null) {
- riljLoge("MockModem create fail.");
- return false;
- }
// Disable HIDL service
if (mRadioProxy != null) {
@@ -541,8 +614,14 @@
if (serviceBound) {
mIsRadioProxyInitialized = false;
- for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
- resetProxyAndRequestList(service);
+ if (mFeatureFlags.combineRilDeathHandle()) {
+ // Reset both hidl and aidl proxies.
+ resetProxyAndRequestList(HAL_SERVICE_RADIO);
+ resetProxyAndRequestList(HAL_SERVICE_DATA);
+ } else {
+ for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
+ resetProxyAndRequestList(service);
+ }
}
}
}
@@ -570,7 +649,15 @@
mHalVersion.put(service, RADIO_HAL_VERSION_UNSUPPORTED);
}
}
- resetProxyAndRequestList(service);
+ if (!mFeatureFlags.combineRilDeathHandle()) {
+ resetProxyAndRequestList(service);
+ }
+ }
+ if (mFeatureFlags.combineRilDeathHandle()) {
+ // Reset both hidl and aidl proxies. Must be after cleaning mocked halVersion,
+ // otherwise an aidl service will be incorrectly considered as disabled.
+ resetProxyAndRequestList(HAL_SERVICE_RADIO);
+ resetProxyAndRequestList(HAL_SERVICE_DATA);
}
}
}
@@ -728,9 +815,12 @@
public synchronized RadioServiceProxy getRadioServiceProxy(int service) {
if (!SubscriptionManager.isValidPhoneId(mPhoneId)) return mServiceProxies.get(service);
if ((service >= HAL_SERVICE_IMS) && !isRadioServiceSupported(service)) {
- riljLogw("getRadioServiceProxy: " + serviceToString(service) + " for "
- + HIDL_SERVICE_NAME[mPhoneId] + " is not supported\n"
- + android.util.Log.getStackTraceString(new RuntimeException()));
+ // Suppress the excessive logging for HAL_SERVICE_IMS when not supported.
+ if (service != HAL_SERVICE_IMS) {
+ riljLogw("getRadioServiceProxy: " + serviceToString(service) + " for "
+ + HIDL_SERVICE_NAME[mPhoneId] + " is not supported\n"
+ + android.util.Log.getStackTraceString(new RuntimeException()));
+ }
return mServiceProxies.get(service);
}
if (!mIsCellularSupported) {
@@ -979,16 +1069,33 @@
@Override
public synchronized void onSlotActiveStatusChange(boolean active) {
mIsRadioProxyInitialized = false;
- for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
+ if (mFeatureFlags.combineRilDeathHandle()) {
if (active) {
- // Try to connect to RIL services and set response functions.
- if (service == HAL_SERVICE_RADIO) {
- getRadioProxy();
- } else {
- getRadioServiceProxy(service);
+ for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
+ // Try to connect to RIL services and set response functions.
+ if (service == HAL_SERVICE_RADIO) {
+ getRadioProxy();
+ } else {
+ getRadioServiceProxy(service);
+ }
}
} else {
- resetProxyAndRequestList(service);
+ // Reset both hidl and aidl proxies
+ resetProxyAndRequestList(HAL_SERVICE_RADIO);
+ resetProxyAndRequestList(HAL_SERVICE_DATA);
+ }
+ } else {
+ for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
+ if (active) {
+ // Try to connect to RIL services and set response functions.
+ if (service == HAL_SERVICE_RADIO) {
+ getRadioProxy();
+ } else {
+ getRadioServiceProxy(service);
+ }
+ } else {
+ resetProxyAndRequestList(service);
+ }
}
}
}
@@ -996,19 +1103,16 @@
//***** Constructors
@UnsupportedAppUsage
- public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription) {
- this(context, allowedNetworkTypes, cdmaSubscription, null);
- }
-
- @UnsupportedAppUsage
- public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription, Integer instanceId) {
- this(context, allowedNetworkTypes, cdmaSubscription, instanceId, null);
+ public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription, Integer instanceId,
+ @NonNull FeatureFlags flags) {
+ this(context, allowedNetworkTypes, cdmaSubscription, instanceId, null, flags);
}
@VisibleForTesting
public RIL(Context context, int allowedNetworkTypes, int cdmaSubscription, Integer instanceId,
- SparseArray<RadioServiceProxy> proxies) {
+ SparseArray<RadioServiceProxy> proxies, @NonNull FeatureFlags flags) {
super(context);
+ mFeatureFlags = flags;
if (RILJ_LOGD) {
riljLog("RIL: init allowedNetworkTypes=" + allowedNetworkTypes
+ " cdmaSubscription=" + cdmaSubscription + ")");
@@ -1115,7 +1219,7 @@
// Set radio callback; needed to set RadioIndication callback (should be done after
// wakelock stuff is initialized above as callbacks are received on separate binder threads)
for (int service = MIN_SERVICE_IDX; service <= MAX_SERVICE_IDX; service++) {
- if (!isRadioServiceSupported(service)) {
+ if (isRadioVersion2_0() && !isRadioServiceSupported(service)) {
riljLog("Not initializing " + serviceToString(service) + " (not supported)");
continue;
}
@@ -1137,12 +1241,13 @@
}
private boolean isRadioVersion2_0() {
+ if (mIsRadioVersion20Cached != null) return mIsRadioVersion20Cached;
for (int service = HAL_SERVICE_DATA; service <= MAX_SERVICE_IDX; service++) {
if (isRadioServiceSupported(service)) {
- return true;
+ return mIsRadioVersion20Cached = true;
}
}
- return false;
+ return mIsRadioVersion20Cached = false;
}
private boolean isRadioServiceSupported(int service) {
@@ -1283,17 +1388,6 @@
} else if (proxy instanceof RadioImsProxy) {
service = HAL_SERVICE_IMS;
}
-
- if (mHalVersion.get(service).less(version)) {
- riljLoge(String.format("%s not supported on service %s < %s.",
- request, serviceToString(service), version));
- if (result != null) {
- AsyncResult.forMessage(result, null,
- CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
- result.sendToTarget();
- }
- return false;
- }
if (proxy == null || proxy.isEmpty()) {
riljLoge(String.format("Unable to complete %s because service %s is not available.",
request, serviceToString(service)));
@@ -1304,6 +1398,16 @@
}
return false;
}
+ if (mHalVersion.get(service).less(version)) {
+ riljLoge(String.format("%s not supported on service %s < %s.",
+ request, serviceToString(service), version));
+ if (result != null) {
+ AsyncResult.forMessage(result, null,
+ CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+ result.sendToTarget();
+ }
+ return false;
+ }
return true;
}
diff --git a/src/java/com/android/internal/telephony/RadioConfig.java b/src/java/com/android/internal/telephony/RadioConfig.java
index 13f6502..da20639 100644
--- a/src/java/com/android/internal/telephony/RadioConfig.java
+++ b/src/java/com/android/internal/telephony/RadioConfig.java
@@ -61,10 +61,6 @@
static final int EVENT_HIDL_SERVICE_DEAD = 1;
static final int EVENT_AIDL_SERVICE_DEAD = 2;
- static final HalVersion RADIO_CONFIG_HAL_VERSION_UNKNOWN = new HalVersion(-1, -1);
- static final HalVersion RADIO_CONFIG_HAL_VERSION_1_1 = new HalVersion(1, 1);
- static final HalVersion RADIO_CONFIG_HAL_VERSION_1_3 = new HalVersion(1, 3);
- static final HalVersion RADIO_CONFIG_HAL_VERSION_2_0 = new HalVersion(2, 0);
private final boolean mIsMobileNetworkSupported;
private final SparseArray<RILRequest> mRequestList = new SparseArray<>();
@@ -294,13 +290,12 @@
if (service != null) {
mRadioConfigProxy.setAidl(
- RADIO_CONFIG_HAL_VERSION_2_0,
android.hardware.radio.config.IRadioConfig.Stub.asInterface(service));
}
if (mRadioConfigProxy.isEmpty()) {
try {
- mRadioConfigProxy.setHidl(RADIO_CONFIG_HAL_VERSION_1_3,
+ mRadioConfigProxy.setHidl(RIL.RADIO_HAL_VERSION_1_3,
android.hardware.radio.config.V1_3.IRadioConfig.getService(true));
} catch (RemoteException | NoSuchElementException e) {
mRadioConfigProxy.clear();
@@ -310,7 +305,7 @@
if (mRadioConfigProxy.isEmpty()) {
try {
- mRadioConfigProxy.setHidl(RADIO_CONFIG_HAL_VERSION_1_1,
+ mRadioConfigProxy.setHidl(RIL.RADIO_HAL_VERSION_1_1,
android.hardware.radio.config.V1_1.IRadioConfig.getService(true));
} catch (RemoteException | NoSuchElementException e) {
mRadioConfigProxy.clear();
@@ -515,7 +510,7 @@
RadioConfigProxy proxy = getRadioConfigProxy(null);
if (proxy.isEmpty()) return;
- if (proxy.getVersion().less(RADIO_CONFIG_HAL_VERSION_1_1)) {
+ if (proxy.getVersion().less(RIL.RADIO_HAL_VERSION_1_1)) {
if (result != null) {
AsyncResult.forMessage(result, null,
CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
@@ -543,7 +538,7 @@
*/
public boolean isSetPreferredDataCommandSupported() {
RadioConfigProxy proxy = getRadioConfigProxy(null);
- return !proxy.isEmpty() && proxy.getVersion().greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_1);
+ return !proxy.isEmpty() && proxy.getVersion().greaterOrEqual(RIL.RADIO_HAL_VERSION_1_1);
}
/**
@@ -574,7 +569,7 @@
RadioConfigProxy proxy = getRadioConfigProxy(result);
if (proxy.isEmpty()) return;
- if (proxy.getVersion().less(RADIO_CONFIG_HAL_VERSION_1_1)) {
+ if (proxy.getVersion().less(RIL.RADIO_HAL_VERSION_1_1)) {
if (result != null) {
AsyncResult.forMessage(
result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
@@ -628,7 +623,7 @@
RadioConfigProxy proxy = getRadioConfigProxy(Message.obtain(result));
if (proxy.isEmpty()) return;
- if (proxy.getVersion().less(RADIO_CONFIG_HAL_VERSION_1_3)) {
+ if (proxy.getVersion().less(RIL.RADIO_HAL_VERSION_1_3)) {
if (result != null) {
if (DBG) {
logd("RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES > REQUEST_NOT_SUPPORTED");
diff --git a/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java b/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java
index 9aa1aaa..127631d 100644
--- a/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java
+++ b/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java
@@ -17,14 +17,14 @@
package com.android.internal.telephony;
import android.os.AsyncResult;
-import android.os.RemoteException;
import android.os.Trace;
import com.android.internal.telephony.uicc.IccSlotStatus;
import com.android.telephony.Rlog;
import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
/**
* This class is the AIDL implementation of IRadioConfigIndication interface.
@@ -58,9 +58,11 @@
*/
@Override
public void onSimultaneousCallingSupportChanged(int[] enabledLogicalSlots) {
- ArrayList<Integer> ret = RILUtils.primitiveArrayToArrayList(enabledLogicalSlots);
+ List<Integer> ret = (enabledLogicalSlots == null) ? Collections.emptyList() :
+ RILUtils.primitiveArrayToArrayList(enabledLogicalSlots);
logd("onSimultaneousCallingSupportChanged: enabledLogicalSlots = " + ret);
if (mRadioConfig.mSimultaneousCallingSupportStatusRegistrant != null) {
+ logd("onSimultaneousCallingSupportChanged: notifying registrant");
mRadioConfig.mSimultaneousCallingSupportStatusRegistrant.notifyRegistrant(
new AsyncResult(null, ret, null));
}
diff --git a/src/java/com/android/internal/telephony/RadioConfigProxy.java b/src/java/com/android/internal/telephony/RadioConfigProxy.java
index b6c6d68..9f34e29 100644
--- a/src/java/com/android/internal/telephony/RadioConfigProxy.java
+++ b/src/java/com/android/internal/telephony/RadioConfigProxy.java
@@ -31,14 +31,15 @@
* downstream users.
*/
public class RadioConfigProxy {
- private final HalVersion mRadioHalVersion;
+ private static final String TAG = "RadioConfigProxy";
+ private HalVersion mRadioHalVersion;
private final RadioConfigHidlServiceDeathRecipient mRadioConfigHidlServiceDeathRecipient;
private final RadioConfigAidlServiceDeathRecipient mRadioConfigAidlServiceDeathRecipient;
private volatile android.hardware.radio.config.V1_1.IRadioConfig mHidlRadioConfigProxy = null;
private volatile android.hardware.radio.config.IRadioConfig mAidlRadioConfigProxy = null;
- private HalVersion mRadioConfigHalVersion = RadioConfig.RADIO_CONFIG_HAL_VERSION_UNKNOWN;
+ private HalVersion mRadioConfigHalVersion = RIL.RADIO_HAL_VERSION_UNKNOWN;
private boolean mIsAidl;
public RadioConfigProxy(RadioConfig radioConfig, HalVersion radioHalVersion) {
@@ -83,13 +84,15 @@
/**
* Set IRadioConfig as the AIDL implementation for RadioConfigProxy
*
- * @param radioConfigHalVersion RadioConfig HAL version
* @param radioConfig IRadioConfig implementation
*/
- public void setAidl(
- HalVersion radioConfigHalVersion,
- android.hardware.radio.config.IRadioConfig radioConfig) {
- mRadioConfigHalVersion = radioConfigHalVersion;
+ public void setAidl(android.hardware.radio.config.IRadioConfig radioConfig) {
+ try {
+ mRadioConfigHalVersion = RIL.getServiceHalVersion(radioConfig.getInterfaceVersion());
+ Rlog.d(TAG, "setAidl: setting HAL version to version = " + mRadioConfigHalVersion);
+ } catch (RemoteException e) {
+ Rlog.e(TAG, "setAidl: " + e);
+ }
mAidlRadioConfigProxy = radioConfig;
mIsAidl = true;
mRadioConfigAidlServiceDeathRecipient.setService(radioConfig.asBinder());
@@ -106,7 +109,7 @@
/** Reset RadioConfigProxy */
public void clear() {
- mRadioConfigHalVersion = RadioConfig.RADIO_CONFIG_HAL_VERSION_UNKNOWN;
+ mRadioConfigHalVersion = RIL.RADIO_HAL_VERSION_UNKNOWN;
mHidlRadioConfigProxy = null;
mAidlRadioConfigProxy = null;
mRadioConfigHidlServiceDeathRecipient.clear();
diff --git a/src/java/com/android/internal/telephony/SMSDispatcher.java b/src/java/com/android/internal/telephony/SMSDispatcher.java
index 498535b..8764e02 100644
--- a/src/java/com/android/internal/telephony/SMSDispatcher.java
+++ b/src/java/com/android/internal/telephony/SMSDispatcher.java
@@ -1054,7 +1054,8 @@
tracker.onSent(mContext);
mPhone.notifySmsSent(tracker.mDestAddress);
mSmsDispatchersController.notifySmsSentToEmergencyStateTracker(
- tracker.mDestAddress, tracker.mMessageId, false);
+ tracker.mDestAddress, tracker.mMessageId, false,
+ tracker.isSinglePartOrLastPart());
mPhone.getSmsStats().onOutgoingSms(
tracker.mImsRetry > 0 /* isOverIms */,
@@ -1063,7 +1064,8 @@
SmsManager.RESULT_ERROR_NONE,
tracker.mMessageId,
tracker.isFromDefaultSmsApplication(mContext),
- tracker.getInterval());
+ tracker.getInterval(),
+ mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1113,7 +1115,8 @@
getNotInServiceError(ss),
tracker.mMessageId,
tracker.isFromDefaultSmsApplication(mContext),
- tracker.getInterval());
+ tracker.getInterval(),
+ mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1149,7 +1152,8 @@
errorCode,
tracker.mMessageId,
tracker.isFromDefaultSmsApplication(mContext),
- tracker.getInterval());
+ tracker.getInterval(),
+ mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -1175,7 +1179,8 @@
errorCode,
tracker.mMessageId,
tracker.isFromDefaultSmsApplication(mContext),
- tracker.getInterval());
+ tracker.getInterval(),
+ mTelephonyManager.isEmergencyNumber(tracker.mDestAddress));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -2403,7 +2408,8 @@
error,
trackers[0].mMessageId,
trackers[0].isFromDefaultSmsApplication(mContext),
- trackers[0].getInterval());
+ trackers[0].getInterval(),
+ mTelephonyManager.isEmergencyNumber(trackers[0].mDestAddress));
if (mPhone != null) {
TelephonyAnalytics telephonyAnalytics = mPhone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
@@ -2608,6 +2614,14 @@
}
/**
+ * Returns the flag specifying whether this {@link SmsTracker} is a single part or
+ * the last part of multipart message.
+ */
+ protected boolean isSinglePartOrLastPart() {
+ return mUnsentPartCount != null ? (mUnsentPartCount.get() == 0) : true;
+ }
+
+ /**
* Persist a sent SMS if required:
* 1. It is a text message
* 2. SmsApplication tells us to persist: sent from apps that are not default-SMS app or
diff --git a/src/java/com/android/internal/telephony/ServiceStateTracker.java b/src/java/com/android/internal/telephony/ServiceStateTracker.java
index ba6479e..2a9bf7f 100644
--- a/src/java/com/android/internal/telephony/ServiceStateTracker.java
+++ b/src/java/com/android/internal/telephony/ServiceStateTracker.java
@@ -227,7 +227,6 @@
private final RegistrantList mAreaCodeChangedRegistrants = new RegistrantList();
/* Radio power off pending flag */
- // @GuardedBy("this")
private volatile boolean mPendingRadioPowerOffAfterDataOff = false;
/** Waiting period before recheck gprs and voice registration. */
@@ -3728,10 +3727,18 @@
// because operatorNumeric would be SIM's mcc/mnc when device is on IWLAN), but if the
// device has camped on a cell either to attempt registration or for emergency services,
// then for purposes of setting the locale, we don't care if registration fails or is
- // incomplete.
+ // incomplete. Additionally, if there is no cellular service and ims is registered over
+ // the IWLAN, the locale will not be updated.
// CellIdentity can return a null MCC and MNC in CDMA
String localeOperator = operatorNumeric;
- if (mSS.getDataNetworkType() == TelephonyManager.NETWORK_TYPE_IWLAN) {
+ int dataNetworkType = mSS.getDataNetworkType();
+ if (dataNetworkType == TelephonyManager.NETWORK_TYPE_IWLAN
+ || (dataNetworkType == TelephonyManager.NETWORK_TYPE_UNKNOWN
+ && getImsRegistrationTech()
+ == ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)) {
+ // TODO(b/333346537#comment10): Complete solution would be ignore mcc/mnc reported
+ // by the unsolicited indication OPERATOR from RIL, but only relies on MCC/MNC from
+ // data registration or voice registration.
localeOperator = null;
}
if (isInvalidOperatorNumeric(localeOperator)) {
@@ -5008,20 +5015,10 @@
}
/**
- * process the pending request to turn radio off after data is disconnected
- *
- * return true if there is pending request to process; false otherwise.
+ * return true if there is pending disconnect data request to process; false otherwise.
*/
- public boolean processPendingRadioPowerOffAfterDataOff() {
- synchronized(this) {
- if (mPendingRadioPowerOffAfterDataOff) {
- if (DBG) log("Process pending request to turn radio off.");
- hangupAndPowerOff();
- mPendingRadioPowerOffAfterDataOff = false;
- return true;
- }
- return false;
- }
+ public boolean isPendingRadioPowerOffAfterDataOff() {
+ return mPendingRadioPowerOffAfterDataOff;
}
private void onCarrierConfigurationChanged(int slotIndex) {
@@ -5911,4 +5908,17 @@
public @Nullable CellIdentity getLastKnownCellIdentity() {
return mLastKnownCellIdentity;
}
+
+ /**
+ * Get the tech where ims is currently registered.
+ * @return Returns the tech of ims registered. if not registered or no phome for ims, returns
+ * {@link ImsRegistrationImplBase#REGISTRATION_TECH_NONE}.
+ */
+ private @ImsRegistrationImplBase.ImsRegistrationTech int getImsRegistrationTech() {
+ ImsPhone imsPhone = (ImsPhone) mPhone.getImsPhone();
+ if (imsPhone != null) {
+ return imsPhone.getImsRegistrationTech();
+ }
+ return ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
+ }
}
diff --git a/src/java/com/android/internal/telephony/SignalStrengthController.java b/src/java/com/android/internal/telephony/SignalStrengthController.java
index b11d7e5..98f84b2 100644
--- a/src/java/com/android/internal/telephony/SignalStrengthController.java
+++ b/src/java/com/android/internal/telephony/SignalStrengthController.java
@@ -50,6 +50,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.ArrayUtils;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.telephony.Rlog;
@@ -60,6 +61,7 @@
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
@@ -101,7 +103,7 @@
private static final int EVENT_GET_SIGNAL_STRENGTH = 6;
private static final int EVENT_POLL_SIGNAL_STRENGTH = 7;
private static final int EVENT_SIGNAL_STRENGTH_UPDATE = 8;
- private static final int EVENT_POLL_SIGNAL_STRENGTH_DONE = 9;
+ public static final int EVENT_POLL_SIGNAL_STRENGTH_DONE = 9;
private static final int EVENT_SERVICE_STATE_CHANGED = 10;
@NonNull
@@ -330,7 +332,7 @@
* @param signalStrength The new SignalStrength used for updating {@code mSignalStrength}.
*/
private void updateSignalStrength(@NonNull SignalStrength signalStrength) {
- mSignalStrength = signalStrength;
+ mSignalStrength = maybeOverrideSignalStrengthForTest(signalStrength);
ServiceStateTracker serviceStateTracker = mPhone.getServiceStateTracker();
if (serviceStateTracker != null) {
mSignalStrength.updateLevel(mCarrierConfig, serviceStateTracker.mSS);
@@ -342,6 +344,18 @@
}
/**
+ * For debug test build, override signal strength for testing.
+ * @param original The real signal strength to use if not in testing mode.
+ * @return The signal strength to broadcast to the external.
+ */
+ @NonNull private SignalStrength maybeOverrideSignalStrengthForTest(
+ @NonNull SignalStrength original) {
+ return TelephonyUtils.IS_DEBUGGABLE && mPhone.getTelephonyTester() != null
+ ? Objects.requireNonNullElse(mPhone.getTelephonyTester()
+ .getOverriddenSignalStrength(), original) : original;
+ }
+
+ /**
* @return signal strength
*/
@NonNull
@@ -750,7 +764,7 @@
}
void setSignalStrengthDefaultValues() {
- mSignalStrength = new SignalStrength();
+ mSignalStrength = maybeOverrideSignalStrengthForTest(new SignalStrength());
mSignalStrengthUpdatedTime = System.currentTimeMillis();
}
diff --git a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
index 0a14ccd..0b427f8 100644
--- a/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
+++ b/src/java/com/android/internal/telephony/SimultaneousCallingTracker.java
@@ -494,7 +494,7 @@
l.onSimultaneousCallingSupportChanged(simultaneousCallSubscriptionIdMap);
}
} catch (Exception e) {
- Log.w(LOG_TAG, "handleVideoCapabilitiesChanged: Exception = " + e);
+ Log.w(LOG_TAG, "handleSimultaneousCallingSupportChanged: Exception = " + e);
}
}
diff --git a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
index 7fc499e..077ee0b 100644
--- a/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
+++ b/src/java/com/android/internal/telephony/SmsBroadcastUndelivered.java
@@ -30,6 +30,7 @@
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import com.android.internal.telephony.analytics.TelephonyAnalytics;
import com.android.internal.telephony.analytics.TelephonyAnalytics.SmsMmsAnalytics;
@@ -243,7 +244,8 @@
message.mMessageCount);
if (phone != null) {
phone.getSmsStats().onDroppedIncomingMultipartSms(message.mIs3gpp2, rows,
- message.mMessageCount);
+ message.mMessageCount, TelephonyManager.from(context)
+ .isEmergencyNumber(message.mAddress));
TelephonyAnalytics telephonyAnalytics = phone.getTelephonyAnalytics();
if (telephonyAnalytics != null) {
SmsMmsAnalytics smsMmsAnalytics =
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 32c7429..59184d8 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -302,16 +302,17 @@
SubscriptionInfo info;
try {
info = getSubscriptionInfo(subId);
+
+ if (isBluetoothSubscription(info)) {
+ sendBluetoothText(info, destAddr, text, sentIntent, deliveryIntent);
+ } else {
+ sendIccText(subId, callingPackage, destAddr, scAddr, text, sentIntent,
+ deliveryIntent, persistMessageForNonDefaultSmsApp, messageId,
+ skipShortCodeCheck);
+ }
} finally {
Binder.restoreCallingIdentity(token);
}
-
- if (isBluetoothSubscription(info)) {
- sendBluetoothText(info, destAddr, text, sentIntent, deliveryIntent);
- } else {
- sendIccText(subId, callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent,
- persistMessageForNonDefaultSmsApp, messageId, skipShortCodeCheck);
- }
}
private boolean isBluetoothSubscription(SubscriptionInfo info) {
diff --git a/src/java/com/android/internal/telephony/SmsDispatchersController.java b/src/java/com/android/internal/telephony/SmsDispatchersController.java
index cc287f8..bc1e1a8 100644
--- a/src/java/com/android/internal/telephony/SmsDispatchersController.java
+++ b/src/java/com/android/internal/telephony/SmsDispatchersController.java
@@ -112,6 +112,9 @@
/** Called when MT SMS is received via IMS. */
private static final int EVENT_SMS_RECEIVED_VIA_IMS = 21;
+ /** Called when the domain selection should be performed. */
+ private static final int EVENT_REQUEST_DOMAIN_SELECTION = 22;
+
/** Delete any partial message segments after being IN_SERVICE for 1 day. */
private static final long PARTIAL_SEGMENT_WAIT_DURATION = (long) (60 * 60 * 1000) * 24;
/** Constant for invalid time */
@@ -491,9 +494,10 @@
Long messageId = (Long) args.arg2;
Boolean success = (Boolean) args.arg3;
Boolean isOverIms = (Boolean) args.arg4;
+ Boolean isLastSmsPart = (Boolean) args.arg5;
try {
handleSmsSentCompletedUsingDomainSelection(
- destAddr, messageId, success, isOverIms);
+ destAddr, messageId, success, isOverIms, isLastSmsPart);
} finally {
args.recycle();
}
@@ -508,6 +512,19 @@
handleSmsReceivedViaIms((String) msg.obj);
break;
}
+ case EVENT_REQUEST_DOMAIN_SELECTION: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ DomainSelectionConnectionHolder holder =
+ (DomainSelectionConnectionHolder) args.arg1;
+ PendingRequest request = (PendingRequest) args.arg2;
+ String logTag = (String) args.arg3;
+ try {
+ requestDomainSelection(holder, request, logTag);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
default:
if (isCdmaMo()) {
mCdmaDispatcher.handleMessage(msg);
@@ -762,18 +779,18 @@
if (!tracker.mUsesImsServiceForIms) {
if (isSmsDomainSelectionEnabled()) {
- DomainSelectionConnectionHolder holder = getDomainSelectionConnection(false);
-
- // If the DomainSelectionConnection is not available,
- // fallback to the legacy implementation.
- if (holder != null && holder.getConnection() != null) {
- sendSmsUsingDomainSelection(holder,
- new PendingRequest(PendingRequest.TYPE_RETRY_SMS, tracker,
- null, null, null, null, null, false, null, 0, null, null, false,
- 0, false, 0, 0L, false),
- "sendRetrySms");
- return;
- }
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ boolean isEmergency = tm.isEmergencyNumber(tracker.mDestAddress);
+ // This may be invoked by another thread, so this operation is posted and
+ // handled through the execution flow of SmsDispatchersController.
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = getDomainSelectionConnectionHolder(isEmergency);
+ args.arg2 = new PendingRequest(PendingRequest.TYPE_RETRY_SMS, tracker,
+ null, null, null, null, null, false, null, 0, null, null, false,
+ 0, false, 0, 0L, false);
+ args.arg3 = "sendRetrySms";
+ sendMessage(obtainMessage(EVENT_REQUEST_DOMAIN_SELECTION, args));
+ return;
}
if (mImsSmsDispatcher.isAvailable()) {
@@ -984,52 +1001,23 @@
* Returns a {@link DomainSelectionConnectionHolder} according to the flag specified.
*
* @param emergency The flag to indicate that the domain selection is for an emergency SMS.
- * @return A {@link DomainSelectionConnectionHolder} instance or null.
+ * @return A {@link DomainSelectionConnectionHolder} instance.
*/
@VisibleForTesting
@Nullable
protected DomainSelectionConnectionHolder getDomainSelectionConnectionHolder(
boolean emergency) {
- return emergency ? mEmergencyDscHolder : mDscHolder;
- }
-
- /**
- * Returns a {@link DomainSelectionConnectionHolder} if the domain selection supports,
- * return null otherwise.
- *
- * @param emergency The flag to indicate that the domain selection is for an emergency SMS.
- * @return A {@link DomainSelectionConnectionHolder} that grabs the
- * {@link DomainSelectionConnection} and its related information to use the domain
- * selection architecture.
- */
- private DomainSelectionConnectionHolder getDomainSelectionConnection(boolean emergency) {
- DomainSelectionConnectionHolder holder = getDomainSelectionConnectionHolder(emergency);
- DomainSelectionConnection connection = (holder != null) ? holder.getConnection() : null;
-
- if (connection == null) {
- connection = mDomainSelectionResolverProxy.getDomainSelectionConnection(
- mPhone, DomainSelectionService.SELECTOR_TYPE_SMS, emergency);
-
- if (connection == null) {
- // Domain selection architecture is not supported.
- // Use the legacy architecture.
- return null;
+ if (emergency) {
+ if (mEmergencyDscHolder == null) {
+ mEmergencyDscHolder = new DomainSelectionConnectionHolder(emergency);
}
- }
-
- if (holder == null) {
- holder = new DomainSelectionConnectionHolder(emergency);
-
- if (emergency) {
- mEmergencyDscHolder = holder;
- } else {
- mDscHolder = holder;
+ return mEmergencyDscHolder;
+ } else {
+ if (mDscHolder == null) {
+ mDscHolder = new DomainSelectionConnectionHolder(emergency);
}
+ return mDscHolder;
}
-
- holder.setConnection(connection);
-
- return holder;
}
/**
@@ -1079,6 +1067,8 @@
*
* @param holder The {@link DomainSelectionConnectionHolder} that contains the
* {@link DomainSelectionConnection} and its related information.
+ * @param request The {@link PendingRequest} that stores the SMS request
+ * (data, text, multipart text) to be sent.
* @param logTag The log string.
*/
private void requestDomainSelection(@NonNull DomainSelectionConnectionHolder holder,
@@ -1088,6 +1078,21 @@
// the domain selection by adding this request to the pending list.
holder.addRequest(request);
+ if (holder.getConnection() == null) {
+ DomainSelectionConnection connection =
+ mDomainSelectionResolverProxy.getDomainSelectionConnection(
+ mPhone, DomainSelectionService.SELECTOR_TYPE_SMS, holder.isEmergency());
+ if (connection == null) {
+ logd("requestDomainSelection: fallback for " + logTag);
+ // If the domain selection connection is not available,
+ // fallback to the legacy implementation.
+ sendAllPendingRequests(holder, NetworkRegistrationInfo.DOMAIN_UNKNOWN);
+ return;
+ } else {
+ holder.setConnection(connection);
+ }
+ }
+
if (!isDomainSelectionRequested) {
if (VDBG) {
logd("requestDomainSelection: " + logTag);
@@ -1157,15 +1162,17 @@
* @param messageId The message id for SMS.
* @param success A flag specifying whether MO SMS is successfully sent or not.
* @param isOverIms A flag specifying whether MO SMS is sent over IMS or not.
+ * @param isLastSmsPart A flag specifying whether this result is for the last SMS part or not.
*/
private void handleSmsSentCompletedUsingDomainSelection(@NonNull String destAddr,
- long messageId, boolean success, boolean isOverIms) {
+ long messageId, boolean success, boolean isOverIms, boolean isLastSmsPart) {
if (mEmergencyStateTracker != null) {
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
if (tm.isEmergencyNumber(destAddr)) {
mEmergencyStateTracker.endSms(String.valueOf(messageId), success,
isOverIms ? NetworkRegistrationInfo.DOMAIN_PS
- : NetworkRegistrationInfo.DOMAIN_CS);
+ : NetworkRegistrationInfo.DOMAIN_CS,
+ isLastSmsPart);
}
}
}
@@ -1174,7 +1181,7 @@
* Called when MO SMS is successfully sent.
*/
protected void notifySmsSentToEmergencyStateTracker(@NonNull String destAddr, long messageId,
- boolean isOverIms) {
+ boolean isOverIms, boolean isLastSmsPart) {
if (isSmsDomainSelectionEnabled()) {
// Run on main thread for interworking with EmergencyStateTracker.
SomeArgs args = SomeArgs.obtain();
@@ -1182,6 +1189,7 @@
args.arg2 = Long.valueOf(messageId);
args.arg3 = Boolean.TRUE;
args.arg4 = Boolean.valueOf(isOverIms);
+ args.arg5 = Boolean.valueOf(isLastSmsPart);
sendMessage(obtainMessage(EVENT_SMS_SENT_COMPLETED_USING_DOMAIN_SELECTION, args));
}
}
@@ -1198,6 +1206,7 @@
args.arg2 = Long.valueOf(messageId);
args.arg3 = Boolean.FALSE;
args.arg4 = Boolean.valueOf(isOverIms);
+ args.arg5 = Boolean.TRUE; // Ignored when sending SMS is failed.
sendMessage(obtainMessage(EVENT_SMS_SENT_COMPLETED_USING_DOMAIN_SELECTION, args));
}
}
@@ -1544,19 +1553,13 @@
}
if (isSmsDomainSelectionEnabled()) {
- DomainSelectionConnectionHolder holder = getDomainSelectionConnection(false);
-
- // If the DomainSelectionConnection is not available,
- // fallback to the legacy implementation.
- if (holder != null && holder.getConnection() != null) {
- sendSmsUsingDomainSelection(holder,
- new PendingRequest(PendingRequest.TYPE_DATA, null, callingPackage,
- destAddr, scAddr, asArrayList(sentIntent),
- asArrayList(deliveryIntent), isForVvm, data, destPort, null, null,
- false, 0, false, 0, 0L, false),
- "sendData");
- return;
- }
+ sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(false),
+ new PendingRequest(PendingRequest.TYPE_DATA, null, callingPackage,
+ destAddr, scAddr, asArrayList(sentIntent),
+ asArrayList(deliveryIntent), isForVvm, data, destPort, null, null,
+ false, 0, false, 0, 0L, false),
+ "sendData");
+ return;
}
if (mImsSmsDispatcher.isAvailable()) {
@@ -1785,20 +1788,14 @@
if (isSmsDomainSelectionEnabled()) {
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
boolean isEmergency = tm.isEmergencyNumber(destAddr);
- DomainSelectionConnectionHolder holder = getDomainSelectionConnection(isEmergency);
-
- // If the DomainSelectionConnection is not available,
- // fallback to the legacy implementation.
- if (holder != null && holder.getConnection() != null) {
- sendSmsUsingDomainSelection(holder,
- new PendingRequest(PendingRequest.TYPE_TEXT, null, callingPkg,
- destAddr, scAddr, asArrayList(sentIntent),
- asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
- messageUri, persistMessage, priority, expectMore, validityPeriod,
- messageId, skipShortCodeCheck),
- "sendText");
- return;
- }
+ sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
+ new PendingRequest(PendingRequest.TYPE_TEXT, null, callingPkg,
+ destAddr, scAddr, asArrayList(sentIntent),
+ asArrayList(deliveryIntent), isForVvm, null, 0, asArrayList(text),
+ messageUri, persistMessage, priority, expectMore, validityPeriod,
+ messageId, skipShortCodeCheck),
+ "sendText");
+ return;
}
if (mImsSmsDispatcher.isAvailable() || mImsSmsDispatcher.isEmergencySmsSupport(destAddr)) {
@@ -1932,19 +1929,15 @@
}
if (isSmsDomainSelectionEnabled()) {
- DomainSelectionConnectionHolder holder = getDomainSelectionConnection(false);
-
- // If the DomainSelectionConnection is not available,
- // fallback to the legacy implementation.
- if (holder != null && holder.getConnection() != null) {
- sendSmsUsingDomainSelection(holder,
- new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
- callingPkg, destAddr, scAddr, sentIntents, deliveryIntents, false,
- null, 0, parts, messageUri, persistMessage, priority, expectMore,
- validityPeriod, messageId, false),
- "sendMultipartText");
- return;
- }
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ boolean isEmergency = tm.isEmergencyNumber(destAddr);
+ sendSmsUsingDomainSelection(getDomainSelectionConnectionHolder(isEmergency),
+ new PendingRequest(PendingRequest.TYPE_MULTIPART_TEXT, null,
+ callingPkg, destAddr, scAddr, sentIntents, deliveryIntents, false,
+ null, 0, parts, messageUri, persistMessage, priority, expectMore,
+ validityPeriod, messageId, false),
+ "sendMultipartText");
+ return;
}
if (mImsSmsDispatcher.isAvailable()) {
diff --git a/src/java/com/android/internal/telephony/TelephonyCapabilities.java b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
index 1b4a3a9..71d3b14 100644
--- a/src/java/com/android/internal/telephony/TelephonyCapabilities.java
+++ b/src/java/com/android/internal/telephony/TelephonyCapabilities.java
@@ -16,9 +16,12 @@
package com.android.internal.telephony;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.os.Build;
+import android.os.SystemProperties;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.telephony.Rlog;
/**
@@ -194,4 +197,16 @@
public static boolean canDistinguishDialingAndConnected(int phoneType) {
return phoneType == PhoneConstants.PHONE_TYPE_GSM;
}
+
+ /**
+ * Returns true if Calling/Data/Messaging features should be checked on this device.
+ */
+ public static boolean minimalTelephonyCdmCheck(@NonNull FeatureFlags featureFlags) {
+ // Check SDK version of the vendor partition.
+ final int vendorApiLevel = SystemProperties.getInt(
+ "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
+ if (vendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) return false;
+
+ return featureFlags.minimalTelephonyCdmCheck();
+ }
}
diff --git a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
index 5da4b12..0b0f9d3 100644
--- a/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
+++ b/src/java/com/android/internal/telephony/TelephonyComponentFactory.java
@@ -523,8 +523,8 @@
/**
* Create a new LinkBandwidthEstimator.
*/
- public LinkBandwidthEstimator makeLinkBandwidthEstimator(Phone phone) {
- return new LinkBandwidthEstimator(phone, mTelephonyFacade);
+ public LinkBandwidthEstimator makeLinkBandwidthEstimator(Phone phone, Looper looper) {
+ return new LinkBandwidthEstimator(phone, looper, mTelephonyFacade);
}
/**
diff --git a/src/java/com/android/internal/telephony/TelephonyTester.java b/src/java/com/android/internal/telephony/TelephonyTester.java
index b9e04c8..7d3d75d 100644
--- a/src/java/com/android/internal/telephony/TelephonyTester.java
+++ b/src/java/com/android/internal/telephony/TelephonyTester.java
@@ -17,16 +17,21 @@
package com.android.internal.telephony;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
+import android.os.AsyncResult;
import android.os.BadParcelableException;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.telephony.AccessNetworkConstants;
+import android.telephony.CellSignalStrengthLte;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsConferenceState;
@@ -46,6 +51,7 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -163,6 +169,7 @@
private static List<ImsExternalCallState> mImsExternalCallStates = null;
private Intent mServiceStateTestIntent;
+ private SignalStrengthTestable mSignalStrengthTest;
private Phone mPhone;
@@ -386,11 +393,68 @@
}
/**
+ * Testable signal strength that mocks its fields.
+ */
+ private class SignalStrengthTestable extends SignalStrength {
+ private SignalStrengthTestable() {
+ super();
+ }
+
+ public void mockLevel(int level) {
+ try {
+ Field lteField = SignalStrength.class.getDeclaredField("mLte");
+ lteField.setAccessible(true);
+ CellSignalStrengthLte lte = (CellSignalStrengthLte) lteField.get(this);
+
+ Field lvlField = CellSignalStrengthLte.class.getDeclaredField("mLevel");
+ lvlField.setAccessible(true);
+ lvlField.set(lte, level);
+ } catch (Exception e) {
+ log("SignalStrengthTestable: mockLevel " + e);
+ }
+ }
+
+ @Override
+ public void updateLevel(PersistableBundle cc, ServiceState ss) {
+ log("SignalStrengthTestable: updateLevel: do nothing ");
+ }
+
+ @Override
+ public String toString() {
+ return "SignalStrengthTestable-" + getLevel();
+ }
+ }
+
+ /** {@link android.telephony.SignalStrength} */
+ public void setSignalStrength(int level) {
+ if (level > -1) {
+ log("setSignalStrength: level " + level);
+ mSignalStrengthTest = new SignalStrengthTestable();
+ mSignalStrengthTest.mockLevel(level);
+ AsyncResult ar = new AsyncResult(null, mSignalStrengthTest, null);
+ mPhone.getSignalStrengthController().sendMessage(mPhone.getSignalStrengthController()
+ .obtainMessage(SignalStrengthController.EVENT_POLL_SIGNAL_STRENGTH_DONE, ar));
+ } else {
+ log("setSignalStrength: clear mock");
+ mSignalStrengthTest = null;
+ mPhone.getSignalStrengthController().getSignalStrengthFromCi();
+ }
+ }
+
+ /** {@link android.telephony.SignalStrength} */
+ @Nullable
+ public SignalStrength getOverriddenSignalStrength() {
+ return mSignalStrengthTest;
+ }
+
+ /**
* Set the service state test intent.
*
* @param intent The service state test intent.
*/
public void setServiceStateTestIntent(@NonNull Intent intent) {
+ // Don't process if the intent is not prepared for this phone slot.
+ if (mPhone.getPhoneId() != intent.getIntExtra(EXTRA_PHONE_ID, mPhone.getPhoneId())) return;
mServiceStateTestIntent = intent;
// Trigger the service state update. The replacement will be done in
// overrideServiceState().
@@ -400,10 +464,6 @@
void overrideServiceState(ServiceState ss) {
if (mServiceStateTestIntent == null || ss == null) return;
- if (mPhone.getPhoneId() != mServiceStateTestIntent.getIntExtra(
- EXTRA_PHONE_ID, mPhone.getPhoneId())) {
- return;
- }
if (mServiceStateTestIntent.hasExtra(EXTRA_ACTION)
&& ACTION_RESET.equals(mServiceStateTestIntent.getStringExtra(EXTRA_ACTION))) {
log("Service state override reset");
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
index cadb02e..4da1622 100644
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -284,6 +284,14 @@
CatLog.d(this, "Disposing CatService object");
mIccRecords.unregisterForRecordsLoaded(this);
+ if (sFlags.unregisterSmsBroadcastReceiverFromCatService()) {
+ try {
+ mContext.unregisterReceiver(mSmsBroadcastReceiver);
+ } catch (IllegalArgumentException e) {
+ CatLog.e(this, "mSmsBroadcastReceiver: was not registered" + e);
+ }
+ }
+
// Clean up stk icon if dispose is called
broadcastCardStateAndIccRefreshResp(CardState.CARDSTATE_ABSENT, null);
diff --git a/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java b/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
index 4b10cae..f9261ff 100644
--- a/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
+++ b/src/java/com/android/internal/telephony/cat/RilMessageDecoder.java
@@ -24,6 +24,7 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.telephony.uicc.IccFileHandler;
import com.android.internal.telephony.uicc.IccUtils;
import com.android.internal.util.State;
@@ -40,11 +41,14 @@
private static final int CMD_START = 1;
private static final int CMD_PARAMS_READY = 2;
+ private final Object mLock = new Object();
// members
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
+ @GuardedBy("mLock")
private CommandParamsFactory mCmdParamsFactory = null;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private RilMessage mCurrentRilMessage = null;
+ @GuardedBy("mLock")
private Handler mCaller = null;
private static int mSimCount = 0;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -113,9 +117,13 @@
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
private void sendCmdForExecution(RilMessage rilMsg) {
- Message msg = mCaller.obtainMessage(CatService.MSG_ID_RIL_MSG_DECODED,
- new RilMessage(rilMsg));
- msg.sendToTarget();
+ synchronized (mLock) {
+ if (mCaller != null) {
+ Message msg = mCaller.obtainMessage(CatService.MSG_ID_RIL_MSG_DECODED,
+ new RilMessage(rilMsg));
+ msg.sendToTarget();
+ }
+ }
}
private RilMessageDecoder(Handler caller, IccFileHandler fh, Context context) {
@@ -125,8 +133,10 @@
addState(mStateCmdParamsReady);
setInitialState(mStateStart);
- mCaller = caller;
- mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh, context);
+ synchronized (mLock) {
+ mCaller = caller;
+ mCmdParamsFactory = CommandParamsFactory.getInstance(this, fh, context);
+ }
}
private RilMessageDecoder() {
@@ -166,7 +176,7 @@
}
private boolean decodeMessageParams(RilMessage rilMsg) {
- boolean decodingStarted;
+ boolean decodingStarted = false;
mCurrentRilMessage = rilMsg;
switch(rilMsg.mId) {
@@ -188,16 +198,21 @@
decodingStarted = false;
break;
}
- try {
- // Start asynch parsing of the command parameters.
- mCmdParamsFactory.make(BerTlv.decode(rawData));
- decodingStarted = true;
- } catch (ResultException e) {
- // send to Service for proper RIL communication.
- CatLog.d(this, "decodeMessageParams: caught ResultException e=" + e);
- mCurrentRilMessage.mResCode = e.result();
- sendCmdForExecution(mCurrentRilMessage);
- decodingStarted = false;
+
+ synchronized (mLock) {
+ if (mCmdParamsFactory != null) {
+ try {
+ // Start asynch parsing of the command parameters.
+ mCmdParamsFactory.make(BerTlv.decode(rawData));
+ decodingStarted = true;
+ } catch (ResultException e) {
+ // send to Service for proper RIL communication.
+ CatLog.d(this, "decodeMessageParams: caught ResultException e=" + e);
+ mCurrentRilMessage.mResCode = e.result();
+ sendCmdForExecution(mCurrentRilMessage);
+ decodingStarted = false;
+ }
+ }
}
break;
default:
@@ -211,10 +226,16 @@
quitNow();
mStateStart = null;
mStateCmdParamsReady = null;
- mCmdParamsFactory.dispose();
- mCmdParamsFactory = null;
+
+ synchronized (mLock) {
+ if (mCmdParamsFactory != null) {
+ mCmdParamsFactory.dispose();
+ mCmdParamsFactory = null;
+ }
+ mCaller = null;
+ }
+
mCurrentRilMessage = null;
- mCaller = null;
mInstance = null;
}
}
diff --git a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
index 0db7844..85413f5 100644
--- a/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
+++ b/src/java/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiver.java
@@ -20,12 +20,16 @@
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
+import android.os.FileUtils;
import android.util.Log;
-import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.satellite.SatelliteConfig;
import com.android.internal.telephony.satellite.SatelliteConfigParser;
+import com.android.internal.telephony.satellite.SatelliteConstants;
+import com.android.internal.telephony.satellite.metrics.ConfigUpdaterMetricsStats;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.server.updates.ConfigUpdateInstallReceiver;
import libcore.io.IoUtils;
@@ -33,6 +37,8 @@
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
@@ -43,7 +49,8 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected static final String UPDATE_DIR = "/data/misc/telephonyconfig";
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected static final String UPDATE_CONTENT_PATH = "telephony_config.pb";
+ protected static final String NEW_CONFIG_CONTENT_PATH = "new_telephony_config.pb";
+ protected static final String VALID_CONFIG_CONTENT_PATH = "valid_telephony_config.pb";
protected static final String UPDATE_METADATA_PATH = "metadata/";
public static final String VERSION = "version";
@@ -52,6 +59,7 @@
private final Object mConfigParserLock = new Object();
@GuardedBy("mConfigParserLock")
private ConfigParser mConfigParser;
+ @NonNull private final ConfigUpdaterMetricsStats mConfigUpdaterMetricsStats;
public static TelephonyConfigUpdateInstallReceiver sReceiverAdaptorInstance =
@@ -66,7 +74,8 @@
}
public TelephonyConfigUpdateInstallReceiver() {
- super(UPDATE_DIR, UPDATE_CONTENT_PATH, UPDATE_METADATA_PATH, VERSION);
+ super(UPDATE_DIR, NEW_CONFIG_CONTENT_PATH, UPDATE_METADATA_PATH, VERSION);
+ mConfigUpdaterMetricsStats = ConfigUpdaterMetricsStats.getOrCreateInstance();
}
/**
@@ -74,57 +83,105 @@
*/
@Nullable
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public byte[] getCurrentContent() {
+ public byte[] getContentFromContentPath(@NonNull File contentPath) {
try {
- return IoUtils.readFileAsByteArray(updateContent.getCanonicalPath());
+ return IoUtils.readFileAsByteArray(contentPath.getCanonicalPath());
} catch (IOException e) {
- Slog.i(TAG, "Failed to read current content, assuming first update!");
+ Log.e(TAG, "Failed to read current content : " + contentPath);
return null;
}
}
+ /**
+ * @param parser target of validation.
+ * @return {@code true} if all the config data are valid {@code false} otherwise.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean isValidSatelliteCarrierConfigData(@NonNull ConfigParser parser) {
+ SatelliteConfig satelliteConfig = (SatelliteConfig) parser.getConfig();
+ if (satelliteConfig == null) {
+ Log.e(TAG, "satelliteConfig is null");
+ mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError(
+ SatelliteConstants.CONFIG_UPDATE_RESULT_NO_SATELLITE_DATA);
+ return false;
+ }
+
+ // If no carrier config exist then it is considered as a valid config
+ Set<Integer> carrierIds = satelliteConfig.getAllSatelliteCarrierIds();
+ for (int carrierId : carrierIds) {
+ Map<String, Set<Integer>> plmnsServices =
+ satelliteConfig.getSupportedSatelliteServices(carrierId);
+ Set<String> plmns = plmnsServices.keySet();
+ for (String plmn : plmns) {
+ if (!TelephonyUtils.isValidPlmn(plmn)) {
+ Log.e(TAG, "found invalid plmn : " + plmn);
+ mConfigUpdaterMetricsStats.reportCarrierConfigError(
+ SatelliteConstants.CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_PLMN);
+ return false;
+ }
+ Set<Integer> serviceSet = plmnsServices.get(plmn);
+ for (int service : serviceSet) {
+ if (!TelephonyUtils.isValidService(service)) {
+ Log.e(TAG, "found invalid service : " + service);
+ mConfigUpdaterMetricsStats.reportCarrierConfigError(SatelliteConstants
+ .CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_SUPPORTED_SERVICES);
+ return false;
+ }
+ }
+ }
+ }
+ Log.d(TAG, "the config data is valid");
+ return true;
+ }
+
+
@Override
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED)
public void postInstall(Context context, Intent intent) {
Log.d(TAG, "Telephony config is updated in file partition");
- ConfigParser updatedConfigParser = getNewConfigParser(DOMAIN_SATELLITE,
- getCurrentContent());
- if (updatedConfigParser == null) {
- Log.d(TAG, "updatedConfigParser is null");
+ ConfigParser newConfigParser = getNewConfigParser(DOMAIN_SATELLITE,
+ getContentFromContentPath(updateContent));
+
+ if (newConfigParser == null) {
+ Log.e(TAG, "newConfigParser is null");
return;
}
- boolean isParserChanged = false;
+ if (!isValidSatelliteCarrierConfigData(newConfigParser)) {
+ Log.e(TAG, "received config data has invalid satellite carrier config data");
+ return;
+ }
synchronized (getInstance().mConfigParserLock) {
- if (getInstance().mConfigParser == null) {
- getInstance().mConfigParser = updatedConfigParser;
- isParserChanged = true;
- } else {
- int updatedVersion = updatedConfigParser.mVersion;
+ if (getInstance().mConfigParser != null) {
+ int updatedVersion = newConfigParser.mVersion;
int previousVersion = getInstance().mConfigParser.mVersion;
Log.d(TAG, "previous version is " + previousVersion + " | updated version is "
+ updatedVersion);
- if (updatedVersion > previousVersion) {
- getInstance().mConfigParser = updatedConfigParser;
- isParserChanged = true;
+ mConfigUpdaterMetricsStats.setConfigVersion(updatedVersion);
+ if (updatedVersion <= previousVersion) {
+ Log.e(TAG, "updatedVersion is smaller than previousVersion");
+ mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError(
+ SatelliteConstants.CONFIG_UPDATE_RESULT_INVALID_VERSION);
+ return;
}
}
+ getInstance().mConfigParser = newConfigParser;
+ }
+
+ if (!getInstance().mCallbackHashMap.keySet().isEmpty()) {
+ Iterator<Executor> iterator = getInstance().mCallbackHashMap.keySet().iterator();
+ while (iterator.hasNext()) {
+ Executor executor = iterator.next();
+ getInstance().mCallbackHashMap.get(executor).onChanged(newConfigParser);
+ }
}
- if (isParserChanged) {
- if (getInstance().mCallbackHashMap.keySet().isEmpty()) {
- Log.d(TAG, "mCallbackHashMap.keySet().isEmpty");
- return;
- }
- Iterator<Executor> iterator =
- getInstance().mCallbackHashMap.keySet().iterator();
- while (iterator.hasNext()) {
- Executor executor = iterator.next();
- getInstance().mCallbackHashMap.get(executor).onChanged(
- updatedConfigParser);
- }
+ if (!copySourceFileToTargetFile(NEW_CONFIG_CONTENT_PATH, VALID_CONFIG_CONTENT_PATH)) {
+ Log.e(TAG, "fail to copy to the valid satellite carrier config data");
+ mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError(
+ SatelliteConstants.CONFIG_UPDATE_RESULT_IO_ERROR);
}
}
@@ -135,7 +192,9 @@
synchronized (getInstance().mConfigParserLock) {
if (getInstance().mConfigParser == null) {
Log.d(TAG, "CreateNewConfigParser with domain " + domain);
- getInstance().mConfigParser = getNewConfigParser(domain, getCurrentContent());
+ getInstance().mConfigParser = getNewConfigParser(
+ domain, getContentFromContentPath(new File(updateDir,
+ VALID_CONFIG_CONTENT_PATH)));
}
return getInstance().mConfigParser;
}
@@ -187,6 +246,8 @@
public ConfigParser getNewConfigParser(String domain, @Nullable byte[] data) {
if (data == null) {
Log.d(TAG, "content data is null");
+ mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError(
+ SatelliteConstants.CONFIG_UPDATE_RESULT_NO_DATA);
return null;
}
switch (domain) {
@@ -194,7 +255,40 @@
return new SatelliteConfigParser(data);
default:
Log.e(TAG, "DOMAIN should be specified");
+ mConfigUpdaterMetricsStats.reportOemAndCarrierConfigError(
+ SatelliteConstants.CONFIG_UPDATE_RESULT_INVALID_DOMAIN);
return null;
}
}
+
+ /**
+ * @param sourceFileName source file name
+ * @param targetFileName target file name
+ * @return {@code true} if successful, {@code false} otherwise
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ public boolean copySourceFileToTargetFile(
+ @NonNull String sourceFileName, @NonNull String targetFileName) {
+ try {
+ File sourceFile = new File(UPDATE_DIR, sourceFileName);
+ File targetFile = new File(UPDATE_DIR, targetFileName);
+ Log.d(TAG, "copy " + sourceFile.getName() + " >> " + targetFile.getName());
+
+ if (sourceFile.exists()) {
+ if (targetFile.exists()) {
+ targetFile.delete();
+ }
+ FileUtils.copy(sourceFile, targetFile);
+ FileUtils.copyPermissions(sourceFile, targetFile);
+ Log.d(TAG, "success to copy the file " + sourceFile.getName() + " to "
+ + targetFile.getName());
+ return true;
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "copy error : " + e);
+ return false;
+ }
+ Log.d(TAG, "source file is not exist, no file to copy");
+ return false;
+ }
}
diff --git a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
index 3d3fbe9..bc684af 100644
--- a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
@@ -69,7 +69,6 @@
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
-import java.util.function.Consumer;
import java.util.stream.Collectors;
/**
@@ -86,7 +85,8 @@
/**
* The counters to detect frequent QNS attempt to change preferred network transport by ApnType.
*/
- private final @NonNull SparseArray<SlidingWindowEventCounter> mApnTypeToQnsChangeNetworkCounter;
+ @NonNull
+ private final SparseArray<SlidingWindowEventCounter> mApnTypeToQnsChangeNetworkCounter;
private final String mLogTag;
private final LocalLog mLocalLog = new LocalLog(64);
@@ -109,12 +109,11 @@
private final CarrierConfigManager mCarrierConfigManager;
- private @Nullable DataConfigManager mDataConfigManager;
+ @Nullable
+ private DataConfigManager mDataConfigManager;
private IQualifiedNetworksService mIQualifiedNetworksService;
- private AccessNetworksManagerDeathRecipient mDeathRecipient;
-
private String mTargetBindingPackageName;
private QualifiedNetworksServiceConnection mServiceConnection;
@@ -122,7 +121,8 @@
// Available networks. Key is the APN type.
private final SparseArray<int[]> mAvailableNetworks = new SparseArray<>();
- private final @TransportType int[] mAvailableTransports;
+ @TransportType
+ private final int[] mAvailableTransports;
private final RegistrantList mQualifiedNetworksChangedRegistrants = new RegistrantList();
@@ -135,7 +135,8 @@
/**
* Callbacks for passing information to interested clients.
*/
- private final @NonNull Set<AccessNetworksManagerCallback> mAccessNetworksManagerCallbacks =
+ @NonNull
+ private final Set<AccessNetworksManagerCallback> mAccessNetworksManagerCallbacks =
new ArraySet<>();
private final FeatureFlags mFeatureFlags;
@@ -144,9 +145,12 @@
* Represents qualified network types list on a specific APN type.
*/
public static class QualifiedNetworks {
- public final @ApnType int apnType;
+ @ApnType
+ public final int apnType;
// The qualified networks in preferred order. Each network is a AccessNetworkType.
- public final @NonNull @RadioAccessNetworkType int[] qualifiedNetworks;
+ @NonNull
+ @RadioAccessNetworkType
+ public final int[] qualifiedNetworks;
public QualifiedNetworks(@ApnType int apnType, @NonNull int[] qualifiedNetworks) {
this.apnType = apnType;
this.qualifiedNetworks = Arrays.stream(qualifiedNetworks)
@@ -198,11 +202,12 @@
public void onServiceConnected(ComponentName name, IBinder service) {
if (DBG) log("onServiceConnected " + name);
mIQualifiedNetworksService = IQualifiedNetworksService.Stub.asInterface(service);
- mDeathRecipient = new AccessNetworksManagerDeathRecipient();
+ AccessNetworksManagerDeathRecipient deathRecipient =
+ new AccessNetworksManagerDeathRecipient();
mLastBoundPackageName = getQualifiedNetworksServicePackageName();
try {
- service.linkToDeath(mDeathRecipient, 0 /* flags */);
+ service.linkToDeath(deathRecipient, 0 /* flags */);
mIQualifiedNetworksService.createNetworkAvailabilityProvider(mPhone.getPhoneId(),
new QualifiedNetworksServiceCallback());
} catch (RemoteException e) {
@@ -310,7 +315,7 @@
/**
* Called when QualifiedNetworksService requests network validation.
- *
+ * <p>
* Since the data network in the connected state corresponding to the given network
* capability must be validated, a request is tossed to the data network controller.
* @param networkCapability network capability
@@ -328,27 +333,22 @@
log("onNetworkValidationRequested: networkCapability = ["
+ DataUtils.networkCapabilityToString(networkCapability) + "]");
- dnc.requestNetworkValidation(networkCapability, new Consumer<Integer>() {
- @Override
- public void accept(Integer result) {
- post(() -> {
- try {
- log("onNetworkValidationRequestDone:"
- + DataServiceCallback.resultCodeToString(result));
- resultCodeCallback.accept(result.intValue());
- } catch (RemoteException e) {
- // Ignore if the remote process is no longer available to call back.
- loge("onNetworkValidationRequestDone RemoteException" + e);
- }
- });
+ dnc.requestNetworkValidation(networkCapability, result -> post(() -> {
+ try {
+ log("onNetworkValidationRequestDone:"
+ + DataServiceCallback.resultCodeToString(result));
+ resultCodeCallback.accept(result);
+ } catch (RemoteException e) {
+ // Ignore if the remote process is no longer available to call back.
+ loge("onNetworkValidationRequestDone RemoteException" + e);
}
- });
+ }));
}
@Override
- public void onReconnectQualifedNetworkType(int apnTypes, int qualifiedNetworkType) {
+ public void onReconnectQualifiedNetworkType(int apnTypes, int qualifiedNetworkType) {
if (mFeatureFlags.reconnectQualifiedNetwork()) {
- log("onReconnectQualifedNetworkType: apnTypes = ["
+ log("onReconnectQualifiedNetworkType: apnTypes = ["
+ ApnSetting.getApnTypesStringFromBitmask(apnTypes)
+ "], networks = [" + AccessNetworkType.toString(qualifiedNetworkType)
+ "]");
@@ -431,7 +431,8 @@
mPhone.getDataNetworkController().getDataRetryManager().registerCallback(
new DataRetryManager.DataRetryManagerCallback(this::post) {
@Override
- public void onThrottleStatusChanged(List<ThrottleStatus> throttleStatuses) {
+ public void onThrottleStatusChanged(
+ @NonNull List<ThrottleStatus> throttleStatuses) {
try {
logl("onThrottleStatusChanged: " + throttleStatuses);
if (mIQualifiedNetworksService != null) {
@@ -473,7 +474,7 @@
*/
private void bindQualifiedNetworksService() {
post(() -> {
- Intent intent = null;
+ Intent intent;
String packageName = getQualifiedNetworksServicePackageName();
String className = getQualifiedNetworksServiceClassName();
@@ -540,7 +541,7 @@
b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId(),
CarrierConfigManager
.KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING);
- if (b != null && !b.isEmpty()) {
+ if (!b.isEmpty()) {
// If carrier config overrides it, use the one from carrier config
String carrierConfigPackageName = b.getString(CarrierConfigManager
.KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING);
@@ -571,7 +572,7 @@
b = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId(),
CarrierConfigManager
.KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_CLASS_OVERRIDE_STRING);
- if (b != null && !b.isEmpty()) {
+ if (!b.isEmpty()) {
// If carrier config overrides it, use the one from carrier config
String carrierConfigClassName = b.getString(CarrierConfigManager
.KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_CLASS_OVERRIDE_STRING);
@@ -587,7 +588,8 @@
return className;
}
- private @NonNull List<QualifiedNetworks> getQualifiedNetworksList() {
+ @NonNull
+ private List<QualifiedNetworks> getQualifiedNetworksList() {
List<QualifiedNetworks> qualifiedNetworksList = new ArrayList<>();
for (int i = 0; i < mAvailableNetworks.size(); i++) {
qualifiedNetworksList.add(new QualifiedNetworks(mAvailableNetworks.keyAt(i),
@@ -619,11 +621,13 @@
/**
* @return The available transports.
*/
- public @NonNull int[] getAvailableTransports() {
+ @NonNull
+ public int[] getAvailableTransports() {
return mAvailableTransports;
}
- private static @TransportType int getTransportFromAccessNetwork(int accessNetwork) {
+ @TransportType
+ private static int getTransportFromAccessNetwork(int accessNetwork) {
return accessNetwork == AccessNetworkType.IWLAN
? AccessNetworkConstants.TRANSPORT_TYPE_WLAN
: AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
@@ -656,7 +660,8 @@
* @param apnType APN type
* @return The preferred transport.
*/
- public @TransportType int getPreferredTransport(@ApnType int apnType) {
+ @TransportType
+ public int getPreferredTransport(@ApnType int apnType) {
return mPreferredTransports.get(apnType) == null
? AccessNetworkConstants.TRANSPORT_TYPE_WWAN : mPreferredTransports.get(apnType);
}
@@ -668,8 +673,8 @@
* supported.)
* @return The preferred transport.
*/
- public @TransportType int getPreferredTransportByNetworkCapability(
- @NetCapability int networkCapability) {
+ @TransportType
+ public int getPreferredTransportByNetworkCapability(@NetCapability int networkCapability) {
int apnType = DataUtils.networkCapabilityToApnType(networkCapability);
// For non-APN type capabilities, always route to WWAN.
if (apnType == ApnSetting.TYPE_NONE) {
diff --git a/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java b/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
index 343bb0b..7486b61 100644
--- a/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
+++ b/src/java/com/android/internal/telephony/data/AutoDataSwitchController.java
@@ -137,17 +137,26 @@
private static final long RETRY_LONG_DELAY_TIMER_THRESHOLD_MILLIS = TimeUnit
.MINUTES.toMillis(1);
- private final @NonNull LocalLog mLocalLog = new LocalLog(128);
- private final @NonNull Context mContext;
- private static @NonNull FeatureFlags sFeatureFlags = new FeatureFlagsImpl();
- private final @NonNull SubscriptionManagerService mSubscriptionManagerService;
- private final @NonNull PhoneSwitcher mPhoneSwitcher;
- private final @NonNull AutoDataSwitchControllerCallback mPhoneSwitcherCallback;
- private final @NonNull AlarmManager mAlarmManager;
+ @NonNull
+ private final LocalLog mLocalLog = new LocalLog(128);
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private static FeatureFlags sFeatureFlags = new FeatureFlagsImpl();
+ @NonNull
+ private final SubscriptionManagerService mSubscriptionManagerService;
+ @NonNull
+ private final PhoneSwitcher mPhoneSwitcher;
+ @NonNull
+ private final AutoDataSwitchControllerCallback mPhoneSwitcherCallback;
+ @NonNull
+ private final AlarmManager mAlarmManager;
/** A map of a scheduled event to its associated extra for action when the event fires off. */
- private final @NonNull Map<Integer, Object> mScheduledEventsToExtras;
+ @NonNull
+ private final Map<Integer, Object> mScheduledEventsToExtras;
/** A map of an event to its associated alarm listener callback for when the event fires off. */
- private final @NonNull Map<Integer, AlarmManager.OnAlarmListener> mEventsToAlarmListener;
+ @NonNull
+ private final Map<Integer, AlarmManager.OnAlarmListener> mEventsToAlarmListener;
/**
* Event extras for checking environment stability.
* @param targetPhoneId The target phone Id to switch to when the stability check pass.
@@ -193,7 +202,7 @@
* To indicate whether allow using roaming nDDS if user enabled its roaming when the DDS is not
* usable(OOS or disabled roaming)
*/
- private boolean mAllowNddsRoamning = true;
+ private boolean mAllowNddsRoaming = true;
/** The count of consecutive auto switch validation failure **/
private int mAutoSwitchValidationFailedCount = 0;
/**
@@ -202,7 +211,8 @@
private int mAutoDataSwitchValidationMaxRetry;
/** The signal status of phones, where index corresponds to phone Id. */
- private @NonNull PhoneSignalStatus[] mPhonesSignalStatus;
+ @NonNull
+ private PhoneSignalStatus[] mPhonesSignalStatus;
/**
* The phone Id of the pending switching phone. Used for pruning frequent switch evaluation.
*/
@@ -268,23 +278,24 @@
boolean isUsingNonTerrestrialNetwork = sFeatureFlags.carrierEnabledSatelliteFlag()
&& (serviceState != null) && serviceState.isUsingNonTerrestrialNetwork();
- switch (mDataRegState) {
- case NetworkRegistrationInfo.REGISTRATION_STATE_HOME:
+ return switch (mDataRegState) {
+ case NetworkRegistrationInfo.REGISTRATION_STATE_HOME -> {
if (isUsingNonTerrestrialNetwork) {
- return UsableState.NON_TERRESTRIAL;
+ yield UsableState.NON_TERRESTRIAL;
}
- return UsableState.HOME;
- case NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING:
+ yield UsableState.HOME;
+ }
+ case NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING -> {
if (mPhone.getDataRoamingEnabled()) {
if (isUsingNonTerrestrialNetwork) {
- return UsableState.NON_TERRESTRIAL;
+ yield UsableState.NON_TERRESTRIAL;
}
- return UsableState.ROAMING_ENABLED;
+ yield UsableState.ROAMING_ENABLED;
}
- return UsableState.NOT_USABLE;
- default:
- return UsableState.NOT_USABLE;
- }
+ yield UsableState.NOT_USABLE;
+ }
+ default -> UsableState.NOT_USABLE;
+ };
}
@Override
@@ -450,7 +461,7 @@
DataConfigManager dataConfig = phone.getDataNetworkController().getDataConfigManager();
mScoreTolerance = dataConfig.getAutoDataSwitchScoreTolerance();
mRequirePingTestBeforeSwitch = dataConfig.isPingTestBeforeAutoDataSwitchRequired();
- mAllowNddsRoamning = dataConfig.doesAutoDataSwitchAllowRoaming();
+ mAllowNddsRoaming = dataConfig.doesAutoDataSwitchAllowRoaming();
mAutoDataSwitchAvailabilityStabilityTimeThreshold =
dataConfig.getAutoDataSwitchAvailabilityStabilityTimeThreshold();
mAutoDataSwitchPerformanceStabilityTimeThreshold =
@@ -462,6 +473,7 @@
@Override
public void handleMessage(@NonNull Message msg) {
AsyncResult ar;
+ Object obj;
int phoneId;
switch (msg.what) {
case EVENT_SERVICE_STATE_CHANGED:
@@ -480,33 +492,20 @@
onSignalStrengthChanged(phoneId);
break;
case EVENT_EVALUATE_AUTO_SWITCH:
- if (sFeatureFlags.autoDataSwitchRatSs()) {
- Object obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH);
- if (obj instanceof EvaluateEventExtra extra) {
- mScheduledEventsToExtras.remove(EVENT_EVALUATE_AUTO_SWITCH);
- onEvaluateAutoDataSwitch(extra.evaluateReason);
- }
- } else {
- int reason = (int) msg.obj;
- onEvaluateAutoDataSwitch(reason);
+ obj = mScheduledEventsToExtras.get(EVENT_EVALUATE_AUTO_SWITCH);
+ if (obj instanceof EvaluateEventExtra extra) {
+ mScheduledEventsToExtras.remove(EVENT_EVALUATE_AUTO_SWITCH);
+ onEvaluateAutoDataSwitch(extra.evaluateReason);
}
break;
case EVENT_STABILITY_CHECK_PASSED:
- if (sFeatureFlags.autoDataSwitchRatSs()) {
- Object obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED);
- if (obj instanceof StabilityEventExtra extra) {
- int targetPhoneId = extra.targetPhoneId;
- boolean needValidation = extra.needValidation;
- log("require validation on phone " + targetPhoneId
- + (needValidation ? "" : " no") + " need to pass");
- mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED);
- mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation);
- }
- } else {
- int targetPhoneId = msg.arg1;
- boolean needValidation = msg.arg2 == 1;
+ obj = mScheduledEventsToExtras.get(EVENT_STABILITY_CHECK_PASSED);
+ if (obj instanceof StabilityEventExtra extra) {
+ int targetPhoneId = extra.targetPhoneId;
+ boolean needValidation = extra.needValidation;
log("require validation on phone " + targetPhoneId
+ (needValidation ? "" : " no") + " need to pass");
+ mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED);
mPhoneSwitcherCallback.onRequireValidation(targetPhoneId, needValidation);
}
break;
@@ -632,15 +631,9 @@
? mAutoDataSwitchAvailabilityStabilityTimeThreshold
<< mAutoSwitchValidationFailedCount
: 0;
- if (sFeatureFlags.autoDataSwitchRatSs()) {
- if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) {
- scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason),
- delayMs);
- }
- } else {
- if (!hasMessages(EVENT_EVALUATE_AUTO_SWITCH)) {
- sendMessageDelayed(obtainMessage(EVENT_EVALUATE_AUTO_SWITCH, reason), delayMs);
- }
+ if (!mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) {
+ scheduleEventWithTimer(EVENT_EVALUATE_AUTO_SWITCH, new EvaluateEventExtra(reason),
+ delayMs);
}
}
@@ -689,12 +682,32 @@
return;
}
- if (!defaultDataPhone.isUserDataEnabled() || !backupDataPhone.isDataAllowed()) {
- mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX,
- EVALUATION_REASON_DATA_SETTINGS_CHANGED);
- log(debugMessage.append(", immediately back to default as user turns off settings")
- .toString());
- return;
+ DataEvaluation internetEvaluation;
+ if (sFeatureFlags.autoDataSwitchUsesDataEnabled()) {
+ if (!defaultDataPhone.isUserDataEnabled()) {
+ mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX,
+ EVALUATION_REASON_DATA_SETTINGS_CHANGED);
+ log(debugMessage.append(
+ ", immediately back to default as user turns off default").toString());
+ return;
+ } else if (!(internetEvaluation = backupDataPhone.getDataNetworkController()
+ .getInternetEvaluation(false/*ignoreExistingNetworks*/))
+ .isSubsetOf(DataEvaluation.DataDisallowedReason.NOT_IN_SERVICE)) {
+ mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(
+ DEFAULT_PHONE_INDEX, EVALUATION_REASON_DATA_SETTINGS_CHANGED);
+ log(debugMessage.append(
+ ", immediately back to default because backup ")
+ .append(internetEvaluation).toString());
+ return;
+ }
+ } else {
+ if (!defaultDataPhone.isUserDataEnabled() || !backupDataPhone.isDataAllowed()) {
+ mPhoneSwitcherCallback.onRequireImmediatelySwitchToPhone(DEFAULT_PHONE_INDEX,
+ EVALUATION_REASON_DATA_SETTINGS_CHANGED);
+ log(debugMessage.append(
+ ", immediately back to default as user turns off settings").toString());
+ return;
+ }
}
boolean backToDefault = false;
@@ -904,12 +917,15 @@
}
if (secondaryDataPhone != null) {
- // check auto switch feature enabled
- if (secondaryDataPhone.isDataAllowed()) {
+ // check internet data is allowed on the candidate
+ DataEvaluation internetEvaluation = secondaryDataPhone.getDataNetworkController()
+ .getInternetEvaluation(false/*ignoreExistingNetworks*/);
+ if (!internetEvaluation.containsDisallowedReasons()) {
return new StabilityEventExtra(phoneId,
isForPerformance, mRequirePingTestBeforeSwitch);
} else {
- debugMessage.append(", but candidate's data is not allowed");
+ debugMessage.append(", but candidate's data is not allowed ")
+ .append(internetEvaluation);
}
}
}
@@ -921,15 +937,14 @@
* @return {@code true} If the feature of switching base on RAT and signal strength is enabled.
*/
private boolean isRatSignalStrengthBasedSwitchEnabled() {
- return sFeatureFlags.autoDataSwitchRatSs() && mScoreTolerance >= 0
- && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0;
+ return mScoreTolerance >= 0 && mAutoDataSwitchPerformanceStabilityTimeThreshold >= 0;
}
/**
* @return {@code true} If the feature of switching to roaming non DDS is enabled.
*/
private boolean isNddsRoamingEnabled() {
- return sFeatureFlags.autoDataSwitchAllowRoaming() && mAllowNddsRoamning;
+ return sFeatureFlags.autoDataSwitchAllowRoaming() && mAllowNddsRoaming;
}
/**
@@ -942,39 +957,27 @@
*/
private void startStabilityCheck(int targetPhoneId, boolean isForPerformance,
boolean needValidation) {
- String combinationIdentifier = targetPhoneId + "" + needValidation;
- if (sFeatureFlags.autoDataSwitchRatSs()) {
- StabilityEventExtra eventExtras = (StabilityEventExtra)
- mScheduledEventsToExtras.getOrDefault(EVENT_STABILITY_CHECK_PASSED,
- new StabilityEventExtra(INVALID_PHONE_INDEX, false /*need validation*/,
- false /*isForPerformance*/));
- long delayMs = -1;
- // Check if already scheduled one with that combination of extras.
- if (eventExtras.targetPhoneId != targetPhoneId
- || eventExtras.needValidation != needValidation
- || eventExtras.isForPerformance != isForPerformance) {
- eventExtras =
- new StabilityEventExtra(targetPhoneId, isForPerformance, needValidation);
+ StabilityEventExtra eventExtras = (StabilityEventExtra)
+ mScheduledEventsToExtras.getOrDefault(EVENT_STABILITY_CHECK_PASSED,
+ new StabilityEventExtra(INVALID_PHONE_INDEX, false /*need validation*/,
+ false /*isForPerformance*/));
+ long delayMs = -1;
+ // Check if already scheduled one with that combination of extras.
+ if (eventExtras.targetPhoneId != targetPhoneId
+ || eventExtras.needValidation != needValidation
+ || eventExtras.isForPerformance != isForPerformance) {
+ eventExtras =
+ new StabilityEventExtra(targetPhoneId, isForPerformance, needValidation);
- // Reset with new timer.
- delayMs = isForPerformance
- ? mAutoDataSwitchPerformanceStabilityTimeThreshold
- : mAutoDataSwitchAvailabilityStabilityTimeThreshold;
- scheduleEventWithTimer(EVENT_STABILITY_CHECK_PASSED, eventExtras, delayMs);
- }
- log("startStabilityCheck: "
- + (delayMs != -1 ? "scheduling " : "already scheduled ")
- + eventExtras);
- } else if (!hasEqualMessages(EVENT_STABILITY_CHECK_PASSED, combinationIdentifier)) {
- removeMessages(EVENT_STABILITY_CHECK_PASSED);
- sendMessageDelayed(obtainMessage(EVENT_STABILITY_CHECK_PASSED, targetPhoneId,
- needValidation ? 1 : 0,
- combinationIdentifier),
- mAutoDataSwitchAvailabilityStabilityTimeThreshold);
- log("startStabilityCheck: targetPhoneId=" + targetPhoneId
- + " isForPerformance=" + isForPerformance
- + " needValidation=" + needValidation);
+ // Reset with new timer.
+ delayMs = isForPerformance
+ ? mAutoDataSwitchPerformanceStabilityTimeThreshold
+ : mAutoDataSwitchAvailabilityStabilityTimeThreshold;
+ scheduleEventWithTimer(EVENT_STABILITY_CHECK_PASSED, eventExtras, delayMs);
}
+ log("startStabilityCheck: "
+ + (delayMs != -1 ? "scheduling " : "already scheduled ")
+ + eventExtras);
}
/**
@@ -1012,19 +1015,20 @@
}
/** Auto data switch evaluation reason to string. */
- public static @NonNull String evaluationReasonToString(
+ @NonNull
+ public static String evaluationReasonToString(
@AutoDataSwitchEvaluationReason int reason) {
- switch (reason) {
- case EVALUATION_REASON_REGISTRATION_STATE_CHANGED: return "REGISTRATION_STATE_CHANGED";
- case EVALUATION_REASON_DISPLAY_INFO_CHANGED: return "DISPLAY_INFO_CHANGED";
- case EVALUATION_REASON_SIGNAL_STRENGTH_CHANGED: return "SIGNAL_STRENGTH_CHANGED";
- case EVALUATION_REASON_DEFAULT_NETWORK_CHANGED: return "DEFAULT_NETWORK_CHANGED";
- case EVALUATION_REASON_DATA_SETTINGS_CHANGED: return "DATA_SETTINGS_CHANGED";
- case EVALUATION_REASON_RETRY_VALIDATION: return "RETRY_VALIDATION";
- case EVALUATION_REASON_SIM_LOADED: return "SIM_LOADED";
- case EVALUATION_REASON_VOICE_CALL_END: return "VOICE_CALL_END";
- }
- return "Unknown(" + reason + ")";
+ return switch (reason) {
+ case EVALUATION_REASON_REGISTRATION_STATE_CHANGED -> "REGISTRATION_STATE_CHANGED";
+ case EVALUATION_REASON_DISPLAY_INFO_CHANGED -> "DISPLAY_INFO_CHANGED";
+ case EVALUATION_REASON_SIGNAL_STRENGTH_CHANGED -> "SIGNAL_STRENGTH_CHANGED";
+ case EVALUATION_REASON_DEFAULT_NETWORK_CHANGED -> "DEFAULT_NETWORK_CHANGED";
+ case EVALUATION_REASON_DATA_SETTINGS_CHANGED -> "DATA_SETTINGS_CHANGED";
+ case EVALUATION_REASON_RETRY_VALIDATION -> "RETRY_VALIDATION";
+ case EVALUATION_REASON_SIM_LOADED -> "SIM_LOADED";
+ case EVALUATION_REASON_VOICE_CALL_END -> "VOICE_CALL_END";
+ default -> "Unknown(" + reason + ")";
+ };
}
/** @return {@code true} if the sub is active. */
@@ -1063,18 +1067,14 @@
private void cancelAnyPendingSwitch() {
mSelectedTargetPhoneId = INVALID_PHONE_INDEX;
resetFailedCount();
- if (sFeatureFlags.autoDataSwitchRatSs()) {
- if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
- if (mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
- mAlarmManager.cancel(mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED));
- } else {
- loge("cancelAnyPendingSwitch: EVENT_STABILITY_CHECK_PASSED listener is null");
- }
- removeMessages(EVENT_STABILITY_CHECK_PASSED);
- mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED);
+ if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
+ if (mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
+ mAlarmManager.cancel(mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED));
+ } else {
+ loge("cancelAnyPendingSwitch: EVENT_STABILITY_CHECK_PASSED listener is null");
}
- } else {
removeMessages(EVENT_STABILITY_CHECK_PASSED);
+ mScheduledEventsToExtras.remove(EVENT_STABILITY_CHECK_PASSED);
}
mPhoneSwitcherCallback.onRequireCancelAnyPendingAutoSwitchValidation();
}
@@ -1085,8 +1085,9 @@
* @param isDueToAutoSwitch {@code true} if the switch was due to auto data switch feature.
*/
public void displayAutoDataSwitchNotification(int phoneId, boolean isDueToAutoSwitch) {
- NotificationManager notificationManager = (NotificationManager)
- mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ NotificationManager notificationManager = mContext.getSystemService(
+ NotificationManager.class);
+ if (notificationManager == null) return;
if (mDisplayedNotification) {
// cancel posted notification if any exist
notificationManager.cancel(AUTO_DATA_SWITCH_NOTIFICATION_TAG,
diff --git a/src/java/com/android/internal/telephony/data/CellularDataService.java b/src/java/com/android/internal/telephony/data/CellularDataService.java
index 80d6b53..a75d4df 100644
--- a/src/java/com/android/internal/telephony/data/CellularDataService.java
+++ b/src/java/com/android/internal/telephony/data/CellularDataService.java
@@ -18,6 +18,7 @@
import static android.telephony.data.DataServiceCallback.RESULT_SUCCESS;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.LinkProperties;
import android.os.AsyncResult;
@@ -41,6 +42,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* This class represents cellular data service which handles telephony data requests and response
@@ -61,6 +63,7 @@
private static final int CANCEL_HANDOVER = 8;
private static final int APN_UNTHROTTLED = 9;
+ @SuppressWarnings("unchecked")
private class CellularDataServiceProvider extends DataService.DataServiceProvider {
private final Map<Message, DataServiceCallback> mCallbackMap = new HashMap<>();
@@ -69,14 +72,15 @@
private final Phone mPhone;
+ @SuppressWarnings("unchecked")
private CellularDataServiceProvider(int slotId) {
super(slotId);
mPhone = PhoneFactory.getPhone(getSlotIndex());
- mHandler = new Handler(Looper.myLooper()) {
+ mHandler = new Handler(Objects.requireNonNull(Looper.myLooper())) {
@Override
- public void handleMessage(Message message) {
+ public void handleMessage(@NonNull Message message) {
DataServiceCallback callback = mCallbackMap.remove(message);
AsyncResult ar = (AsyncResult) message.obj;
@@ -147,8 +151,7 @@
if (t == null) {
return RESULT_SUCCESS;
} else {
- if (t instanceof CommandException) {
- CommandException ce = (CommandException) t;
+ if (t instanceof CommandException ce) {
if (ce.getCommandError() == CommandException.Error.REQUEST_NOT_SUPPORTED) {
return DataServiceCallback.RESULT_ERROR_UNSUPPORTED;
} else {
@@ -163,10 +166,10 @@
}
@Override
- public void setupDataCall(int accessNetworkType, DataProfile dataProfile,
+ public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties,
int pduSessionId, NetworkSliceInfo sliceInfo, TrafficDescriptor trafficDescriptor,
- boolean matchAllRuleAllowed, DataServiceCallback callback) {
+ boolean matchAllRuleAllowed, @Nullable DataServiceCallback callback) {
// TODO: remove isRoaming parameter
if (DBG) log("setupDataCall " + getSlotIndex());
@@ -199,8 +202,8 @@
}
@Override
- public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming,
- DataServiceCallback callback) {
+ public void setInitialAttachApn(@NonNull DataProfile dataProfile, boolean isRoaming,
+ @Nullable DataServiceCallback callback) {
// TODO: remove isRoaming parameter
if (DBG) log("setInitialAttachApn " + getSlotIndex());
@@ -216,8 +219,8 @@
}
@Override
- public void setDataProfile(List<DataProfile> dps, boolean isRoaming,
- DataServiceCallback callback) {
+ public void setDataProfile(@NonNull List<DataProfile> dps, boolean isRoaming,
+ @Nullable DataServiceCallback callback) {
// TODO: remove isRoaming parameter
if (DBG) log("setDataProfile " + getSlotIndex());
@@ -229,11 +232,11 @@
mCallbackMap.put(message, callback);
}
- mPhone.mCi.setDataProfile(dps.toArray(new DataProfile[dps.size()]), message);
+ mPhone.mCi.setDataProfile(dps.toArray(new DataProfile[0]), message);
}
@Override
- public void requestDataCallList(DataServiceCallback callback) {
+ public void requestDataCallList(@Nullable DataServiceCallback callback) {
if (DBG) log("requestDataCallList " + getSlotIndex());
Message message = null;
@@ -247,7 +250,7 @@
}
@Override
- public void startHandover(int cid, DataServiceCallback callback) {
+ public void startHandover(int cid, @Nullable DataServiceCallback callback) {
if (DBG) log("startHandover " + getSlotIndex());
Message message = null;
// Only obtain the message when the caller wants a callback. If the caller doesn't care
@@ -260,7 +263,7 @@
}
@Override
- public void cancelHandover(int cid, DataServiceCallback callback) {
+ public void cancelHandover(int cid, @Nullable DataServiceCallback callback) {
Message message = null;
// Only obtain the message when the caller wants a callback. If the caller doesn't care
// the request completed or results, then no need to pass the message down.
diff --git a/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java b/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
index c1d1203..ad1a8aa 100644
--- a/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
+++ b/src/java/com/android/internal/telephony/data/CellularNetworkValidator.java
@@ -20,6 +20,7 @@
import static android.telephony.CarrierConfigManager.KEY_DATA_SWITCH_VALIDATION_MIN_INTERVAL_MILLIS_LONG;
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
+import android.annotation.NonNull;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
@@ -58,9 +59,6 @@
*/
public class CellularNetworkValidator {
private static final String LOG_TAG = "NetworkValidator";
- // If true, upon validated network cache hit, we report validationDone only when
- // network becomes available. Otherwise, we report validationDone immediately.
- private static boolean sWaitForNetworkAvailableWhenCacheHit = true;
// States of validator. Only one validation can happen at once.
// IDLE: no validation going on.
@@ -69,7 +67,7 @@
private static final int STATE_VALIDATING = 1;
// VALIDATED: validation is done and successful.
// Waiting for stopValidation() to release
- // validationg NetworkRequest.
+ // validation NetworkRequest.
private static final int STATE_VALIDATED = 2;
// Singleton instance.
@@ -79,13 +77,11 @@
private int mState = STATE_IDLE;
private int mSubId;
- private long mTimeoutInMs;
private boolean mReleaseAfterValidation;
- private NetworkRequest mNetworkRequest;
private ValidationCallback mValidationCallback;
- private Context mContext;
- private ConnectivityManager mConnectivityManager;
+ private final Context mContext;
+ private final ConnectivityManager mConnectivityManager;
@VisibleForTesting
public Handler mHandler = new Handler();
@VisibleForTesting
@@ -96,18 +92,11 @@
// A cache with fixed size. It remembers 10 most recently successfully validated networks.
private static final int VALIDATED_NETWORK_CACHE_SIZE = 10;
private final PriorityQueue<ValidatedNetwork> mValidatedNetworkPQ =
- new PriorityQueue((Comparator<ValidatedNetwork>) (n1, n2) -> {
- if (n1.mValidationTimeStamp < n2.mValidationTimeStamp) {
- return -1;
- } else if (n1.mValidationTimeStamp > n2.mValidationTimeStamp) {
- return 1;
- } else {
- return 0;
- }
- });
- private final Map<String, ValidatedNetwork> mValidatedNetworkMap = new HashMap();
+ new PriorityQueue<>((Comparator<ValidatedNetwork>) Comparator.comparingLong(
+ (ValidatedNetwork n) -> n.mValidationTimeStamp));
+ private final Map<String, ValidatedNetwork> mValidatedNetworkMap = new HashMap<>();
- private final class ValidatedNetwork {
+ private static final class ValidatedNetwork {
ValidatedNetwork(String identity, long timeStamp) {
mValidationIdentity = identity;
mValidationTimeStamp = timeStamp;
@@ -165,7 +154,6 @@
private String getValidationNetworkIdentity(int subId) {
if (!SubscriptionManager.isUsableSubscriptionId(subId)) return null;
- if (SubscriptionManagerService.getInstance() == null) return null;
Phone phone = PhoneFactory.getPhone(SubscriptionManagerService.getInstance()
.getPhoneId(subId));
if (phone == null || phone.getServiceState() == null) return null;
@@ -270,26 +258,18 @@
stopValidation();
}
- if (!sWaitForNetworkAvailableWhenCacheHit && mValidatedNetworkCache
- .isRecentlyValidated(subId)) {
- callback.onValidationDone(true, subId);
- return;
- }
-
mState = STATE_VALIDATING;
mSubId = subId;
- mTimeoutInMs = timeoutInMs;
mValidationCallback = callback;
mReleaseAfterValidation = releaseAfterValidation;
- mNetworkRequest = createNetworkRequest();
- logd("Start validating subId " + mSubId + " mTimeoutInMs " + mTimeoutInMs
+ logd("Start validating subId " + mSubId + " timeoutInMs " + timeoutInMs
+ " mReleaseAfterValidation " + mReleaseAfterValidation);
mNetworkCallback = new ConnectivityNetworkCallback(subId);
- mConnectivityManager.requestNetwork(mNetworkRequest, mNetworkCallback, mHandler);
- mHandler.postDelayed(() -> onValidationTimeout(subId), mTimeoutInMs);
+ mConnectivityManager.requestNetwork(createNetworkRequest(), mNetworkCallback, mHandler);
+ mHandler.postDelayed(() -> onValidationTimeout(subId), timeoutInMs);
}
private synchronized void onValidationTimeout(int subId) {
@@ -351,7 +331,7 @@
mState = STATE_VALIDATED;
// If validation passed and per request to NOT release after validation, delay cleanup.
if (!mReleaseAfterValidation && passed) {
- mHandler.postDelayed(()-> stopValidation(), 500);
+ mHandler.postDelayed(this::stopValidation, 500);
} else {
stopValidation();
}
@@ -379,7 +359,7 @@
* ConnectivityManager.NetworkCallback implementation
*/
@Override
- public void onAvailable(Network network) {
+ public void onAvailable(@NonNull Network network) {
logd("network onAvailable " + network);
TelephonyMetrics.getInstance().writeNetworkValidate(
TelephonyEvent.NetworkValidationState.NETWORK_VALIDATION_STATE_AVAILABLE);
@@ -393,7 +373,7 @@
}
@Override
- public void onLosing(Network network, int maxMsToLive) {
+ public void onLosing(@NonNull Network network, int maxMsToLive) {
logd("network onLosing " + network + " maxMsToLive " + maxMsToLive);
mValidatedNetworkCache.storeLastValidationResult(
ConnectivityNetworkCallback.this.mSubId, false);
@@ -401,7 +381,7 @@
}
@Override
- public void onLost(Network network) {
+ public void onLost(@NonNull Network network) {
logd("network onLost " + network);
mValidatedNetworkCache.storeLastValidationResult(
ConnectivityNetworkCallback.this.mSubId, false);
@@ -417,7 +397,7 @@
}
@Override
- public void onCapabilitiesChanged(Network network,
+ public void onCapabilitiesChanged(@NonNull Network network,
NetworkCapabilities networkCapabilities) {
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
logd("onValidated");
diff --git a/src/java/com/android/internal/telephony/data/DataCallback.java b/src/java/com/android/internal/telephony/data/DataCallback.java
index 1fafe8c..05d1851 100644
--- a/src/java/com/android/internal/telephony/data/DataCallback.java
+++ b/src/java/com/android/internal/telephony/data/DataCallback.java
@@ -28,7 +28,8 @@
*/
public class DataCallback {
/** The executor of the callback. */
- private final @NonNull Executor mExecutor;
+ @NonNull
+ private final Executor mExecutor;
/**
* Constructor
@@ -43,7 +44,8 @@
* @return The executor of the callback.
*/
@VisibleForTesting
- public @NonNull Executor getExecutor() {
+ @NonNull
+ public Executor getExecutor() {
return mExecutor;
}
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index 0e06dad..20761e2 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -64,6 +64,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -163,6 +164,13 @@
/** Network type NR_SA_MMWAVE. Should not be used outside of DataConfigManager. */
private static final String DATA_CONFIG_NETWORK_TYPE_NR_SA_MMWAVE = "NR_SA_MMWAVE";
+ /**
+ * The delay in milliseconds to re-evaluate existing data networks for bootstrap sim data usage
+ * limit.
+ */
+ private static final long REEVALUATE_BOOTSTRAP_SIM_DATA_USAGE_MILLIS =
+ TimeUnit.SECONDS.toMillis(60);
+
@StringDef(prefix = {"DATA_CONFIG_NETWORK_TYPE_"}, value = {
DATA_CONFIG_NETWORK_TYPE_GPRS,
DATA_CONFIG_NETWORK_TYPE_EDGE,
@@ -192,8 +200,8 @@
private @interface DataConfigNetworkType {}
/** Data config update callbacks. */
- private final @NonNull Set<DataConfigManagerCallback> mDataConfigManagerCallbacks =
- new ArraySet<>();
+ @NonNull
+ private final Set<DataConfigManagerCallback> mDataConfigManagerCallbacks = new ArraySet<>();
/** DeviceConfig key of anomaly report threshold for back to back ims release-request. */
private static final String KEY_ANOMALY_IMS_RELEASE_REQUEST = "anomaly_ims_release_request";
@@ -258,55 +266,77 @@
*/
private boolean mIsApnConfigAnomalyReportEnabled;
- private @NonNull final Phone mPhone;
- private @NonNull final String mLogTag;
-
- @NonNull private final FeatureFlags mFeatureFlags;
- private @NonNull final CarrierConfigManager mCarrierConfigManager;
- private @NonNull PersistableBundle mCarrierConfig = null;
- private @NonNull Resources mResources = null;
+ @NonNull
+ private final Phone mPhone;
+ @NonNull
+ private final String mLogTag;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
+ @NonNull
+ private final CarrierConfigManager mCarrierConfigManager;
+ @NonNull
+ private PersistableBundle mCarrierConfig = null;
+ @NonNull
+ private Resources mResources = null;
/** The network capability priority map */
- private @NonNull final Map<Integer, Integer> mNetworkCapabilityPriorityMap =
- new ConcurrentHashMap<>();
+ @NonNull
+ private final Map<Integer, Integer> mNetworkCapabilityPriorityMap = new ConcurrentHashMap<>();
/** The data setup retry rules */
- private @NonNull final List<DataSetupRetryRule> mDataSetupRetryRules = new ArrayList<>();
+ @NonNull
+ private final List<DataSetupRetryRule> mDataSetupRetryRules = new ArrayList<>();
/** The data handover retry rules */
- private @NonNull final List<DataHandoverRetryRule> mDataHandoverRetryRules = new ArrayList<>();
+ @NonNull
+ private final List<DataHandoverRetryRule> mDataHandoverRetryRules = new ArrayList<>();
/** The metered APN types for home network */
- private @NonNull final @ApnType Set<Integer> mMeteredApnTypes = new HashSet<>();
+ @NonNull
+ @ApnType
+ private final Set<Integer> mMeteredApnTypes = new HashSet<>();
/** The metered APN types for roaming network */
- private @NonNull final @ApnType Set<Integer> mRoamingMeteredApnTypes = new HashSet<>();
+ @NonNull
+ @ApnType
+ private final Set<Integer> mRoamingMeteredApnTypes = new HashSet<>();
/** The network types that only support single data networks */
- private @NonNull final @NetworkType List<Integer> mSingleDataNetworkTypeList =
- new ArrayList<>();
- private @NonNull final @NetCapability Set<Integer> mCapabilitiesExemptFromSingleDataList =
- new HashSet<>();
+ @NonNull
+ @NetworkType
+ private final List<Integer> mSingleDataNetworkTypeList = new ArrayList<>();
+ @NonNull
+ @NetCapability
+ private final Set<Integer> mCapabilitiesExemptFromSingleDataList = new HashSet<>();
/** The network types that support temporarily not metered */
- private @NonNull final @DataConfigNetworkType Set<String> mUnmeteredNetworkTypes =
- new HashSet<>();
+ @NonNull
+ @DataConfigNetworkType
+ private final Set<String> mUnmeteredNetworkTypes = new HashSet<>();
/** The network types that support temporarily not metered when roaming */
- private @NonNull final @DataConfigNetworkType Set<String> mRoamingUnmeteredNetworkTypes =
- new HashSet<>();
+ @NonNull
+ @DataConfigNetworkType
+ private final Set<String> mRoamingUnmeteredNetworkTypes = new HashSet<>();
/** A map of network types to the downlink and uplink bandwidth values for that network type */
- private @NonNull final @DataConfigNetworkType Map<String, DataNetwork.NetworkBandwidth>
- mBandwidthMap = new ConcurrentHashMap<>();
- /** A map of network types to the TCP buffer sizes for that network type */
- private @NonNull final @DataConfigNetworkType Map<String, String> mTcpBufferSizeMap =
+ @NonNull
+ @DataConfigNetworkType
+ private final Map<String, DataNetwork.NetworkBandwidth> mBandwidthMap =
new ConcurrentHashMap<>();
+ /** A map of network types to the TCP buffer sizes for that network type */
+ @NonNull
+ @DataConfigNetworkType
+ private final Map<String, String> mTcpBufferSizeMap = new ConcurrentHashMap<>();
/** Rules for handover between IWLAN and cellular network. */
- private @NonNull final List<HandoverRule> mHandoverRuleList = new ArrayList<>();
+ @NonNull
+ private final List<HandoverRule> mHandoverRuleList = new ArrayList<>();
/** {@code True} keep IMS network in case of moving to non VOPS area; {@code false} otherwise.*/
private boolean mShouldKeepNetworkUpInNonVops = false;
/** The set of network types that enable VOPS even in non VOPS area. */
- @NonNull private final @CarrierConfigManager.Ims.NetworkType List<Integer>
- mEnabledVopsNetworkTypesInNonVops = new ArrayList<>();
+ @NonNull
+ @CarrierConfigManager.Ims.NetworkType
+ private final List<Integer> mEnabledVopsNetworkTypesInNonVops = new ArrayList<>();
/**
* A map of network types to the estimated downlink values by signal strength 0 - 4 for that
* network type
*/
- private @NonNull final @DataConfigNetworkType Map<String, int[]>
- mAutoDataSwitchNetworkTypeSignalMap = new ConcurrentHashMap<>();
+ @NonNull
+ @DataConfigNetworkType
+ private final Map<String, int[]> mAutoDataSwitchNetworkTypeSignalMap =
+ new ConcurrentHashMap<>();
/**
* Constructor
@@ -546,14 +576,16 @@
/**
* @return The data setup retry rules from carrier config.
*/
- public @NonNull List<DataSetupRetryRule> getDataSetupRetryRules() {
+ @NonNull
+ public List<DataSetupRetryRule> getDataSetupRetryRules() {
return Collections.unmodifiableList(mDataSetupRetryRules);
}
/**
* @return The data handover retry rules from carrier config.
*/
- public @NonNull List<DataHandoverRetryRule> getDataHandoverRetryRules() {
+ @NonNull
+ public List<DataHandoverRetryRule> getDataHandoverRetryRules() {
return Collections.unmodifiableList(mDataHandoverRetryRules);
}
@@ -596,7 +628,9 @@
*
* @return The metered network capabilities when connected to a home network.
*/
- public @NonNull @NetCapability Set<Integer> getMeteredNetworkCapabilities(boolean isRoaming) {
+ @NonNull
+ @NetCapability
+ public Set<Integer> getMeteredNetworkCapabilities(boolean isRoaming) {
Set<Integer> meteredApnTypes = isRoaming ? mRoamingMeteredApnTypes : mMeteredApnTypes;
Set<Integer> meteredCapabilities = meteredApnTypes.stream()
.map(DataUtils::apnTypeToNetworkCapability)
@@ -680,8 +714,7 @@
/**
* Update the voice over PS related config from the carrier config.
*/
- private void updateVopsConfig() {
- synchronized (this) {
+ private synchronized void updateVopsConfig() {
mShouldKeepNetworkUpInNonVops = mCarrierConfig.getBoolean(CarrierConfigManager
.Ims.KEY_KEEP_PDN_UP_IN_NO_VOPS_BOOL);
int[] allowedNetworkTypes = mCarrierConfig.getIntArray(
@@ -689,13 +722,14 @@
if (allowedNetworkTypes != null) {
Arrays.stream(allowedNetworkTypes).forEach(mEnabledVopsNetworkTypesInNonVops::add);
}
- }
}
/**
* @return The list of {@link NetworkType} that only supports single data networks
*/
- public @NonNull @NetworkType List<Integer> getNetworkTypesOnlySupportSingleDataNetwork() {
+ @NonNull
+ @NetworkType
+ public List<Integer> getNetworkTypesOnlySupportSingleDataNetwork() {
return Collections.unmodifiableList(mSingleDataNetworkTypeList);
}
@@ -703,7 +737,9 @@
* @return The list of {@link android.net.NetworkCapabilities.NetCapability} that every of which
* is exempt from the single PDN check.
*/
- public @NonNull @NetCapability Set<Integer> getCapabilitiesExemptFromSingleDataNetwork() {
+ @NonNull
+ @NetCapability
+ public Set<Integer> getCapabilitiesExemptFromSingleDataNetwork() {
return Collections.unmodifiableSet(mCapabilitiesExemptFromSingleDataList);
}
@@ -836,7 +872,8 @@
* @param displayInfo The {@link TelephonyDisplayInfo} to get the bandwidth for.
* @return The pre-configured bandwidth estimate from carrier config.
*/
- public @NonNull DataNetwork.NetworkBandwidth getBandwidthForNetworkType(
+ @NonNull
+ public DataNetwork.NetworkBandwidth getBandwidthForNetworkType(
@NonNull TelephonyDisplayInfo displayInfo) {
DataNetwork.NetworkBandwidth bandwidth = mBandwidthMap.get(
getDataConfigNetworkType(displayInfo));
@@ -847,6 +884,14 @@
}
/**
+ * @return What kind of traffic is supported on an unrestricted satellite network.
+ */
+ @CarrierConfigManager.SATELLITE_DATA_SUPPORT_MODE
+ public int getSatelliteDataSupportMode() {
+ return mCarrierConfig.getInt(CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT);
+ }
+
+ /**
* @return Whether data throttling should be reset when the TAC changes from the carrier config.
*/
public boolean shouldResetDataThrottlingWhenTacChanges() {
@@ -878,6 +923,21 @@
}
/**
+ * @return the interval in millisecond used to re-evaluate bootstrap sim data usage during esim
+ * bootstrap activation
+ */
+ public long getReevaluateBootstrapSimDataUsageMillis() {
+ long bootStrapSimDataUsageReevaluateInterval = mResources.getInteger(
+ com.android.internal.R.integer.config_reevaluate_bootstrap_sim_data_usage_millis);
+
+ if (bootStrapSimDataUsageReevaluateInterval <= 0) {
+ bootStrapSimDataUsageReevaluateInterval = REEVALUATE_BOOTSTRAP_SIM_DATA_USAGE_MILLIS;
+ }
+
+ return bootStrapSimDataUsageReevaluateInterval;
+ }
+
+ /**
* Update the TCP buffer sizes from the resource overlays.
*/
private void updateTcpBuffers() {
@@ -908,7 +968,8 @@
* Anomaly report thresholds for frequent setup data call failure.
* @return EventFrequency to trigger the anomaly report
*/
- public @NonNull EventFrequency getAnomalySetupDataCallThreshold() {
+ @NonNull
+ public EventFrequency getAnomalySetupDataCallThreshold() {
return mSetupDataCallAnomalyReportThreshold;
}
@@ -917,7 +978,8 @@
* at {@link TelephonyNetworkAgent#onNetworkUnwanted}
* @return EventFrequency to trigger the anomaly report
*/
- public @NonNull EventFrequency getAnomalyNetworkUnwantedThreshold() {
+ @NonNull
+ public EventFrequency getAnomalyNetworkUnwantedThreshold() {
return mNetworkUnwantedAnomalyReportThreshold;
}
@@ -925,7 +987,8 @@
* Anomaly report thresholds for back to back release-request of IMS.
* @return EventFrequency to trigger the anomaly report
*/
- public @NonNull EventFrequency getAnomalyImsReleaseRequestThreshold() {
+ @NonNull
+ public EventFrequency getAnomalyImsReleaseRequestThreshold() {
return mImsReleaseRequestAnomalyReportThreshold;
}
@@ -1096,7 +1159,8 @@
* @return The TCP configuration string for the given display info or the default value from
* {@code config_tcp_buffers} if unavailable.
*/
- public @NonNull String getTcpConfigString(@NonNull TelephonyDisplayInfo displayInfo) {
+ @NonNull
+ public String getTcpConfigString(@NonNull TelephonyDisplayInfo displayInfo) {
String config = mTcpBufferSizeMap.get(getDataConfigNetworkType(displayInfo));
if (TextUtils.isEmpty(config)) {
config = getDefaultTcpConfigString();
@@ -1107,7 +1171,8 @@
/**
* @return The fixed TCP buffer size configured based on the device's memory and performance.
*/
- public @NonNull String getDefaultTcpConfigString() {
+ @NonNull
+ public String getDefaultTcpConfigString() {
return mResources.getString(com.android.internal.R.string.config_tcp_buffers);
}
@@ -1150,20 +1215,21 @@
/**
* @return The bandwidth estimation source.
*/
- public @DataNetwork.BandwidthEstimationSource int getBandwidthEstimateSource() {
+ @DataNetwork.BandwidthEstimationSource
+ public int getBandwidthEstimateSource() {
String source = mResources.getString(
com.android.internal.R.string.config_bandwidthEstimateSource);
- switch (source) {
- case BANDWIDTH_SOURCE_MODEM_STRING_VALUE:
- return DataNetwork.BANDWIDTH_SOURCE_MODEM;
- case BANDWIDTH_SOURCE_CARRIER_CONFIG_STRING_VALUE:
- return DataNetwork.BANDWIDTH_SOURCE_CARRIER_CONFIG;
- case BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_STRING_VALUE:
- return DataNetwork.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR;
- default:
+ return switch (source) {
+ case BANDWIDTH_SOURCE_MODEM_STRING_VALUE -> DataNetwork.BANDWIDTH_SOURCE_MODEM;
+ case BANDWIDTH_SOURCE_CARRIER_CONFIG_STRING_VALUE ->
+ DataNetwork.BANDWIDTH_SOURCE_CARRIER_CONFIG;
+ case BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR_STRING_VALUE ->
+ DataNetwork.BANDWIDTH_SOURCE_BANDWIDTH_ESTIMATOR;
+ default -> {
loge("Invalid bandwidth estimation source config: " + source);
- return DataNetwork.BANDWIDTH_SOURCE_UNKNOWN;
- }
+ yield DataNetwork.BANDWIDTH_SOURCE_UNKNOWN;
+ }
+ };
}
/**
@@ -1172,8 +1238,9 @@
* @param displayInfo The {@link TelephonyDisplayInfo} used to determine the type.
* @return The equivalent {@link DataConfigNetworkType}.
*/
- private static @NonNull @DataConfigNetworkType String getDataConfigNetworkType(
- @NonNull TelephonyDisplayInfo displayInfo) {
+ @NonNull
+ @DataConfigNetworkType
+ private static String getDataConfigNetworkType(@NonNull TelephonyDisplayInfo displayInfo) {
int networkType = displayInfo.getNetworkType();
switch (displayInfo.getOverrideNetworkType()) {
case TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED:
@@ -1282,7 +1349,8 @@
*
* @see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY
*/
- public @NonNull List<HandoverRule> getHandoverRules() {
+ @NonNull
+ public List<HandoverRule> getHandoverRules() {
return Collections.unmodifiableList(mHandoverRuleList);
}
@@ -1300,52 +1368,33 @@
* @param networkType The network type
* @return The equivalent data config network type
*/
- private static @NonNull @DataConfigNetworkType String networkTypeToDataConfigNetworkType(
+ @NonNull
+ @DataConfigNetworkType
+ private static String networkTypeToDataConfigNetworkType(
@NetworkType int networkType) {
- switch (networkType) {
- case TelephonyManager.NETWORK_TYPE_GPRS:
- return DATA_CONFIG_NETWORK_TYPE_GPRS;
- case TelephonyManager.NETWORK_TYPE_EDGE:
- return DATA_CONFIG_NETWORK_TYPE_EDGE;
- case TelephonyManager.NETWORK_TYPE_UMTS:
- return DATA_CONFIG_NETWORK_TYPE_UMTS;
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- return DATA_CONFIG_NETWORK_TYPE_HSDPA;
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- return DATA_CONFIG_NETWORK_TYPE_HSUPA;
- case TelephonyManager.NETWORK_TYPE_HSPA:
- return DATA_CONFIG_NETWORK_TYPE_HSPA;
- case TelephonyManager.NETWORK_TYPE_CDMA:
- return DATA_CONFIG_NETWORK_TYPE_CDMA;
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- return DATA_CONFIG_NETWORK_TYPE_EVDO_0;
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- return DATA_CONFIG_NETWORK_TYPE_EVDO_A;
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- return DATA_CONFIG_NETWORK_TYPE_EVDO_B;
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- return DATA_CONFIG_NETWORK_TYPE_1xRTT;
- case TelephonyManager.NETWORK_TYPE_LTE:
- return DATA_CONFIG_NETWORK_TYPE_LTE;
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- return DATA_CONFIG_NETWORK_TYPE_EHRPD;
- case TelephonyManager.NETWORK_TYPE_IDEN:
- return DATA_CONFIG_NETWORK_TYPE_IDEN;
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- return DATA_CONFIG_NETWORK_TYPE_HSPAP;
- case TelephonyManager.NETWORK_TYPE_GSM:
- return DATA_CONFIG_NETWORK_TYPE_GSM;
- case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
- return DATA_CONFIG_NETWORK_TYPE_TD_SCDMA;
- case TelephonyManager.NETWORK_TYPE_IWLAN:
- return DATA_CONFIG_NETWORK_TYPE_IWLAN;
- case TelephonyManager.NETWORK_TYPE_LTE_CA:
- return DATA_CONFIG_NETWORK_TYPE_LTE_CA;
- case TelephonyManager.NETWORK_TYPE_NR:
- return DATA_CONFIG_NETWORK_TYPE_NR_SA;
- default:
- return "";
- }
+ return switch (networkType) {
+ case TelephonyManager.NETWORK_TYPE_GPRS -> DATA_CONFIG_NETWORK_TYPE_GPRS;
+ case TelephonyManager.NETWORK_TYPE_EDGE -> DATA_CONFIG_NETWORK_TYPE_EDGE;
+ case TelephonyManager.NETWORK_TYPE_UMTS -> DATA_CONFIG_NETWORK_TYPE_UMTS;
+ case TelephonyManager.NETWORK_TYPE_HSDPA -> DATA_CONFIG_NETWORK_TYPE_HSDPA;
+ case TelephonyManager.NETWORK_TYPE_HSUPA -> DATA_CONFIG_NETWORK_TYPE_HSUPA;
+ case TelephonyManager.NETWORK_TYPE_HSPA -> DATA_CONFIG_NETWORK_TYPE_HSPA;
+ case TelephonyManager.NETWORK_TYPE_CDMA -> DATA_CONFIG_NETWORK_TYPE_CDMA;
+ case TelephonyManager.NETWORK_TYPE_EVDO_0 -> DATA_CONFIG_NETWORK_TYPE_EVDO_0;
+ case TelephonyManager.NETWORK_TYPE_EVDO_A -> DATA_CONFIG_NETWORK_TYPE_EVDO_A;
+ case TelephonyManager.NETWORK_TYPE_EVDO_B -> DATA_CONFIG_NETWORK_TYPE_EVDO_B;
+ case TelephonyManager.NETWORK_TYPE_1xRTT -> DATA_CONFIG_NETWORK_TYPE_1xRTT;
+ case TelephonyManager.NETWORK_TYPE_LTE -> DATA_CONFIG_NETWORK_TYPE_LTE;
+ case TelephonyManager.NETWORK_TYPE_EHRPD -> DATA_CONFIG_NETWORK_TYPE_EHRPD;
+ case TelephonyManager.NETWORK_TYPE_IDEN -> DATA_CONFIG_NETWORK_TYPE_IDEN;
+ case TelephonyManager.NETWORK_TYPE_HSPAP -> DATA_CONFIG_NETWORK_TYPE_HSPAP;
+ case TelephonyManager.NETWORK_TYPE_GSM -> DATA_CONFIG_NETWORK_TYPE_GSM;
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA -> DATA_CONFIG_NETWORK_TYPE_TD_SCDMA;
+ case TelephonyManager.NETWORK_TYPE_IWLAN -> DATA_CONFIG_NETWORK_TYPE_IWLAN;
+ case TelephonyManager.NETWORK_TYPE_LTE_CA -> DATA_CONFIG_NETWORK_TYPE_LTE_CA;
+ case TelephonyManager.NETWORK_TYPE_NR -> DATA_CONFIG_NETWORK_TYPE_NR_SA;
+ default -> "";
+ };
}
/**
@@ -1353,7 +1402,8 @@
*
* @see CarrierConfigManager#KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY
*/
- public @NonNull long[] getDataStallRecoveryDelayMillis() {
+ @NonNull
+ public long[] getDataStallRecoveryDelayMillis() {
return mCarrierConfig.getLongArray(
CarrierConfigManager.KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY);
}
@@ -1363,7 +1413,8 @@
*
* @see CarrierConfigManager#KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY
*/
- public @NonNull boolean[] getDataStallRecoveryShouldSkipArray() {
+ @NonNull
+ public boolean[] getDataStallRecoveryShouldSkipArray() {
return mCarrierConfig.getBooleanArray(
CarrierConfigManager.KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY);
}
@@ -1372,7 +1423,8 @@
* @return The default preferred APN. An empty string if not configured. This is used for the
* first time boot up where preferred APN is not set.
*/
- public @NonNull String getDefaultPreferredApn() {
+ @NonNull
+ public String getDefaultPreferredApn() {
return TextUtils.emptyIfNull(mCarrierConfig.getString(
CarrierConfigManager.KEY_DEFAULT_PREFERRED_APN_NAME_STRING));
}
@@ -1391,7 +1443,9 @@
* cases that we need to use "user-added" APN for initial attach. The regular way to configure
* IA APN is by adding "IA" type to the APN in APN config.
*/
- public @NonNull @ApnType List<Integer> getAllowedInitialAttachApnTypes() {
+ @NonNull
+ @ApnType
+ public List<Integer> getAllowedInitialAttachApnTypes() {
String[] apnTypesArray = mCarrierConfig.getStringArray(
CarrierConfigManager.KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY);
if (apnTypesArray != null) {
@@ -1436,6 +1490,19 @@
}
/**
+ * @return The capabilities that network will be forced to mark as cellular transport.
+ */
+ @NetCapability
+ public Set<Integer> getForcedCellularTransportCapabilities() {
+ String[] forcedCellularTransportCapabilities = mResources.getStringArray(
+ com.android.internal.R.array.config_force_cellular_transport_capabilities);
+
+ return Arrays.stream(forcedCellularTransportCapabilities)
+ .map(DataUtils::getNetworkCapabilityFromString)
+ .collect(Collectors.toSet());
+ }
+
+ /**
* Log debug messages.
* @param s debug messages
*/
@@ -1543,6 +1610,9 @@
pw.println("isTetheringProfileDisabledForRoaming="
+ isTetheringProfileDisabledForRoaming());
pw.println("allowClearInitialAttachDataProfile=" + allowClearInitialAttachDataProfile());
+ pw.println("forcedCellularTransportCapabilities=" + getForcedCellularTransportCapabilities()
+ .stream().map(DataUtils::networkCapabilityToString)
+ .collect(Collectors.joining(",")));
pw.decreaseIndent();
}
}
diff --git a/src/java/com/android/internal/telephony/data/DataEvaluation.java b/src/java/com/android/internal/telephony/data/DataEvaluation.java
index 3d10e9c..f5eae91 100644
--- a/src/java/com/android/internal/telephony/data/DataEvaluation.java
+++ b/src/java/com/android/internal/telephony/data/DataEvaluation.java
@@ -36,25 +36,30 @@
*/
public class DataEvaluation {
/** The reason for this evaluation */
- private final @NonNull DataEvaluationReason mDataEvaluationReason;
+ @NonNull
+ private final DataEvaluationReason mDataEvaluationReason;
/** Data disallowed reasons. There could be multiple reasons for not allowing data. */
- private final @NonNull Set<DataDisallowedReason> mDataDisallowedReasons = new HashSet<>();
+ @NonNull
+ private final Set<DataDisallowedReason> mDataDisallowedReasons = new HashSet<>();
/** Data allowed reason. It is intended to only have one allowed reason. */
- private @NonNull DataAllowedReason mDataAllowedReason = DataAllowedReason.NONE;
+ @NonNull
+ private DataAllowedReason mDataAllowedReason = DataAllowedReason.NONE;
- private @Nullable DataProfile mCandidateDataProfile = null;
+ @Nullable
+ private DataProfile mCandidateDataProfile = null;
/** The timestamp of evaluation time */
- private @CurrentTimeMillisLong long mEvaluatedTime = 0;
+ @CurrentTimeMillisLong
+ private long mEvaluatedTime = 0;
/**
* Constructor
*
* @param reason The reason for this evaluation.
*/
- public DataEvaluation(DataEvaluationReason reason) {
+ public DataEvaluation(@NonNull DataEvaluationReason reason) {
mDataEvaluationReason = reason;
}
@@ -100,14 +105,16 @@
/**
* @return List of data disallowed reasons.
*/
- public @NonNull List<DataDisallowedReason> getDataDisallowedReasons() {
+ @NonNull
+ public List<DataDisallowedReason> getDataDisallowedReasons() {
return new ArrayList<>(mDataDisallowedReasons);
}
/**
* @return The data allowed reason.
*/
- public @NonNull DataAllowedReason getDataAllowedReason() {
+ @NonNull
+ public DataAllowedReason getDataAllowedReason() {
return mDataAllowedReason;
}
@@ -123,7 +130,8 @@
/**
* @return The candidate data profile for setup data network.
*/
- public @Nullable DataProfile getCandidateDataProfile() {
+ @Nullable
+ public DataProfile getCandidateDataProfile() {
return mCandidateDataProfile;
}
@@ -131,7 +139,7 @@
* @return {@code true} if the evaluation contains disallowed reasons.
*/
public boolean containsDisallowedReasons() {
- return mDataDisallowedReasons.size() != 0;
+ return !mDataDisallowedReasons.isEmpty();
}
/**
@@ -346,7 +354,9 @@
/** Handover max retry stopped but network is not on the preferred transport. */
HANDOVER_RETRY_STOPPED(true),
/** BootStrap sim data limit reached. */
- DATA_LIMIT_REACHED(true);
+ DATA_LIMIT_REACHED(true),
+ /** Data network connectivity transport not allowed. */
+ DATA_NETWORK_TRANSPORT_NOT_ALLOWED(true);
private final boolean mIsHardReason;
@@ -415,8 +425,9 @@
@Override
public String toString() {
StringBuilder evaluationStr = new StringBuilder();
- evaluationStr.append("Data evaluation: evaluation reason:" + mDataEvaluationReason + ", ");
- if (mDataDisallowedReasons.size() > 0) {
+ evaluationStr.append("Data evaluation: evaluation reason:")
+ .append(mDataEvaluationReason).append(", ");
+ if (!mDataDisallowedReasons.isEmpty()) {
evaluationStr.append("Data disallowed reasons:");
for (DataDisallowedReason reason : mDataDisallowedReasons) {
evaluationStr.append(" ").append(reason);
@@ -425,8 +436,8 @@
evaluationStr.append("Data allowed reason:");
evaluationStr.append(" ").append(mDataAllowedReason);
}
- evaluationStr.append(", candidate profile=" + mCandidateDataProfile);
- evaluationStr.append(", time=" + DataUtils.systemTimeToString(mEvaluatedTime));
+ evaluationStr.append(", candidate profile=").append(mCandidateDataProfile);
+ evaluationStr.append(", time=").append(DataUtils.systemTimeToString(mEvaluatedTime));
return evaluationStr.toString();
}
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index 0dbbc5c..8369874 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -103,6 +103,7 @@
import com.android.internal.telephony.data.TelephonyNetworkAgent.TelephonyNetworkAgentCallback;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.DataCallSessionStats;
+import com.android.internal.telephony.metrics.DataNetworkValidationStats;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FunctionalUtils;
@@ -124,6 +125,7 @@
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -135,11 +137,11 @@
/**
* DataNetwork class represents a single PDN (Packet Data Network).
- *
+ * <p>
* The life cycle of a data network starts from {@link ConnectingState}. If setup data request
* succeeds, then it enters {@link ConnectedState}, otherwise it enters
* {@link DisconnectedState}.
- *
+ * <p>
* When data network is in {@link ConnectingState}, it can enter {@link HandoverState} if handover
* between IWLAN and cellular occurs. After handover completes or fails, it return back to
* {@link ConnectedState}. When the data network is about to be disconnected, it first enters
@@ -148,9 +150,9 @@
* notifies data disconnected. Note that an unsolicited disconnected event from {@link DataService}
* or any vendor HAL failure response can immediately move data network from {@link ConnectedState}
* to {@link DisconnectedState}. {@link DisconnectedState} is the final state of a data network.
- *
+ * <p>
* State machine diagram:
- *
+ * <p>
*
* ┌─────────┐
* │Handover │
@@ -200,6 +202,9 @@
/** Event for bandwidth estimation from the modem changed. */
private static final int EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED = 11;
+ /** Event to report anomaly {@link #EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE} not received. */
+ private static final int EVENT_CANCEL_HANDOVER_NO_RESPONSE = 12;
+
/** Event for display info changed. This is for getting 5G NSA or mmwave information. */
private static final int EVENT_DISPLAY_INFO_CHANGED = 13;
@@ -269,17 +274,6 @@
/** Invalid context id. */
private static final int INVALID_CID = -1;
- /**
- * The data network providing default internet will have a higher score of 50. Other network
- * will have a slightly lower score of 45. The intention is other connections will not cause
- * connectivity service to tear down default internet connection. For example, to validate
- * internet connection on non-default data SIM, we'll set up a temporary internet network on
- * that data SIM. In this case, score of 45 is assigned so connectivity service will not replace
- * the default internet network with it.
- */
- private static final int DEFAULT_INTERNET_NETWORK_SCORE = 50;
- private static final int OTHER_NETWORK_SCORE = 45;
-
@IntDef(prefix = {"TEAR_DOWN_REASON_"},
value = {
TEAR_DOWN_REASON_NONE,
@@ -314,6 +308,7 @@
TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK,
TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED,
TEAR_DOWN_REASON_DATA_LIMIT_REACHED,
+ TEAR_DOWN_REASON_DATA_NETWORK_TRANSPORT_NOT_ALLOWED,
})
public @interface TearDownReason {}
@@ -413,6 +408,9 @@
/** Data network tear down due to bootstrap sim data limit reached. */
public static final int TEAR_DOWN_REASON_DATA_LIMIT_REACHED = 31;
+ /** Data network tear down due to current data network transport mismatch. */
+ public static final int TEAR_DOWN_REASON_DATA_NETWORK_TRANSPORT_NOT_ALLOWED = 32;
+
//********************************************************************************************//
// WHENEVER ADD A NEW TEAR DOWN REASON, PLEASE UPDATE DataDeactivateReasonEnum in enums.proto //
//********************************************************************************************//
@@ -507,10 +505,12 @@
private final DisconnectedState mDisconnectedState = new DisconnectedState();
/** The phone instance. */
- private final @NonNull Phone mPhone;
+ @NonNull
+ private final Phone mPhone;
/** Feature flags */
- private final @NonNull FeatureFlags mFlags;
+ @NonNull
+ private final FeatureFlags mFlags;
/**
* The subscription id. This is assigned when the network is created, and not supposed to
@@ -519,7 +519,8 @@
private final int mSubId;
/** The network score of this network. */
- private @NonNull NetworkScore mNetworkScore;
+ @NonNull
+ private NetworkScore mNetworkScore;
/**
* Indicates that
@@ -534,13 +535,15 @@
private boolean mEverConnected = false;
/** RIL interface. */
- private final @NonNull CommandsInterface mRil;
+ @NonNull
+ private final CommandsInterface mRil;
/** Local log. */
private final LocalLog mLocalLog = new LocalLog(128);
/** The callback to receives data network state update. */
- private final @NonNull DataNetworkCallback mDataNetworkCallback;
+ @NonNull
+ private final DataNetworkCallback mDataNetworkCallback;
/** The log tag. */
private String mLogTag;
@@ -548,6 +551,10 @@
/** Metrics of per data network connection. */
private final DataCallSessionStats mDataCallSessionStats;
+ /** Metrics of per data network validation. */
+ @NonNull
+ private final DataNetworkValidationStats mDataNetworkValidationStats;
+
/**
* The unique context id assigned by the data service in {@link DataCallResponse#getId()}. One
* for {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN} and one for
@@ -570,71 +577,92 @@
* Data service managers for accessing {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN} and
* {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN} data services.
*/
- private final @NonNull SparseArray<DataServiceManager> mDataServiceManagers;
+ @NonNull
+ private final SparseArray<DataServiceManager> mDataServiceManagers;
/** Access networks manager. */
- private final @NonNull AccessNetworksManager mAccessNetworksManager;
+ @NonNull
+ private final AccessNetworksManager mAccessNetworksManager;
/** Data network controller. */
- private final @NonNull DataNetworkController mDataNetworkController;
+ @NonNull
+ private final DataNetworkController mDataNetworkController;
/** Data network controller callback. */
- private final @NonNull DataNetworkController.DataNetworkControllerCallback
+ @NonNull
+ private final DataNetworkController.DataNetworkControllerCallback
mDataNetworkControllerCallback;
/** Data settings manager callback. */
- private @NonNull DataSettingsManagerCallback mDataSettingsManagerCallback;
+ @NonNull
+ private DataSettingsManagerCallback mDataSettingsManagerCallback;
/** Data config manager. */
- private final @NonNull DataConfigManager mDataConfigManager;
+ @NonNull
+ private final DataConfigManager mDataConfigManager;
/** VCN manager. */
- private final @Nullable VcnManager mVcnManager;
+ @Nullable
+ private final VcnManager mVcnManager;
/** VCN policy changed listener. */
- private @Nullable VcnNetworkPolicyChangeListener mVcnPolicyChangeListener;
+ @Nullable
+ private VcnNetworkPolicyChangeListener mVcnPolicyChangeListener;
/** The network agent associated with this data network. */
- private @NonNull TelephonyNetworkAgent mNetworkAgent;
+ @NonNull
+ private TelephonyNetworkAgent mNetworkAgent;
/** QOS callback tracker. This is only created after network connected on WWAN. */
- private @Nullable QosCallbackTracker mQosCallbackTracker;
+ @Nullable
+ private QosCallbackTracker mQosCallbackTracker;
/** NAT keepalive tracker. */
- private @Nullable KeepaliveTracker mKeepaliveTracker;
+ @Nullable
+ private KeepaliveTracker mKeepaliveTracker;
/** The data profile used to establish this data network. */
- private @NonNull DataProfile mDataProfile;
+ @NonNull
+ private DataProfile mDataProfile;
/**
* The data profile used for data handover. Some carriers might use different data profile
* between IWLAN and cellular. Only set before handover started.
*/
- private @Nullable DataProfile mHandoverDataProfile;
+ @Nullable
+ private DataProfile mHandoverDataProfile;
/** The network capabilities of this data network. */
- private @NonNull NetworkCapabilities mNetworkCapabilities;
+ @NonNull
+ private NetworkCapabilities mNetworkCapabilities;
/** The matched traffic descriptor returned from setup data call request. */
- private final @NonNull List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>();
+ @NonNull
+ private final List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>();
/** The link properties of this data network. */
- private @NonNull LinkProperties mLinkProperties;
+ @NonNull
+ private LinkProperties mLinkProperties;
/** The network slice info. */
- private @Nullable NetworkSliceInfo mNetworkSliceInfo;
+ @Nullable
+ private NetworkSliceInfo mNetworkSliceInfo;
/** The link status (i.e. RRC state). */
- private @LinkStatus int mLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN;
+ @LinkStatus
+ private int mLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN;
/** The network bandwidth. */
- private @NonNull NetworkBandwidth mNetworkBandwidth = new NetworkBandwidth(14, 14);
+ @NonNull
+ private NetworkBandwidth mNetworkBandwidth = new NetworkBandwidth(14, 14);
/** The TCP buffer sizes config. */
- private @NonNull String mTcpBufferSizes;
+ @NonNull
+ private String mTcpBufferSizes;
/** The telephony display info. */
- private @NonNull TelephonyDisplayInfo mTelephonyDisplayInfo;
+ @NonNull
+ private TelephonyDisplayInfo mTelephonyDisplayInfo;
/** Whether {@link NetworkCapabilities#NET_CAPABILITY_TEMPORARILY_NOT_METERED} is supported. */
private boolean mTempNotMeteredSupported = false;
@@ -646,7 +674,8 @@
private boolean mCongested = false;
/** The network requests associated with this data network */
- private final @NonNull NetworkRequestList mAttachedNetworkRequestList =
+ @NonNull
+ private final NetworkRequestList mAttachedNetworkRequestList =
new NetworkRequestList();
/**
@@ -655,18 +684,21 @@
* {@link DataServiceCallback#onDataCallListChanged(List)}. The very first update must be
* from {@link DataServiceCallback#onSetupDataCallComplete(int, DataCallResponse)}.
*/
- private @Nullable DataCallResponse mDataCallResponse = null;
+ @Nullable
+ private DataCallResponse mDataCallResponse = null;
/**
* The fail cause from either setup data failure or unsolicited disconnect reported by data
* service.
*/
- private @DataFailureCause int mFailCause = DataFailCause.NONE;
+ @DataFailureCause
+ private int mFailCause = DataFailCause.NONE;
/**
* The tear down reason if the data call is voluntarily deactivated, not due to failure.
*/
- private @TearDownReason int mTearDownReason = TEAR_DOWN_REASON_NONE;
+ @TearDownReason
+ private int mTearDownReason = TEAR_DOWN_REASON_NONE;
/**
* The retry delay in milliseconds from setup data failure.
@@ -686,40 +718,53 @@
* The current transport of the data network. For handover, the current transport will be set
* after handover completes.
*/
- private @TransportType int mTransport;
+ @TransportType
+ private int mTransport;
/**
* The last known data network type.
*/
- private @NetworkType int mLastKnownDataNetworkType;
+ @NetworkType
+ private int mLastKnownDataNetworkType;
/**
* The last known roaming state of this data network.
*/
private boolean mLastKnownRoamingState;
+ /**
+ * The non-terrestrial status
+ */
+ private final boolean mIsSatellite;
+
/** The reason that why setting up this data network is allowed. */
- private @NonNull DataAllowedReason mDataAllowedReason;
+ @NonNull
+ private final DataAllowedReason mDataAllowedReason;
/**
* PCO (Protocol Configuration Options) data received from the network. The first key is the
* cid of the PCO data, the second key is the PCO id, the value is the PCO data.
*/
- private final @NonNull Map<Integer, Map<Integer, PcoData>> mPcoData = new ArrayMap<>();
+ @NonNull
+ private final Map<Integer, Map<Integer, PcoData>> mPcoData = new ArrayMap<>();
/** The QOS bearer sessions. */
- private final @NonNull List<QosBearerSession> mQosBearerSessions = new ArrayList<>();
+ @NonNull
+ private final List<QosBearerSession> mQosBearerSessions = new ArrayList<>();
/** The QOS for the Default Bearer, should be non-null on LTE and NR */
- private @Nullable Qos mDefaultQos;
+ @Nullable
+ private Qos mDefaultQos;
/**
* The UIDs of packages that have carrier privilege.
*/
- private @NonNull int[] mAdministratorUids = new int[0];
+ @NonNull
+ private int[] mAdministratorUids = new int[0];
/** Carrier privileges callback to monitor administrator UID change. */
- private @Nullable TelephonyManager.CarrierPrivilegesCallback mCarrierPrivilegesCallback;
+ @Nullable
+ private TelephonyManager.CarrierPrivilegesCallback mCarrierPrivilegesCallback;
/**
* Carrier service package uid. This UID will not change through the life cycle of data network.
@@ -729,30 +774,42 @@
/**
* Link bandwidth estimator callback for receiving latest link bandwidth information.
*/
- private @Nullable LinkBandwidthEstimatorCallback mLinkBandwidthEstimatorCallback;
+ @Nullable
+ private LinkBandwidthEstimatorCallback mLinkBandwidthEstimatorCallback;
/**
* Data config callback for carrier config update.
*/
- private @Nullable DataConfigManagerCallback mDataConfigManagerCallback;
+ @Nullable
+ private DataConfigManagerCallback mDataConfigManagerCallback;
/**
* Network validation status for this data network. If the data service provider does not
* support the network validation feature, should be UNSUPPORTED.
*/
- private @PreciseDataConnectionState.NetworkValidationStatus int mNetworkValidationStatus =
+ @PreciseDataConnectionState.NetworkValidationStatus
+ private int mNetworkValidationStatus =
PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED;
/**
* Callback used to respond to a network validation request to determine whether the request is
* successfully submitted. If the request has been submitted, change it to null.
*/
- private @Nullable Consumer<Integer> mNetworkValidationResultCodeCallback;
+ @Nullable
+ private Consumer<Integer> mNetworkValidationResultCodeCallback;
/**
* Callback used to listen QNS preference changes.
*/
- private @Nullable AccessNetworksManagerCallback mAccessNetworksManagerCallback;
+ @Nullable
+ private AccessNetworksManagerCallback mAccessNetworksManagerCallback;
+
+ /**
+ * PreciseDataConnectionState, the most recently notified. If it has never been notified, it is
+ * null.
+ */
+ @Nullable
+ private PreciseDataConnectionState mPreciseDataConnectionState;
/**
* The network bandwidth.
@@ -977,6 +1034,7 @@
mDataNetworkControllerCallback);
mDataConfigManager = mDataNetworkController.getDataConfigManager();
mDataCallSessionStats = new DataCallSessionStats(mPhone);
+ mDataNetworkValidationStats = new DataNetworkValidationStats(mPhone);
mDataNetworkCallback = callback;
mDataProfile = dataProfile;
if (dataProfile.getTrafficDescriptor() != null) {
@@ -988,25 +1046,40 @@
mTransport = transport;
mLastKnownDataNetworkType = getDataNetworkType();
mLastKnownRoamingState = mPhone.getServiceState().getDataRoamingFromRegistration();
+ mIsSatellite = mPhone.getServiceState().isUsingNonTerrestrialNetwork()
+ && transport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
mDataAllowedReason = dataAllowedReason;
dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
- mAttachedNetworkRequestList.addAll(networkRequestList);
for (int transportType : mAccessNetworksManager.getAvailableTransports()) {
mCid.put(transportType, INVALID_CID);
}
mTelephonyDisplayInfo = mPhone.getDisplayInfoController().getTelephonyDisplayInfo();
mTcpBufferSizes = mDataConfigManager.getTcpConfigString(mTelephonyDisplayInfo);
- for (TelephonyNetworkRequest networkRequest : networkRequestList) {
- networkRequest.setAttachedNetwork(DataNetwork.this);
- networkRequest.setState(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED);
- }
-
+ // network capabilities infer connectivity transport and MMTEL from the requested
+ // capabilities.
+ // TODO: Ideally we shouldn't infer network capabilities base on the requested capabilities,
+ // but currently there are 2 hacks associated with getForcedCellularTransportCapabilities
+ // and IMS service requesting IMS|MMTEL that need to support. When we stop supporting these
+ // cases, we shouldn't consider the requests when determining the network capabilities.
+ mAttachedNetworkRequestList.addAll(networkRequestList);
// Update the capabilities in the constructor is to make sure the data network has initial
// capability immediately after created. Doing this connecting state creates the window that
// DataNetworkController might check if existing data network's capability can satisfy the
// next network request within this window.
updateNetworkCapabilities();
+
+ // Remove the requests that can't use the initial capabilities
+ ListIterator<TelephonyNetworkRequest> iter = mAttachedNetworkRequestList.listIterator();
+ while (iter.hasNext()) {
+ TelephonyNetworkRequest request = iter.next();
+ if (request.canBeSatisfiedBy(mNetworkCapabilities)) {
+ request.setAttachedNetwork(DataNetwork.this);
+ request.setState(TelephonyNetworkRequest.REQUEST_STATE_SATISFIED);
+ } else {
+ iter.remove();
+ }
+ }
}
/**
@@ -1050,7 +1123,8 @@
*
* @return The telephony network agent.
*/
- private @NonNull TelephonyNetworkAgent createNetworkAgent() {
+ @NonNull
+ private TelephonyNetworkAgent createNetworkAgent() {
final NetworkAgentConfig.Builder configBuilder = new NetworkAgentConfig.Builder();
configBuilder.setLegacyType(ConnectivityManager.TYPE_MOBILE);
configBuilder.setLegacyTypeName("MOBILE");
@@ -1083,13 +1157,8 @@
mPhone.getPhoneId());
final NetworkProvider provider = (null == factory) ? null : factory.getProvider();
- // Always prefer IWLAN network for MMS designated network.
- // TODO(b/293656884) Proper use of primary transport to avoid conflicting with DSDA.
- boolean isPreferred = mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
- && getApnTypeNetworkCapability() == NetworkCapabilities.NET_CAPABILITY_MMS;
-
- mNetworkScore = new NetworkScore.Builder().setTransportPrimary(isPreferred)
- .setKeepConnectedReason(isHandoverInProgress()
+ mNetworkScore = new NetworkScore.Builder()
+ .setKeepConnectedReason(isHandoverInProgress()
? NetworkScore.KEEP_CONNECTED_FOR_HANDOVER
: NetworkScore.KEEP_CONNECTED_NONE).build();
@@ -1164,7 +1233,7 @@
mCarrierPrivilegesCallback =
(Set<String> privilegedPackageNames, Set<Integer> privilegedUids) -> {
- log("onCarrierPrivilegesChanged, Uids=" + privilegedUids.toString());
+ log("onCarrierPrivilegesChanged, Uids=" + privilegedUids);
Message message = obtainMessage(EVENT_CARRIER_PRIVILEGED_UIDS_CHANGED);
AsyncResult.forMessage(
message,
@@ -1316,11 +1385,13 @@
break;
}
case EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE:
+ removeMessages(EVENT_CANCEL_HANDOVER_NO_RESPONSE);
log("Notified handover cancelled.");
break;
case EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED:
case EVENT_TEAR_DOWN_NETWORK:
case EVENT_STUCK_IN_TRANSIENT_STATE:
+ case EVENT_CANCEL_HANDOVER_NO_RESPONSE:
case EVENT_DISPLAY_INFO_CHANGED:
case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
case EVENT_CSS_INDICATOR_CHANGED:
@@ -1416,7 +1487,10 @@
setupData();
} else {
mRetryDelayMillis = DataCallResponse.RETRY_DURATION_UNDEFINED;
- mFailCause = DataFailCause.NO_RETRY_FAILURE;
+ if (!mFlags.keepEmptyRequestsNetwork()) {
+ // This will mark the data profile as no retry perm failure.
+ mFailCause = DataFailCause.NO_RETRY_FAILURE;
+ }
transitionTo(mDisconnectedState);
}
break;
@@ -1494,7 +1568,7 @@
int apnTypeBitmask = mDataProfile.getApnSetting() != null
? mDataProfile.getApnSetting().getApnTypeBitmask() : ApnSetting.TYPE_NONE;
- mDataCallSessionStats.onSetupDataCall(apnTypeBitmask);
+ mDataCallSessionStats.onSetupDataCall(apnTypeBitmask, isSatellite());
logl("setupData: accessNetwork="
+ AccessNetworkType.toString(accessNetwork) + ", " + mDataProfile
@@ -1542,12 +1616,7 @@
updateDataNetwork(response);
- // TODO: Evaluate all network requests and see if each request still can be
- // satisfied.
- // For requests that can't be satisfied anymore, we need to put them back to the
- // unsatisfied pool. If none of network requests can be satisfied, then there is no
- // need to mark network agent connected. Just silently deactivate the data network.
- if (mAttachedNetworkRequestList.isEmpty()) {
+ if (!mFlags.keepEmptyRequestsNetwork() && mAttachedNetworkRequestList.isEmpty()) {
log("Tear down the network since there is no live network request.");
// Directly call onTearDown here. Calling tearDown will cause deadlock because
// EVENT_TEAR_DOWN_NETWORK is deferred until state machine enters connected
@@ -1634,9 +1703,7 @@
// If we've ever received PCO data before connected, now it's the time to process it.
mPcoData.getOrDefault(mCid.get(mTransport), Collections.emptyMap())
- .forEach((pcoId, pcoData) -> {
- onPcoDataChanged(pcoData);
- });
+ .forEach((pcoId, pcoData) -> onPcoDataChanged(pcoData));
mDataNetworkCallback.invokeFromExecutor(
() -> mDataNetworkCallback.onLinkStatusChanged(DataNetwork.this, mLinkStatus));
@@ -1710,6 +1777,12 @@
// Network validation request can be accepted if the data is in connected state
handleDataNetworkValidationRequest((Consumer<Integer>) msg.obj);
break;
+ case EVENT_CANCEL_HANDOVER_NO_RESPONSE:
+ reportAnomaly("Cancel handover no response within "
+ + TimeUnit.MILLISECONDS.toSeconds(
+ mDataConfigManager.getNetworkHandoverTimeoutMs())
+ + " seconds.", "ad320988-0601-4955-836a-e6b67289c294");
+ break;
default:
return NOT_HANDLED;
}
@@ -1725,6 +1798,7 @@
private final class HandoverState extends State {
@Override
public void enter() {
+ removeMessages(EVENT_CANCEL_HANDOVER_NO_RESPONSE);
sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE,
mDataConfigManager.getNetworkHandoverTimeoutMs());
notifyPreciseDataConnectionState();
@@ -1908,6 +1982,9 @@
if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
unregisterForWwanEvents();
}
+ // Since NetworkValidation is able to request only in the Connected state,
+ // if ever connected, log for onDataNetworkDisconnected.
+ mDataNetworkValidationStats.onDataNetworkDisconnected(getDataNetworkType());
} else {
mDataNetworkCallback.invokeFromExecutor(() -> mDataNetworkCallback
.onSetupDataFailed(DataNetwork.this,
@@ -2008,7 +2085,7 @@
log("Successfully attached network request " + networkRequest);
}
}
- if (failedList.size() > 0) {
+ if (!failedList.isEmpty()) {
mDataNetworkCallback.invokeFromExecutor(() -> mDataNetworkCallback
.onAttachFailed(DataNetwork.this, failedList));
}
@@ -2173,8 +2250,7 @@
private static boolean areImmutableCapabilitiesChanged(
@NonNull NetworkCapabilities oldCapabilities,
@NonNull NetworkCapabilities newCapabilities) {
- if (oldCapabilities == null
- || ArrayUtils.isEmpty(oldCapabilities.getCapabilities())) return false;
+ if (ArrayUtils.isEmpty(oldCapabilities.getCapabilities())) return false;
// Remove mutable capabilities from both old and new capabilities, the remaining
// capabilities would be immutable capabilities.
@@ -2204,6 +2280,7 @@
// will always be registered with NOT_SUSPENDED capability.
mNetworkAgent = createNetworkAgent();
mNetworkAgent.markConnected();
+ notifyPreciseDataConnectionState();
// Because network agent is always created with NOT_SUSPENDED, we need to update
// the suspended if it's was in suspended state.
if (mSuspended) {
@@ -2214,11 +2291,32 @@
}
/**
+ * @return {@code true} if this is a satellite data network.
+ */
+ public boolean isSatellite() {
+ return mIsSatellite;
+ }
+
+ /**
* Update the network capabilities.
*/
private void updateNetworkCapabilities() {
- final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder();
+
+ if (mFlags.satelliteInternet() && mIsSatellite
+ && mDataConfigManager.getForcedCellularTransportCapabilities().stream()
+ .noneMatch(this::hasNetworkCapabilityInNetworkRequests)) {
+ // TODO: b/328622096 remove the try/catch
+ try {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ } catch (IllegalArgumentException exception) {
+ loge("TRANSPORT_SATELLITE is not supported.");
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ }
+ } else {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ }
+
boolean roaming = mPhone.getServiceState().getDataRoaming();
builder.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
@@ -2347,6 +2445,7 @@
}
// Always start with not-restricted, and then remove if needed.
+ // By default, NET_CAPABILITY_NOT_RESTRICTED and NET_CAPABILITY_NOT_CONSTRAINED are included
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
// When data is disabled, or data roaming is disabled and the device is roaming, we need
@@ -2401,13 +2500,13 @@
DataProfile dataProfile = mDataNetworkController.getDataProfileManager()
.getDataProfileForNetworkRequest(new TelephonyNetworkRequest(
new NetworkRequest.Builder().addCapability(
- NetworkCapabilities.NET_CAPABILITY_MMS).build(), mPhone),
+ NetworkCapabilities.NET_CAPABILITY_MMS).build(), mPhone, mFlags),
TelephonyManager.NETWORK_TYPE_IWLAN, false, false, false);
// If we find another data data profile that can support MMS on IWLAN, then remove
// the MMS capability from this cellular network. This will allow IWLAN to be
// brought up for MMS later.
- if (dataProfile != null && !dataProfile.equals(mDataProfile)) {
- log("Found a different data profile " + mDataProfile.getApn()
+ if (dataProfile != null && !dataProfile.getApn().equals(mDataProfile.getApn())) {
+ log("Found a different apn name " + mDataProfile.getApn()
+ " that can serve MMS on IWLAN.");
builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
}
@@ -2426,6 +2525,23 @@
builder.setLinkDownstreamBandwidthKbps(mNetworkBandwidth.downlinkBandwidthKbps);
builder.setLinkUpstreamBandwidthKbps(mNetworkBandwidth.uplinkBandwidthKbps);
+ // Configure the network as restricted/constrained for unrestricted satellite network.
+ if (mFlags.satelliteInternet() && mIsSatellite && builder.build()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
+ switch (mDataConfigManager.getSatelliteDataSupportMode()) {
+ case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED
+ -> builder.removeCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ case CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED -> {
+ try {
+ builder.removeCapability(DataUtils
+ .NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+ } catch (Exception ignored) { }
+ }
+ // default case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL
+ }
+ }
+
NetworkCapabilities nc = builder.build();
if (mNetworkCapabilities == null || mNetworkAgent == null) {
// This is the first time when network capabilities is created. The agent is not created
@@ -2474,21 +2590,24 @@
/**
* @return The network capabilities of this data network.
*/
- public @NonNull NetworkCapabilities getNetworkCapabilities() {
+ @NonNull
+ public NetworkCapabilities getNetworkCapabilities() {
return mNetworkCapabilities;
}
/**
* @return The link properties of this data network.
*/
- public @NonNull LinkProperties getLinkProperties() {
+ @NonNull
+ public LinkProperties getLinkProperties() {
return mLinkProperties;
}
/**
* @return The data profile of this data network.
*/
- public @NonNull DataProfile getDataProfile() {
+ @NonNull
+ public DataProfile getDataProfile() {
return mDataProfile;
}
@@ -2509,7 +2628,6 @@
// Never set suspended for emergency apn. Emergency data connection
// can work while device is not in service.
if (mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) {
- newSuspendedState = false;
// If we are not in service, change to suspended.
} else if (nri.getRegistrationState()
!= NetworkRegistrationInfo.REGISTRATION_STATE_HOME
@@ -2553,7 +2671,8 @@
*
* @return The fail cause. {@link DataFailCause#NONE} if succeeds.
*/
- private @DataFailureCause int getFailCauseFromDataCallResponse(
+ @DataFailureCause
+ private int getFailCauseFromDataCallResponse(
@DataServiceCallback.ResultCode int resultCode, @Nullable DataCallResponse response) {
int failCause = DataFailCause.NONE;
switch (resultCode) {
@@ -2584,7 +2703,8 @@
*
* @param response The data call response from data service.
*/
- private void updateDataNetwork(@NonNull DataCallResponse response) {
+ private void updateDataNetwork(@Nullable DataCallResponse response) {
+ if (response == null) return;
mCid.put(mTransport, response.getId());
LinkProperties linkProperties = new LinkProperties();
@@ -2611,7 +2731,7 @@
}
// Set link addresses
- if (response.getAddresses().size() > 0) {
+ if (!response.getAddresses().isEmpty()) {
for (LinkAddress la : response.getAddresses()) {
if (!la.getAddress().isAnyLocalAddress()) {
logv("addr/pl=" + la.getAddress() + "/" + la.getPrefixLength());
@@ -2623,7 +2743,7 @@
}
// Set DNS servers
- if (response.getDnsAddresses().size() > 0) {
+ if (!response.getDnsAddresses().isEmpty()) {
for (InetAddress dns : response.getDnsAddresses()) {
if (!dns.isAnyLocalAddress()) {
linkProperties.addDnsServer(dns);
@@ -2634,7 +2754,7 @@
}
// Set PCSCF
- if (response.getPcscfAddresses().size() > 0) {
+ if (!response.getPcscfAddresses().isEmpty()) {
for (InetAddress pcscf : response.getPcscfAddresses()) {
linkProperties.addPcscfServer(pcscf);
}
@@ -2773,22 +2893,22 @@
== AccessNetworkConstants.TRANSPORT_TYPE_WWAN
? "RIL" : "IWLAN data service";
if (protocol == ApnSetting.PROTOCOL_IP) {
- if (response.getAddresses().stream().anyMatch(
- la -> la.getAddress() instanceof java.net.Inet6Address)) {
- loge("Invalid DataCallResponse. Requested IPv4 but got IPv6 address."
- + response);
+ if (response.getAddresses().stream().noneMatch(
+ la -> la.getAddress() instanceof java.net.Inet4Address)) {
+ loge("Invalid DataCallResponse. Requested IPv4 but didn't get an "
+ + "IPv4 address." + response);
reportAnomaly(underlyingDataService + " reported mismatched IP "
- + "type. Requested IPv4 but got IPv6 address.",
- "7744f920-fb64-4db0-ba47-de0eae485a81");
+ + "type. Requested IPv4 but didn't get an IPv4 "
+ + "address.", "7744f920-fb64-4db0-ba47-de0eae485a82");
}
} else if (protocol == ApnSetting.PROTOCOL_IPV6) {
- if (response.getAddresses().stream().anyMatch(
- la -> la.getAddress() instanceof java.net.Inet4Address)) {
- loge("Invalid DataCallResponse. Requested IPv6 but got IPv4 address."
- + response);
+ if (response.getAddresses().stream().noneMatch(
+ la -> la.getAddress() instanceof java.net.Inet6Address)) {
+ loge("Invalid DataCallResponse. Requested IPv6 but didn't get an "
+ + "IPv6 address." + response);
reportAnomaly(underlyingDataService + " reported mismatched IP "
- + "type. Requested IPv6 but got IPv4 address.",
- "7744f920-fb64-4db0-ba47-de0eae485a81");
+ + "type. Requested IPv6 but didn't get an IPv6 "
+ + "address.", "7744f920-fb64-4db0-ba47-de0eae485a82");
}
}
}
@@ -2890,8 +3010,8 @@
* will be performed. {@code null} if the data network is already disconnected or being
* disconnected.
*/
- public @Nullable Runnable tearDownWhenConditionMet(@TearDownReason int reason,
- long timeoutMillis) {
+ @Nullable
+ public Runnable tearDownWhenConditionMet(@TearDownReason int reason, long timeoutMillis) {
if (getCurrentState() == null || isDisconnected() || isDisconnecting()) {
loge("tearDownWhenConditionMet: Not in the right state. State=" + getCurrentState());
return null;
@@ -2930,6 +3050,7 @@
mDataCallResponse = response;
if (response.getLinkStatus() != DataCallResponse.LINK_STATUS_INACTIVE) {
updateDataNetwork(response);
+ notifyPreciseDataConnectionState();
} else {
log("onDataStateChanged: PDN inactive reported by "
+ AccessNetworkConstants.transportTypeToString(mTransport)
@@ -3003,12 +3124,12 @@
NetworkBandwidth bandwidthFromConfig = mDataConfigManager.getBandwidthForNetworkType(
mTelephonyDisplayInfo);
- if (downlinkBandwidthKbps == LinkCapacityEstimate.INVALID && bandwidthFromConfig != null) {
+ if (downlinkBandwidthKbps == LinkCapacityEstimate.INVALID) {
// Fallback to carrier config.
downlinkBandwidthKbps = bandwidthFromConfig.downlinkBandwidthKbps;
}
- if (uplinkBandwidthKbps == LinkCapacityEstimate.INVALID && bandwidthFromConfig != null) {
+ if (uplinkBandwidthKbps == LinkCapacityEstimate.INVALID) {
// Fallback to carrier config.
uplinkBandwidthKbps = bandwidthFromConfig.uplinkBandwidthKbps;
}
@@ -3153,7 +3274,8 @@
/**
* @return The current network type reported by the network service.
*/
- private @NetworkType int getDataNetworkType() {
+ @NetworkType
+ private int getDataNetworkType() {
return getDataNetworkType(mTransport);
}
@@ -3163,7 +3285,8 @@
* @param transport The transport.
* @return The data network type.
*/
- private @NetworkType int getDataNetworkType(@TransportType int transport) {
+ @NetworkType
+ private int getDataNetworkType(@TransportType int transport) {
// WLAN transport can't have network type other than IWLAN. Ideally service state tracker
// should report the correct RAT, but sometimes race condition could happen that service
// state is reset to out of service and RAT not updated to IWLAN yet.
@@ -3183,7 +3306,8 @@
/**
* @return The physical link status (i.e. RRC state).
*/
- public @LinkStatus int getLinkStatus() {
+ @LinkStatus
+ public int getLinkStatus() {
return mLinkStatus;
}
@@ -3206,7 +3330,8 @@
/**
* @return Network registration info on the current transport.
*/
- private @Nullable NetworkRegistrationInfo getNetworkRegistrationInfo() {
+ @Nullable
+ private NetworkRegistrationInfo getNetworkRegistrationInfo() {
NetworkRegistrationInfo nri = mPhone.getServiceStateTracker().getServiceState()
.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, mTransport);
if (nri == null) {
@@ -3228,7 +3353,8 @@
*
* @see #getPriority()
*/
- public @NetCapability int getApnTypeNetworkCapability() {
+ @NetCapability
+ public int getApnTypeNetworkCapability() {
if (!mAttachedNetworkRequestList.isEmpty()) {
// The highest priority network request is always at the top of list.
return mAttachedNetworkRequestList.get(0).getApnTypeNetworkCapability();
@@ -3269,7 +3395,8 @@
/**
* @return The attached network request list.
*/
- public @NonNull NetworkRequestList getAttachedNetworkRequestList() {
+ @NonNull
+ public NetworkRequestList getAttachedNetworkRequestList() {
return mAttachedNetworkRequestList;
}
@@ -3318,11 +3445,13 @@
/**
* @return The current transport of the data network.
*/
- public @TransportType int getTransport() {
+ @TransportType
+ public int getTransport() {
return mTransport;
}
- private @DataState int getState() {
+ @DataState
+ private int getState() {
IState state = getCurrentState();
if (state == null || isDisconnected()) {
return TelephonyManager.DATA_DISCONNECTED;
@@ -3367,6 +3496,7 @@
return new PreciseDataConnectionState.Builder()
.setTransportType(mTransport)
.setId(mCid.get(mTransport))
+ .setNetworkAgentId(mNetworkAgent.getId())
.setState(getState())
.setApnSetting(mDataProfile.getApnSetting())
.setLinkProperties(mLinkProperties)
@@ -3380,16 +3510,27 @@
/**
* Send the precise data connection state to the listener of
* {@link android.telephony.TelephonyCallback.PreciseDataConnectionStateListener}.
+ * <p>
+ * Note that notify only when {@link DataState} or {@link
+ * PreciseDataConnectionState.NetworkValidationStatus} or {@link TelephonyNetworkAgent#getId}
+ * changes.
*/
private void notifyPreciseDataConnectionState() {
PreciseDataConnectionState pdcs = getPreciseDataConnectionState();
- logv("notifyPreciseDataConnectionState=" + pdcs);
- mPhone.notifyDataConnection(pdcs);
+ if (mPreciseDataConnectionState == null
+ || mPreciseDataConnectionState.getState() != pdcs.getState()
+ || mPreciseDataConnectionState.getNetworkValidationStatus()
+ != pdcs.getNetworkValidationStatus()
+ || mPreciseDataConnectionState.getNetId() != pdcs.getNetId()) {
+ mPreciseDataConnectionState = pdcs;
+ logv("notifyPreciseDataConnectionState=" + pdcs);
+ mPhone.notifyDataConnection(pdcs);
+ }
}
/**
* Request the data network to handover to the target transport.
- *
+ * <p>
* This is the starting point of initiating IWLAN/cellular handover. It will first call
* {@link DataServiceManager#startHandover(int, Message)} to notify source transport that
* handover is about to start, and then call {@link DataServiceManager#setupDataCall(int,
@@ -3474,6 +3615,8 @@
DataService.REQUEST_REASON_HANDOVER, mLinkProperties, mPduSessionId,
mNetworkSliceInfo, mHandoverDataProfile.getTrafficDescriptor(), true,
obtainMessage(EVENT_HANDOVER_RESPONSE, retryEntry));
+
+ mDataNetworkValidationStats.onHandoverAttempted();
}
/**
@@ -3521,6 +3664,8 @@
// id can be released if it is preserved for handover.
mDataServiceManagers.get(mTransport).cancelHandover(mCid.get(mTransport),
obtainMessage(EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE));
+ sendMessageDelayed(EVENT_CANCEL_HANDOVER_NO_RESPONSE,
+ mDataConfigManager.getNetworkHandoverTimeoutMs());
long retry = response != null ? response.getRetryDurationMillis()
: DataCallResponse.RETRY_DURATION_UNDEFINED;
@@ -3596,7 +3741,8 @@
/**
* @return The last known data network type of the data network.
*/
- public @NetworkType int getLastKnownDataNetworkType() {
+ @NetworkType
+ public int getLastKnownDataNetworkType() {
return mLastKnownDataNetworkType;
}
@@ -3610,7 +3756,8 @@
/**
* @return The PCO data received from the network.
*/
- public @NonNull Map<Integer, PcoData> getPcoData() {
+ @NonNull
+ public Map<Integer, PcoData> getPcoData() {
if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
|| mCid.get(mTransport) == INVALID_CID) {
return Collections.emptyMap();
@@ -3644,7 +3791,7 @@
}
/**
- * The network validation requests moves to process on the statemachich handler. A request is
+ * The network validation requests moves to process on the state machine handler. A request is
* processed according to state of the data network.
*/
public void requestNetworkValidation(@NonNull Consumer<Integer> resultCodeCallback) {
@@ -3668,6 +3815,11 @@
// Request validation directly from the data service.
mDataServiceManagers.get(mTransport).requestNetworkValidation(
mCid.get(mTransport), obtainMessage(EVENT_DATA_NETWORK_VALIDATION_RESPONSE));
+
+ int apnTypeBitmask = mDataProfile.getApnSetting() != null
+ ? mDataProfile.getApnSetting().getApnTypeBitmask() : ApnSetting.TYPE_NONE;
+ mDataNetworkValidationStats.onRequestNetworkValidation(apnTypeBitmask);
+
log("handleDataNetworkValidationRequest, network validation requested");
}
@@ -3696,8 +3848,7 @@
/**
* Update the validation status from {@link DataCallResponse}, convert to network validation
- * status {@link PreciseDataConnectionState.NetworkValidationStatus} and notify to
- * {@link PreciseDataConnectionState} if status was changed.
+ * status {@link PreciseDataConnectionState.NetworkValidationStatus}.
*
* @param networkValidationStatus {@link PreciseDataConnectionState.NetworkValidationStatus}
*/
@@ -3714,8 +3865,10 @@
+ PreciseDataConnectionState.networkValidationStatusToString(
networkValidationStatus));
mNetworkValidationStatus = networkValidationStatus;
- notifyPreciseDataConnectionState();
}
+
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ mNetworkValidationStatus, getDataNetworkType());
}
/**
@@ -3724,75 +3877,54 @@
* @param reason Data deactivation reason.
* @return The deactivation reason in string format.
*/
- public static @NonNull String tearDownReasonToString(@TearDownReason int reason) {
- switch (reason) {
- case TEAR_DOWN_REASON_NONE:
- return "NONE";
- case TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED:
- return "CONNECTIVITY_SERVICE_UNWANTED";
- case TEAR_DOWN_REASON_SIM_REMOVAL:
- return "SIM_REMOVAL";
- case TEAR_DOWN_REASON_AIRPLANE_MODE_ON:
- return "AIRPLANE_MODE_ON";
- case TEAR_DOWN_REASON_DATA_DISABLED:
- return "DATA_DISABLED";
- case TEAR_DOWN_REASON_NO_LIVE_REQUEST:
- return "TEAR_DOWN_REASON_NO_LIVE_REQUEST";
- case TEAR_DOWN_REASON_RAT_NOT_ALLOWED:
- return "TEAR_DOWN_REASON_RAT_NOT_ALLOWED";
- case TEAR_DOWN_REASON_ROAMING_DISABLED:
- return "TEAR_DOWN_REASON_ROAMING_DISABLED";
- case TEAR_DOWN_REASON_CONCURRENT_VOICE_DATA_NOT_ALLOWED:
- return "TEAR_DOWN_REASON_CONCURRENT_VOICE_DATA_NOT_ALLOWED";
- case TEAR_DOWN_REASON_SERVICE_OPTION_NOT_SUPPORTED:
- return "TEAR_DOWN_REASON_SERVICE_OPTION_NOT_SUPPORTED";
- case TEAR_DOWN_REASON_DATA_SERVICE_NOT_READY:
- return "TEAR_DOWN_REASON_DATA_SERVICE_NOT_READY";
- case TEAR_DOWN_REASON_POWER_OFF_BY_CARRIER:
- return "TEAR_DOWN_REASON_POWER_OFF_BY_CARRIER";
- case TEAR_DOWN_REASON_DATA_STALL:
- return "TEAR_DOWN_REASON_DATA_STALL";
- case TEAR_DOWN_REASON_HANDOVER_FAILED:
- return "TEAR_DOWN_REASON_HANDOVER_FAILED";
- case TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED:
- return "TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED";
- case TEAR_DOWN_REASON_VCN_REQUESTED:
- return "TEAR_DOWN_REASON_VCN_REQUESTED";
- case TEAR_DOWN_REASON_VOPS_NOT_SUPPORTED:
- return "TEAR_DOWN_REASON_VOPS_NOT_SUPPORTED";
- case TEAR_DOWN_REASON_DEFAULT_DATA_UNSELECTED:
- return "TEAR_DOWN_REASON_DEFAULT_DATA_UNSELECTED";
- case TEAR_DOWN_REASON_NOT_IN_SERVICE:
- return "TEAR_DOWN_REASON_NOT_IN_SERVICE";
- case TEAR_DOWN_REASON_DATA_CONFIG_NOT_READY:
- return "TEAR_DOWN_REASON_DATA_CONFIG_NOT_READY";
- case TEAR_DOWN_REASON_PENDING_TEAR_DOWN_ALL:
- return "TEAR_DOWN_REASON_PENDING_TEAR_DOWN_ALL";
- case TEAR_DOWN_REASON_NO_SUITABLE_DATA_PROFILE:
- return "TEAR_DOWN_REASON_NO_SUITABLE_DATA_PROFILE";
- case TEAR_DOWN_REASON_CDMA_EMERGENCY_CALLBACK_MODE:
- return "TEAR_DOWN_REASON_CDMA_EMERGENCY_CALLBACK_MODE";
- case TEAR_DOWN_REASON_RETRY_SCHEDULED:
- return "TEAR_DOWN_REASON_RETRY_SCHEDULED";
- case TEAR_DOWN_REASON_DATA_THROTTLED:
- return "TEAR_DOWN_REASON_DATA_THROTTLED";
- case TEAR_DOWN_REASON_DATA_PROFILE_INVALID:
- return "TEAR_DOWN_REASON_DATA_PROFILE_INVALID";
- case TEAR_DOWN_REASON_DATA_PROFILE_NOT_PREFERRED:
- return "TEAR_DOWN_REASON_DATA_PROFILE_NOT_PREFERRED";
- case TEAR_DOWN_REASON_NOT_ALLOWED_BY_POLICY:
- return "TEAR_DOWN_REASON_NOT_ALLOWED_BY_POLICY";
- case TEAR_DOWN_REASON_ILLEGAL_STATE:
- return "TEAR_DOWN_REASON_ILLEGAL_STATE";
- case TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK:
- return "TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK";
- case TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED:
- return "TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED";
- case TEAR_DOWN_REASON_DATA_LIMIT_REACHED:
- return "TEAR_DOWN_REASON_DATA_LIMIT_REACHED";
- default:
- return "UNKNOWN(" + reason + ")";
- }
+ @NonNull
+ public static String tearDownReasonToString(@TearDownReason int reason) {
+ return switch (reason) {
+ case TEAR_DOWN_REASON_NONE -> "NONE";
+ case TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED -> "CONNECTIVITY_SERVICE_UNWANTED";
+ case TEAR_DOWN_REASON_SIM_REMOVAL -> "SIM_REMOVAL";
+ case TEAR_DOWN_REASON_AIRPLANE_MODE_ON -> "AIRPLANE_MODE_ON";
+ case TEAR_DOWN_REASON_DATA_DISABLED -> "DATA_DISABLED";
+ case TEAR_DOWN_REASON_NO_LIVE_REQUEST -> "TEAR_DOWN_REASON_NO_LIVE_REQUEST";
+ case TEAR_DOWN_REASON_RAT_NOT_ALLOWED -> "TEAR_DOWN_REASON_RAT_NOT_ALLOWED";
+ case TEAR_DOWN_REASON_ROAMING_DISABLED -> "TEAR_DOWN_REASON_ROAMING_DISABLED";
+ case TEAR_DOWN_REASON_CONCURRENT_VOICE_DATA_NOT_ALLOWED ->
+ "TEAR_DOWN_REASON_CONCURRENT_VOICE_DATA_NOT_ALLOWED";
+ case TEAR_DOWN_REASON_SERVICE_OPTION_NOT_SUPPORTED ->
+ "TEAR_DOWN_REASON_SERVICE_OPTION_NOT_SUPPORTED";
+ case TEAR_DOWN_REASON_DATA_SERVICE_NOT_READY ->
+ "TEAR_DOWN_REASON_DATA_SERVICE_NOT_READY";
+ case TEAR_DOWN_REASON_POWER_OFF_BY_CARRIER -> "TEAR_DOWN_REASON_POWER_OFF_BY_CARRIER";
+ case TEAR_DOWN_REASON_DATA_STALL -> "TEAR_DOWN_REASON_DATA_STALL";
+ case TEAR_DOWN_REASON_HANDOVER_FAILED -> "TEAR_DOWN_REASON_HANDOVER_FAILED";
+ case TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED -> "TEAR_DOWN_REASON_HANDOVER_NOT_ALLOWED";
+ case TEAR_DOWN_REASON_VCN_REQUESTED -> "TEAR_DOWN_REASON_VCN_REQUESTED";
+ case TEAR_DOWN_REASON_VOPS_NOT_SUPPORTED -> "TEAR_DOWN_REASON_VOPS_NOT_SUPPORTED";
+ case TEAR_DOWN_REASON_DEFAULT_DATA_UNSELECTED ->
+ "TEAR_DOWN_REASON_DEFAULT_DATA_UNSELECTED";
+ case TEAR_DOWN_REASON_NOT_IN_SERVICE -> "TEAR_DOWN_REASON_NOT_IN_SERVICE";
+ case TEAR_DOWN_REASON_DATA_CONFIG_NOT_READY -> "TEAR_DOWN_REASON_DATA_CONFIG_NOT_READY";
+ case TEAR_DOWN_REASON_PENDING_TEAR_DOWN_ALL -> "TEAR_DOWN_REASON_PENDING_TEAR_DOWN_ALL";
+ case TEAR_DOWN_REASON_NO_SUITABLE_DATA_PROFILE ->
+ "TEAR_DOWN_REASON_NO_SUITABLE_DATA_PROFILE";
+ case TEAR_DOWN_REASON_CDMA_EMERGENCY_CALLBACK_MODE ->
+ "TEAR_DOWN_REASON_CDMA_EMERGENCY_CALLBACK_MODE";
+ case TEAR_DOWN_REASON_RETRY_SCHEDULED -> "TEAR_DOWN_REASON_RETRY_SCHEDULED";
+ case TEAR_DOWN_REASON_DATA_THROTTLED -> "TEAR_DOWN_REASON_DATA_THROTTLED";
+ case TEAR_DOWN_REASON_DATA_PROFILE_INVALID -> "TEAR_DOWN_REASON_DATA_PROFILE_INVALID";
+ case TEAR_DOWN_REASON_DATA_PROFILE_NOT_PREFERRED ->
+ "TEAR_DOWN_REASON_DATA_PROFILE_NOT_PREFERRED";
+ case TEAR_DOWN_REASON_NOT_ALLOWED_BY_POLICY -> "TEAR_DOWN_REASON_NOT_ALLOWED_BY_POLICY";
+ case TEAR_DOWN_REASON_ILLEGAL_STATE -> "TEAR_DOWN_REASON_ILLEGAL_STATE";
+ case TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK ->
+ "TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK";
+ case TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED ->
+ "TEAR_DOWN_REASON_PREFERRED_DATA_SWITCHED";
+ case TEAR_DOWN_REASON_DATA_LIMIT_REACHED -> "TEAR_DOWN_REASON_DATA_LIMIT_REACHED";
+ case TEAR_DOWN_REASON_DATA_NETWORK_TRANSPORT_NOT_ALLOWED ->
+ "TEAR_DOWN_REASON_DATA_NETWORK_TRANSPORT_NOT_ALLOWED";
+ default -> "UNKNOWN(" + reason + ")";
+ };
}
/**
@@ -3801,65 +3933,43 @@
* @param event The event
* @return The event in string format.
*/
- private static @NonNull String eventToString(int event) {
- switch (event) {
- case EVENT_DATA_CONFIG_UPDATED:
- return "EVENT_DATA_CONFIG_UPDATED";
- case EVENT_ATTACH_NETWORK_REQUEST:
- return "EVENT_ATTACH_NETWORK_REQUEST";
- case EVENT_DETACH_NETWORK_REQUEST:
- return "EVENT_DETACH_NETWORK_REQUEST";
- case EVENT_RADIO_NOT_AVAILABLE:
- return "EVENT_RADIO_NOT_AVAILABLE";
- case EVENT_ALLOCATE_PDU_SESSION_ID_RESPONSE:
- return "EVENT_ALLOCATE_PDU_SESSION_ID_RESPONSE";
- case EVENT_SETUP_DATA_NETWORK_RESPONSE:
- return "EVENT_SETUP_DATA_NETWORK_RESPONSE";
- case EVENT_TEAR_DOWN_NETWORK:
- return "EVENT_TEAR_DOWN_NETWORK";
- case EVENT_DATA_STATE_CHANGED:
- return "EVENT_DATA_STATE_CHANGED";
- case EVENT_SERVICE_STATE_CHANGED:
- return "EVENT_DATA_NETWORK_TYPE_REG_STATE_CHANGED";
- case EVENT_DETACH_ALL_NETWORK_REQUESTS:
- return "EVENT_DETACH_ALL_NETWORK_REQUESTS";
- case EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED:
- return "EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED";
- case EVENT_DISPLAY_INFO_CHANGED:
- return "EVENT_DISPLAY_INFO_CHANGED";
- case EVENT_HANDOVER_RESPONSE:
- return "EVENT_HANDOVER_RESPONSE";
- case EVENT_SUBSCRIPTION_PLAN_OVERRIDE:
- return "EVENT_SUBSCRIPTION_PLAN_OVERRIDE";
- case EVENT_PCO_DATA_RECEIVED:
- return "EVENT_PCO_DATA_RECEIVED";
- case EVENT_CARRIER_PRIVILEGED_UIDS_CHANGED:
- return "EVENT_CARRIER_PRIVILEGED_UIDS_CHANGED";
- case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE:
- return "EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE";
- case EVENT_STUCK_IN_TRANSIENT_STATE:
- return "EVENT_STUCK_IN_TRANSIENT_STATE";
- case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET:
- return "EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET";
- case EVENT_VOICE_CALL_STARTED:
- return "EVENT_VOICE_CALL_STARTED";
- case EVENT_VOICE_CALL_ENDED:
- return "EVENT_VOICE_CALL_ENDED";
- case EVENT_CSS_INDICATOR_CHANGED:
- return "EVENT_CSS_INDICATOR_CHANGED";
- case EVENT_NOTIFY_HANDOVER_STARTED:
- return "EVENT_NOTIFY_HANDOVER_STARTED";
- case EVENT_NOTIFY_HANDOVER_STARTED_RESPONSE:
- return "EVENT_NOTIFY_HANDOVER_STARTED_RESPONSE";
- case EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE:
- return "EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE";
- case EVENT_DATA_NETWORK_VALIDATION_REQUESTED:
- return "EVENT_DATA_NETWORK_VALIDATION_REQUESTED";
- case EVENT_DATA_NETWORK_VALIDATION_RESPONSE:
- return "EVENT_DATA_NETWORK_VALIDATION_RESPONSE";
- default:
- return "Unknown(" + event + ")";
- }
+ @NonNull
+ private static String eventToString(int event) {
+ return switch (event) {
+ case EVENT_DATA_CONFIG_UPDATED -> "EVENT_DATA_CONFIG_UPDATED";
+ case EVENT_ATTACH_NETWORK_REQUEST -> "EVENT_ATTACH_NETWORK_REQUEST";
+ case EVENT_DETACH_NETWORK_REQUEST -> "EVENT_DETACH_NETWORK_REQUEST";
+ case EVENT_RADIO_NOT_AVAILABLE -> "EVENT_RADIO_NOT_AVAILABLE";
+ case EVENT_ALLOCATE_PDU_SESSION_ID_RESPONSE -> "EVENT_ALLOCATE_PDU_SESSION_ID_RESPONSE";
+ case EVENT_SETUP_DATA_NETWORK_RESPONSE -> "EVENT_SETUP_DATA_NETWORK_RESPONSE";
+ case EVENT_TEAR_DOWN_NETWORK -> "EVENT_TEAR_DOWN_NETWORK";
+ case EVENT_DATA_STATE_CHANGED -> "EVENT_DATA_STATE_CHANGED";
+ case EVENT_SERVICE_STATE_CHANGED -> "EVENT_DATA_NETWORK_TYPE_REG_STATE_CHANGED";
+ case EVENT_DETACH_ALL_NETWORK_REQUESTS -> "EVENT_DETACH_ALL_NETWORK_REQUESTS";
+ case EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED ->
+ "EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED";
+ case EVENT_CANCEL_HANDOVER_NO_RESPONSE -> "EVENT_CANCEL_HANDOVER_NO_RESPONSE";
+ case EVENT_DISPLAY_INFO_CHANGED -> "EVENT_DISPLAY_INFO_CHANGED";
+ case EVENT_HANDOVER_RESPONSE -> "EVENT_HANDOVER_RESPONSE";
+ case EVENT_SUBSCRIPTION_PLAN_OVERRIDE -> "EVENT_SUBSCRIPTION_PLAN_OVERRIDE";
+ case EVENT_PCO_DATA_RECEIVED -> "EVENT_PCO_DATA_RECEIVED";
+ case EVENT_CARRIER_PRIVILEGED_UIDS_CHANGED -> "EVENT_CARRIER_PRIVILEGED_UIDS_CHANGED";
+ case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE -> "EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE";
+ case EVENT_STUCK_IN_TRANSIENT_STATE -> "EVENT_STUCK_IN_TRANSIENT_STATE";
+ case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET ->
+ "EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET";
+ case EVENT_VOICE_CALL_STARTED -> "EVENT_VOICE_CALL_STARTED";
+ case EVENT_VOICE_CALL_ENDED -> "EVENT_VOICE_CALL_ENDED";
+ case EVENT_CSS_INDICATOR_CHANGED -> "EVENT_CSS_INDICATOR_CHANGED";
+ case EVENT_NOTIFY_HANDOVER_STARTED -> "EVENT_NOTIFY_HANDOVER_STARTED";
+ case EVENT_NOTIFY_HANDOVER_STARTED_RESPONSE -> "EVENT_NOTIFY_HANDOVER_STARTED_RESPONSE";
+ case EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE ->
+ "EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE";
+ case EVENT_DATA_NETWORK_VALIDATION_REQUESTED ->
+ "EVENT_DATA_NETWORK_VALIDATION_REQUESTED";
+ case EVENT_DATA_NETWORK_VALIDATION_RESPONSE -> "EVENT_DATA_NETWORK_VALIDATION_RESPONSE";
+ default -> "Unknown(" + event + ")";
+ };
}
@Override
@@ -3872,7 +3982,8 @@
/**
* @return The short name of the data network (e.g. DN-C-1)
*/
- public @NonNull String name() {
+ @NonNull
+ public String name() {
return mLogTag;
}
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index 70d3b23..30172db 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.data;
import android.annotation.CallbackExecutor;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -38,6 +39,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.SystemClock;
import android.telecom.TelecomManager;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
@@ -90,6 +92,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.SlidingWindowEventCounter;
+import com.android.internal.telephony.TelephonyCapabilities;
import com.android.internal.telephony.TelephonyComponentFactory;
import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback;
import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
@@ -244,32 +247,46 @@
TimeUnit.SECONDS.toMillis(1);
/**
- * The delay in milliseconds to re-evaluate existing data networks for bootstrap sim data usage
- * limit.
+ * The guard timer in milliseconds to limit querying the data usage api stats frequently
*/
- private static final long REEVALUATE_BOOTSTRAP_SIM_DATA_USAGE_MILLIS =
- TimeUnit.SECONDS.toMillis(60);
+ private static final long GUARD_TIMER_INTERVAL_TO_QUERY_DATA_USAGE_API_STATS_MILLIS =
+ TimeUnit.SECONDS.toMillis(1);
/**
* bootstrap sim total data usage bytes
*/
private long mBootStrapSimTotalDataUsageBytes = 0L;
+ /**
+ * bootstrap sim last data usage query time
+ */
+ @ElapsedRealtimeLong
+ private long mBootstrapSimLastDataUsageQueryTime = 0L;
+
private final Phone mPhone;
private final String mLogTag;
private final LocalLog mLocalLog = new LocalLog(128);
- private final @NonNull DataConfigManager mDataConfigManager;
- private final @NonNull DataSettingsManager mDataSettingsManager;
- private final @NonNull DataProfileManager mDataProfileManager;
- private final @NonNull DataStallRecoveryManager mDataStallRecoveryManager;
- private final @NonNull AccessNetworksManager mAccessNetworksManager;
- private final @NonNull DataRetryManager mDataRetryManager;
- private final @NonNull ImsManager mImsManager;
- private final @NonNull TelecomManager mTelecomManager;
- private final @NonNull NetworkPolicyManager mNetworkPolicyManager;
- private final @NonNull SparseArray<DataServiceManager> mDataServiceManagers =
- new SparseArray<>();
+ @NonNull
+ private final DataConfigManager mDataConfigManager;
+ @NonNull
+ private final DataSettingsManager mDataSettingsManager;
+ @NonNull
+ private final DataProfileManager mDataProfileManager;
+ @NonNull
+ private final DataStallRecoveryManager mDataStallRecoveryManager;
+ @NonNull
+ private final AccessNetworksManager mAccessNetworksManager;
+ @NonNull
+ private final DataRetryManager mDataRetryManager;
+ @NonNull
+ private final ImsManager mImsManager;
+ @NonNull
+ private final TelecomManager mTelecomManager;
+ @NonNull
+ private final NetworkPolicyManager mNetworkPolicyManager;
+ @NonNull
+ private final SparseArray<DataServiceManager> mDataServiceManagers = new SparseArray<>();
/** The subscription index associated with this data network controller. */
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -277,35 +294,41 @@
/** The current service state of the device. */
// Note that keeping a copy here instead of directly using ServiceStateTracker.getServiceState()
// is intended for detecting the delta.
- private @NonNull ServiceState mServiceState;
+ @NonNull
+ private ServiceState mServiceState;
/** The list of SubscriptionPlans, updated when initialized and when plans are changed. */
- private final @NonNull List<SubscriptionPlan> mSubscriptionPlans = new ArrayList<>();
+ @NonNull
+ private final List<SubscriptionPlan> mSubscriptionPlans = new ArrayList<>();
/**
* The set of network types an unmetered override applies to, set by onSubscriptionOverride
* and cleared when the device is rebooted or the override expires.
*/
- private final @NonNull @NetworkType Set<Integer> mUnmeteredOverrideNetworkTypes =
- new ArraySet<>();
+ @NonNull
+ @NetworkType
+ private final Set<Integer> mUnmeteredOverrideNetworkTypes = new ArraySet<>();
/**
* The set of network types a congested override applies to, set by onSubscriptionOverride
* and cleared when the device is rebooted or the override expires.
*/
- private final @NonNull @NetworkType Set<Integer> mCongestedOverrideNetworkTypes =
- new ArraySet<>();
+ @NonNull
+ @NetworkType
+ private final Set<Integer> mCongestedOverrideNetworkTypes = new ArraySet<>();
/**
* The list of all network requests.
*/
- private final @NonNull NetworkRequestList mAllNetworkRequestList = new NetworkRequestList();
+ @NonNull
+ private final NetworkRequestList mAllNetworkRequestList = new NetworkRequestList();
/**
* The current data network list, including the ones that are connected, connecting, or
* disconnecting.
*/
- private final @NonNull List<DataNetwork> mDataNetworkList = new ArrayList<>();
+ @NonNull
+ private final List<DataNetwork> mDataNetworkList = new ArrayList<>();
/** {@code true} indicating at least one data network exists. */
private boolean mAnyDataNetworkExisting;
@@ -313,27 +336,33 @@
/**
* Contain the last 10 data networks that were connected. This is for debugging purposes only.
*/
- private final @NonNull List<DataNetwork> mPreviousConnectedDataNetworkList = new ArrayList<>();
+ @NonNull
+ private final List<DataNetwork> mPreviousConnectedDataNetworkList = new ArrayList<>();
/**
* The internet data network state. Note that this is the best effort if more than one
* data network supports internet.
*/
- private @DataState int mInternetDataNetworkState = TelephonyManager.DATA_DISCONNECTED;
+ @DataState
+ private int mInternetDataNetworkState = TelephonyManager.DATA_DISCONNECTED;
/** All the current connected/handover internet networks. */
- @NonNull private Set<DataNetwork> mConnectedInternetNetworks = new HashSet<>();
+ @NonNull
+ private Set<DataNetwork> mConnectedInternetNetworks = new HashSet<>();
/**
* The IMS data network state. For now this is just for debugging purposes.
*/
- private @DataState int mImsDataNetworkState = TelephonyManager.DATA_DISCONNECTED;
+ @DataState
+ private int mImsDataNetworkState = TelephonyManager.DATA_DISCONNECTED;
/** Overall aggregated link status from internet data networks. */
- private @LinkStatus int mInternetLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN;
+ @LinkStatus
+ private int mInternetLinkStatus = DataCallResponse.LINK_STATUS_UNKNOWN;
/** Data network controller callbacks. */
- private final @NonNull Set<DataNetworkControllerCallback> mDataNetworkControllerCallbacks =
+ @NonNull
+ private final Set<DataNetworkControllerCallback> mDataNetworkControllerCallbacks =
new ArraySet<>();
/** Indicates if packet switch data is restricted by the cellular network. */
@@ -349,54 +378,59 @@
* Indicates if the data services are bound. Key if the transport type, and value is the boolean
* indicating service is bound or not.
*/
- private final @NonNull SparseBooleanArray mDataServiceBound = new SparseBooleanArray();
+ @NonNull
+ private final SparseBooleanArray mDataServiceBound = new SparseBooleanArray();
/** SIM state. */
- private @SimState int mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
+ @SimState
+ private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
/** Data activity. */
- private @DataActivityType int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
+ @DataActivityType
+ private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
/**
* IMS state callbacks. Key is the IMS feature, value is the callback.
*/
- private final @NonNull SparseArray<ImsStateCallback> mImsStateCallbacks = new SparseArray<>();
+ @NonNull
+ private final SparseArray<ImsStateCallback> mImsStateCallbacks = new SparseArray<>();
/** Registered IMS features. Unregistered IMS features are removed from the set. */
- private final @NonNull Set<Integer> mRegisteredImsFeatures = new ArraySet<>();
+ @NonNull
+ private final Set<Integer> mRegisteredImsFeatures = new ArraySet<>();
/** IMS feature package names. Key is the IMS feature, value is the package name. */
- private final @NonNull SparseArray<String> mImsFeaturePackageName = new SparseArray<>();
+ @NonNull
+ private final SparseArray<String> mImsFeaturePackageName = new SparseArray<>();
/**
* Networks that are pending IMS de-registration. Key is the data network, value is the function
* to tear down the network.
*/
- private final @NonNull Map<DataNetwork, Runnable> mPendingImsDeregDataNetworks =
- new ArrayMap<>();
+ @NonNull
+ private final Map<DataNetwork, Runnable> mPendingImsDeregDataNetworks = new ArrayMap<>();
/**
* IMS feature registration callback. The key is the IMS feature, the value is the registration
* callback. When new SIM inserted, the old callbacks associated with the old subscription index
* will be unregistered.
*/
- private final @NonNull SparseArray<RegistrationManager.RegistrationCallback>
+ @NonNull
+ private final SparseArray<RegistrationManager.RegistrationCallback>
mImsFeatureRegistrationCallbacks = new SparseArray<>();
/** The counter to detect back to back release/request IMS network. */
- private @NonNull SlidingWindowEventCounter mImsThrottleCounter;
+ @NonNull
+ private SlidingWindowEventCounter mImsThrottleCounter;
/** Event counter for unwanted network within time window, is used to trigger anomaly report. */
- private @NonNull SlidingWindowEventCounter mNetworkUnwantedCounter;
+ @NonNull
+ private SlidingWindowEventCounter mNetworkUnwantedCounter;
/** Event counter for WLAN setup data failure within time window to trigger anomaly report. */
- private @NonNull SlidingWindowEventCounter mSetupDataCallWlanFailureCounter;
+ @NonNull
+ private SlidingWindowEventCounter mSetupDataCallWlanFailureCounter;
/** Event counter for WWAN setup data failure within time window to trigger anomaly report. */
- private @NonNull SlidingWindowEventCounter mSetupDataCallWwanFailureCounter;
-
- /**
- * {@code true} if {@link #tearDownAllDataNetworks(int)} was invoked and waiting for all
- * networks torn down.
- */
- private boolean mPendingTearDownAllNetworks = false;
+ @NonNull
+ private SlidingWindowEventCounter mSetupDataCallWwanFailureCounter;
/**
* The capabilities of the latest released IMS request. To detect back to back release/request
@@ -407,7 +441,8 @@
/** True after try to release an IMS network; False after try to request an IMS network. */
private boolean mLastImsOperationIsRelease;
- private final @NonNull FeatureFlags mFeatureFlags;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
/** The broadcast receiver. */
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@@ -428,7 +463,7 @@
};
private boolean hasCalling() {
- if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
return mPhone.getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_CALLING);
}
@@ -436,7 +471,7 @@
/**
* The sorted network request list by priority. The highest priority network request stays at
* the head of the list. The highest priority is 100, the lowest is 0.
- *
+ * <p>
* Note this list is not thread-safe. Do not access the list from different threads.
*/
@VisibleForTesting
@@ -519,7 +554,8 @@
* @return The first network request in the list that contains all the provided
* capabilities.
*/
- public @Nullable TelephonyNetworkRequest get(@NonNull @NetCapability int[] netCaps) {
+ @Nullable
+ public TelephonyNetworkRequest get(@NonNull @NetCapability int[] netCaps) {
int index = 0;
while (index < size()) {
TelephonyNetworkRequest networkRequest = get(index);
@@ -528,7 +564,7 @@
.boxed()
.collect(Collectors.toSet())
.containsAll(Arrays.stream(netCaps).boxed()
- .collect(Collectors.toList()))) {
+ .toList())) {
return networkRequest;
}
index++;
@@ -559,6 +595,16 @@
}
/**
+ * Print "capabilities - connectivity transport". e.g. INTERNET|NOT_RESTRICTED-SATELLITE
+ */
+ @NonNull
+ public String toStringSimplified() {
+ return size() > 0 ? DataUtils.networkCapabilitiesToString(get(0).getCapabilities())
+ + "-" + DataUtils.connectivityTransportsToString(get(0).getTransportTypes())
+ : "";
+ }
+
+ /**
* Dump the network request list.
*
* @param pw print writer.
@@ -696,19 +742,26 @@
private static final String RULE_TAG_ROAMING = "roaming";
/** Handover rule type. */
- public final @HandoverRuleType int type;
+ @HandoverRuleType
+ public final int type;
/** The applicable source access networks for handover. */
- public final @NonNull @RadioAccessNetworkType Set<Integer> sourceAccessNetworks;
+ @NonNull
+ @RadioAccessNetworkType
+ public final Set<Integer> sourceAccessNetworks;
/** The applicable target access networks for handover. */
- public final @NonNull @RadioAccessNetworkType Set<Integer> targetAccessNetworks;
+ @NonNull
+ @RadioAccessNetworkType
+ public final Set<Integer> targetAccessNetworks;
/**
* The network capabilities to any of which this handover rule applies.
* If is empty, then capability is ignored as a rule matcher.
*/
- public final @NonNull @NetCapability Set<Integer> networkCapabilities;
+ @NonNull
+ @NetCapability
+ public final Set<Integer> networkCapabilities;
/** {@code true} indicates this policy is only applicable when the device is roaming. */
public final boolean isOnlyForRoaming;
@@ -1185,7 +1238,7 @@
mSubscriptionPlans.clear();
mSubscriptionPlans.addAll(Arrays.asList(plans));
mDataNetworkControllerCallbacks.forEach(cb -> cb.invokeFromExecutor(
- () -> cb.onSubscriptionPlanOverride()));
+ cb::onSubscriptionPlanOverride));
break;
case EVENT_SUBSCRIPTION_OVERRIDE:
int overrideMask = msg.arg1;
@@ -1205,7 +1258,7 @@
}
}
mDataNetworkControllerCallbacks.forEach(cb -> cb.invokeFromExecutor(
- () -> cb.onSubscriptionPlanOverride()));
+ cb::onSubscriptionPlanOverride));
} else if (overrideMask == NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED) {
log("Congested subscription override: override=" + override
+ ", networkTypes=" + Arrays.stream(networkTypes)
@@ -1219,7 +1272,7 @@
}
}
mDataNetworkControllerCallbacks.forEach(cb -> cb.invokeFromExecutor(
- () -> cb.onSubscriptionPlanOverride()));
+ cb::onSubscriptionPlanOverride));
} else {
loge("Unknown override mask: " + overrideMask);
}
@@ -1358,28 +1411,6 @@
// When reaching here, it means this data network can satisfy all the network requests.
logv("Found a compatible data network " + dataNetwork + ". Attaching "
+ requestList);
-
- // If WLAN preferred, see whether a more suitable data profile shall be used to satisfy
- // a short-lived request that doesn't perform handover.
- int capability = requestList.getFirst().getApnTypeNetworkCapability();
- int preferredTransport = mAccessNetworksManager
- .getPreferredTransportByNetworkCapability(capability);
- if (capability == NetworkCapabilities.NET_CAPABILITY_MMS
- && preferredTransport != dataNetwork.getTransport()
- && preferredTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
- DataProfile candidate = mDataProfileManager
- .getDataProfileForNetworkRequest(requestList.getFirst(),
- TelephonyManager.NETWORK_TYPE_IWLAN,
- mServiceState.isUsingNonTerrestrialNetwork(),
- isEsimBootStrapProvisioningActivated(),
- false/*ignorePermanentFailure*/);
- if (candidate != null && !dataNetwork.getDataProfile().equals(candidate)) {
- logv("But skipped because found better data profile " + candidate
- + DataUtils.networkCapabilityToString(capability) + " preferred on "
- + AccessNetworkConstants.transportTypeToString(preferredTransport));
- continue;
- }
- }
return dataNetwork.attachNetworkRequests(requestList);
}
return false;
@@ -1451,11 +1482,23 @@
* still allowed in this case.
*/
public boolean isInternetDataAllowed(boolean ignoreExistingNetworks) {
+ return !getInternetEvaluation(ignoreExistingNetworks).containsDisallowedReasons();
+ }
+
+ /**
+ * @param ignoreExistingNetworks {@code true} to skip the existing network check.
+ * @return The internet evaluation result.
+ * For example, if SIM is absent, or airplane mode is on, then data is NOT allowed.
+ * This API does not reflect the currently internet data network status. It's possible there is
+ * no internet data due to weak cellular signal or network side issue, but internet data is
+ * still allowed in this case.
+ */
+ @NonNull
+ public DataEvaluation getInternetEvaluation(boolean ignoreExistingNetworks) {
TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
// If we don't skip checking existing network, then we should check If one of the
// existing networks can satisfy the internet request, then internet is allowed.
if ((!mFeatureFlags.ignoreExistingNetworksForInternetAllowedChecking()
@@ -1463,7 +1506,7 @@
&& mDataNetworkList.stream().anyMatch(
dataNetwork -> internetRequest.canBeSatisfiedBy(
dataNetwork.getNetworkCapabilities()))) {
- return true;
+ return new DataEvaluation(DataEvaluationReason.EXTERNAL_QUERY);
}
// If no existing network can satisfy the request, then check if we can possibly setup
@@ -1471,17 +1514,19 @@
DataEvaluation evaluation = evaluateNetworkRequest(internetRequest,
DataEvaluationReason.EXTERNAL_QUERY);
- if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)) {
+ if (evaluation.containsOnly(DataDisallowedReason.ONLY_ALLOWED_SINGLE_NETWORK)
+ && internetRequest.getPriority() > mDataNetworkList.stream()
+ .map(DataNetwork::getPriority)
+ .max(Comparator.comparing(Integer::valueOf))
+ .orElse(0)) {
// If the only failed reason is only single network allowed, then check if the request
// can trump the current network.
- return internetRequest.getPriority() > mDataNetworkList.stream()
- .map(DataNetwork::getPriority)
- .max(Comparator.comparing(Integer::valueOf))
- .orElse(0);
+ evaluation.addDataAllowedReason(DataAllowedReason.NORMAL);
}
- return !evaluation.containsDisallowedReasons();
+ return evaluation;
}
+
/**
* @return {@code true} if internet is unmetered.
*/
@@ -1510,12 +1555,12 @@
* @return List of the reasons why internet data is not allowed. An empty list if internet
* is allowed.
*/
- public @NonNull List<DataDisallowedReason> getInternetDataDisallowedReasons() {
+ @NonNull
+ public List<DataDisallowedReason> getInternetDataDisallowedReasons() {
TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataEvaluation evaluation = evaluateNetworkRequest(internetRequest,
DataEvaluationReason.EXTERNAL_QUERY);
return evaluation.getDataDisallowedReasons();
@@ -1529,18 +1574,26 @@
* @param reason The reason for evaluation.
* @return The data evaluation result.
*/
- private @NonNull DataEvaluation evaluateNetworkRequest(
+ @NonNull
+ private DataEvaluation evaluateNetworkRequest(
@NonNull TelephonyNetworkRequest networkRequest, DataEvaluationReason reason) {
DataEvaluation evaluation = new DataEvaluation(reason);
int transport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
networkRequest.getApnTypeNetworkCapability());
+ // Check if the request can be satisfied by cellular network or satellite network.
+ if (mFeatureFlags.satelliteInternet()
+ && !canConnectivityTransportSatisfyNetworkRequest(networkRequest, transport)) {
+ evaluation.addDataDisallowedReason(
+ DataDisallowedReason.DATA_NETWORK_TRANSPORT_NOT_ALLOWED);
+ }
+
// Bypass all checks for emergency network request.
if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) {
DataProfile emergencyProfile = mDataProfileManager.getDataProfileForNetworkRequest(
networkRequest, getDataNetworkType(transport),
mServiceState.isUsingNonTerrestrialNetwork(),
- isEsimBootStrapProvisioningActivated(), true);
+ false /*isEsimBootStrapProvisioning*/, true);
// Check if the profile is being throttled.
if (mDataConfigManager.shouldHonorRetryTimerForEmergencyNetworkRequest()
@@ -1549,14 +1602,13 @@
evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_THROTTLED);
log("Emergency network request is throttled by the previous setup data "
+ "call response.");
- log(evaluation.toString());
- networkRequest.setEvaluation(evaluation);
- return evaluation;
}
- evaluation.addDataAllowedReason(DataAllowedReason.EMERGENCY_REQUEST);
- if (emergencyProfile != null) {
- evaluation.setCandidateDataProfile(emergencyProfile);
+ if (!evaluation.containsDisallowedReasons()) {
+ evaluation.addDataAllowedReason(DataAllowedReason.EMERGENCY_REQUEST);
+ if (emergencyProfile != null) {
+ evaluation.setCandidateDataProfile(emergencyProfile);
+ }
}
networkRequest.setEvaluation(evaluation);
log(evaluation.toString());
@@ -1617,7 +1669,7 @@
}
// Check if there are pending tear down all networks request.
- if (mPendingTearDownAllNetworks) {
+ if (mPhone.getServiceStateTracker().isPendingRadioPowerOffAfterDataOff()) {
evaluation.addDataDisallowedReason(DataDisallowedReason.PENDING_TEAR_DOWN_ALL);
}
@@ -1645,11 +1697,6 @@
evaluation.addDataDisallowedReason(DataDisallowedReason.CDMA_EMERGENCY_CALLBACK_MODE);
}
- // Check whether data is disallowed while using satellite
- if (isDataDisallowedDueToSatellite(networkRequest.getCapabilities())) {
- evaluation.addDataDisallowedReason(DataDisallowedReason.SERVICE_OPTION_NOT_SUPPORTED);
- }
-
// Check if only one data network is allowed.
if (isOnlySingleDataNetworkAllowed(transport)
&& !hasCapabilityExemptsFromSinglePdnRule(networkRequest.getCapabilities())) {
@@ -1746,7 +1793,7 @@
networkRequest.setEvaluation(evaluation);
// EXTERNAL_QUERY generates too many log spam.
if (reason != DataEvaluationReason.EXTERNAL_QUERY) {
- log(evaluation.toString() + ", network type="
+ log(evaluation + ", network type="
+ TelephonyManager.getNetworkTypeName(getDataNetworkType(transport))
+ ", reg state="
+ NetworkRegistrationInfo.registrationStateToString(
@@ -1761,7 +1808,8 @@
* - At evaluation network request and evaluation data network determines, if
* bootstrap sim current data usage reached bootstrap sim max data limit allowed set
* at {@link DataConfigManager#getEsimBootStrapMaxDataLimitBytes()}
- * - Query the current data usage at {@link #getDataUsage()}
+ * - Query the current data usage at {@link #getDataUsage()}, if last data usage query guarding
+ * interval as expired.
*
* @return true, if bootstrap sim data limit is reached
* else false, if bootstrap sim max data limit allowed set is -1(Unlimited) or current
@@ -1776,13 +1824,15 @@
return false;
}
- log("current bootstrap sim data Usage: " + mBootStrapSimTotalDataUsageBytes);
- if (mBootStrapSimTotalDataUsageBytes >= esimBootStrapMaxDataLimitBytes) {
- return true;
- } else {
+ if (mBootStrapSimTotalDataUsageBytes < esimBootStrapMaxDataLimitBytes
+ && (mBootstrapSimLastDataUsageQueryTime == 0
+ || SystemClock.elapsedRealtime() - mBootstrapSimLastDataUsageQueryTime
+ > GUARD_TIMER_INTERVAL_TO_QUERY_DATA_USAGE_API_STATS_MILLIS)) {
mBootStrapSimTotalDataUsageBytes = getDataUsage();
- return mBootStrapSimTotalDataUsageBytes >= esimBootStrapMaxDataLimitBytes;
+ log("current bootstrap sim data usage: " + mBootStrapSimTotalDataUsageBytes);
+ mBootstrapSimLastDataUsageQueryTime = SystemClock.elapsedRealtime();
}
+ return mBootStrapSimTotalDataUsageBytes >= esimBootStrapMaxDataLimitBytes;
}
/**
@@ -1802,6 +1852,8 @@
if (!TextUtils.isEmpty(subscriberId)) {
builder.setSubscriberIds(Set.of(subscriberId));
+ // Consider data usage calculation of only metered capabilities / data network
+ builder.setMeteredness(android.net.NetworkStats.METERED_YES);
NetworkTemplate template = builder.build();
final NetworkStats.Bucket ret = networkStatsManager
.querySummaryForDevice(template, 0L, System.currentTimeMillis());
@@ -1815,14 +1867,15 @@
* @return The grouped unsatisfied network requests. The network requests that have the same
* network capabilities is grouped into one {@link NetworkRequestList}.
*/
- private @NonNull List<NetworkRequestList> getGroupedUnsatisfiedNetworkRequests() {
+ @NonNull
+ private List<NetworkRequestList> getGroupedUnsatisfiedNetworkRequests() {
NetworkRequestList networkRequestList = new NetworkRequestList();
for (TelephonyNetworkRequest networkRequest : mAllNetworkRequestList) {
if (networkRequest.getState() == TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED) {
networkRequestList.add(networkRequest);
}
}
- return DataUtils.getGroupedNetworkRequestList(networkRequestList);
+ return DataUtils.getGroupedNetworkRequestList(networkRequestList, mFeatureFlags);
}
/**
@@ -1836,8 +1889,7 @@
log("Re-evaluating " + networkRequestLists.stream().mapToInt(List::size).sum()
+ " unsatisfied network requests in " + networkRequestLists.size()
+ " groups, " + networkRequestLists.stream().map(
- requestList -> DataUtils.networkCapabilitiesToString(
- requestList.get(0).getCapabilities()))
+ NetworkRequestList::toStringSimplified)
.collect(Collectors.joining(", ")) + " due to " + reason);
// Second, see if any existing network can satisfy those network requests.
@@ -1870,7 +1922,8 @@
*
* @return The data evaluation result.
*/
- private @NonNull DataEvaluation evaluateDataNetwork(@NonNull DataNetwork dataNetwork,
+ @NonNull
+ private DataEvaluation evaluateDataNetwork(@NonNull DataNetwork dataNetwork,
@NonNull DataEvaluationReason reason) {
DataEvaluation evaluation = new DataEvaluation(reason);
// Bypass all checks for emergency data network.
@@ -1891,10 +1944,16 @@
evaluation.addDataDisallowedReason(DataDisallowedReason.CDMA_EMERGENCY_CALLBACK_MODE);
}
- // Check whether data is disallowed while using satellite
- if (isDataDisallowedDueToSatellite(dataNetwork.getNetworkCapabilities()
- .getCapabilities())) {
- evaluation.addDataDisallowedReason(DataDisallowedReason.SERVICE_OPTION_NOT_SUPPORTED);
+ // If the network is satellite, then the network must be restricted.
+ if (mFeatureFlags.satelliteInternet()) {
+ // The IWLAN data network should remain intact even when satellite is connected.
+ if (dataNetwork.getTransport() != AccessNetworkConstants.TRANSPORT_TYPE_WLAN
+ && mServiceState.isUsingNonTerrestrialNetwork() != dataNetwork.isSatellite()) {
+ // Since we don't support satellite/cellular network handover, we should always
+ // tear down the network when transport changes.
+ evaluation.addDataDisallowedReason(
+ DataDisallowedReason.DATA_NETWORK_TRANSPORT_NOT_ALLOWED);
+ }
}
// Check whether data limit reached for bootstrap sim, else re-evaluate based on the timer
@@ -1908,7 +1967,7 @@
if (!hasMessages(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS)) {
sendMessageDelayed(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
DataEvaluationReason.CHECK_DATA_USAGE),
- REEVALUATE_BOOTSTRAP_SIM_DATA_USAGE_MILLIS);
+ mDataConfigManager.getReevaluateBootstrapSimDataUsageMillis());
} else {
log("skip scheduling evaluating existing data networks since already"
+ "scheduled");
@@ -2082,15 +2141,97 @@
}
/**
- * tethering and enterprise capabilities are not respected as restricted requests. For a request
- * with these capabilities, any soft disallowed reasons are honored.
+ * Check if the transport from connectivity service can satisfy the network request. Note the
+ * transport here is connectivity service's transport (Wifi, cellular, satellite, etc..), not
+ * the widely used {@link AccessNetworkConstants#TRANSPORT_TYPE_WLAN WLAN},
+ * {@link AccessNetworkConstants#TRANSPORT_TYPE_WWAN WWAN} transport in telephony.
+ *
+ * @param networkRequest Network request
+ * @param transport The preferred transport type for the request. The transport here is
+ * WWAN/WLAN.
+ * @return {@code true} if the connectivity transport can satisfy the network request, otherwise
+ * {@code false}.
+ */
+ private boolean canConnectivityTransportSatisfyNetworkRequest(
+ @NonNull TelephonyNetworkRequest networkRequest, @TransportType int transport) {
+ // Check if this is a IWLAN network request.
+ if (transport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
+ // If the request would result in bringing up network on IWLAN, then no
+ // need to check if the device is using satellite network.
+ return true;
+ }
+
+ // When the device is on satellite, only restricted/constrained network request can request
+ // network.
+ if (mServiceState.isUsingNonTerrestrialNetwork() && networkRequest.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
+ switch (mDataConfigManager.getSatelliteDataSupportMode()) {
+ case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED -> {
+ return false;
+ }
+ case CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED -> {
+ try {
+ if (networkRequest.hasCapability(DataUtils
+ .NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)) {
+ return false;
+ }
+ } catch (Exception ignored) { }
+ }
+ // default case CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL
+ }
+ }
+
+ // If the network request does not specify cellular or satellite, then it can be
+ // satisfied when the device is either on cellular ot satellite.
+ if (!networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && !networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)) {
+ return true;
+ }
+
+ // As a short term solution, allowing some networks to be always marked as cellular
+ // transport if certain capabilities are in the network request.
+ if (networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) && Arrays.stream(
+ networkRequest.getCapabilities())
+ .anyMatch(mDataConfigManager.getForcedCellularTransportCapabilities()::contains)) {
+ return true;
+ }
+
+ // If the network is cellular, then the request must specify cellular transport. Or if the
+ // the network is satellite, then the request must specify satellite transport and
+ // restricted.
+ return (mServiceState.isUsingNonTerrestrialNetwork()
+ && networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE))
+ || (!mServiceState.isUsingNonTerrestrialNetwork()
+ && networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR));
+ }
+
+ /**
+ * Check if a network request should be treated as a valid restricted network request that
+ * can bypass soft disallowed reasons, for example, mobile data off.
+ *
* @param networkRequest The network request to evaluate.
- * @return {@code true} if the request doesn't contain any exceptional capabilities, its
- * restricted capability, if any, is respected.
+ * @return {@code true} if the request can be considered as a valid restricted network request
+ * that can bypass any soft disallowed reasons, otherwise {@code false}.
*/
private boolean isValidRestrictedRequest(@NonNull TelephonyNetworkRequest networkRequest) {
- return !(networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE));
+
+ if (!mFeatureFlags.satelliteInternet()) {
+ return !(networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+ || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE));
+ } else {
+ // tethering, enterprise and mms with restricted capabilities always honor soft
+ // disallowed reasons and not respected as restricted request
+ if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
+ || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
+ || networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ return false;
+ }
+ // When the device is on satellite, internet with restricted capabilities always honor
+ // soft disallowed reasons and not respected as restricted request
+ return !(mServiceState.isUsingNonTerrestrialNetwork()
+ && networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+
+ }
}
/**
@@ -2124,7 +2265,8 @@
*
* @see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY
*/
- private @NonNull DataEvaluation evaluateDataNetworkHandover(@NonNull DataNetwork dataNetwork) {
+ @NonNull
+ private DataEvaluation evaluateDataNetworkHandover(@NonNull DataNetwork dataNetwork) {
DataEvaluation dataEvaluation = new DataEvaluation(DataEvaluationReason.DATA_HANDOVER);
if (!dataNetwork.isConnecting() && !dataNetwork.isConnected()) {
dataEvaluation.addDataDisallowedReason(DataDisallowedReason.ILLEGAL_STATE);
@@ -2182,10 +2324,7 @@
sourceNetworkType);
NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- boolean isWwanInService = false;
- if (nri != null && nri.isInService()) {
- isWwanInService = true;
- }
+ boolean isWwanInService = nri != null && nri.isInService();
// If WWAN is inService, use the real roaming state reported by modem instead of
// using the overridden roaming state, otherwise get last known roaming state stored
// in data network.
@@ -2247,7 +2386,8 @@
* {@link #evaluateDataNetwork(DataNetwork, DataEvaluationReason)}.
* @return The tear down reason.
*/
- private static @TearDownReason int getTearDownReason(@NonNull DataEvaluation dataEvaluation) {
+ @TearDownReason
+ private static int getTearDownReason(@NonNull DataEvaluation dataEvaluation) {
if (dataEvaluation.containsDisallowedReasons()) {
switch (dataEvaluation.getDataDisallowedReasons().get(0)) {
case DATA_DISABLED:
@@ -2300,6 +2440,8 @@
return DataNetwork.TEAR_DOWN_REASON_HANDOVER_FAILED;
case DATA_LIMIT_REACHED:
return DataNetwork.TEAR_DOWN_REASON_DATA_LIMIT_REACHED;
+ case DATA_NETWORK_TRANSPORT_NOT_ALLOWED:
+ return DataNetwork.TEAR_DOWN_REASON_DATA_NETWORK_TRANSPORT_NOT_ALLOWED;
}
}
return DataNetwork.TEAR_DOWN_REASON_NONE;
@@ -2446,14 +2588,14 @@
RegistrationManager.RegistrationCallback callback =
new RegistrationManager.RegistrationCallback() {
@Override
- public void onRegistered(ImsRegistrationAttributes attributes) {
+ public void onRegistered(@NonNull ImsRegistrationAttributes attributes) {
log("IMS " + DataUtils.imsFeatureToString(imsFeature)
+ " registered. Attributes=" + attributes);
mRegisteredImsFeatures.add(imsFeature);
}
@Override
- public void onUnregistered(ImsReasonInfo info) {
+ public void onUnregistered(@NonNull ImsReasonInfo info) {
log("IMS " + DataUtils.imsFeatureToString(imsFeature)
+ " deregistered. Info=" + info);
mRegisteredImsFeatures.remove(imsFeature);
@@ -2661,8 +2803,8 @@
* @param dataProfile The data profile.
* @return The network requests list.
*/
- private @NonNull NetworkRequestList findSatisfiableNetworkRequests(
- @NonNull DataProfile dataProfile) {
+ @NonNull
+ private NetworkRequestList findSatisfiableNetworkRequests(@NonNull DataProfile dataProfile) {
return new NetworkRequestList(mAllNetworkRequestList.stream()
.filter(request -> request.getState()
== TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED)
@@ -2839,7 +2981,6 @@
mDataNetworkList.remove(dataNetwork);
trackSetupDataCallFailure(dataNetwork.getTransport(), cause);
if (mAnyDataNetworkExisting && mDataNetworkList.isEmpty()) {
- mPendingTearDownAllNetworks = false;
mAnyDataNetworkExisting = false;
mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
() -> callback.onAnyDataNetworkExistingChanged(mAnyDataNetworkExisting)));
@@ -2940,7 +3081,7 @@
if (isEsimBootStrapProvisioningActivated()) {
sendMessageDelayed(obtainMessage(EVENT_REEVALUATE_EXISTING_DATA_NETWORKS,
DataEvaluationReason.CHECK_DATA_USAGE),
- REEVALUATE_BOOTSTRAP_SIM_DATA_USAGE_MILLIS);
+ mDataConfigManager.getReevaluateBootstrapSimDataUsageMillis());
}
}
@@ -2962,8 +3103,18 @@
List<NetworkRequestList> groupRequestLists = getGroupedUnsatisfiedNetworkRequests();
dataSetupRetryEntry.networkRequestList.stream()
.filter(request -> groupRequestLists.stream()
- .anyMatch(groupRequestList -> groupRequestList
- .get(request.getCapabilities()) != null))
+ .anyMatch(groupRequestList -> {
+ // The unsatisfied request has all the requested capabilities.
+ if (groupRequestList.get(request.getCapabilities()) == null) {
+ return false;
+ }
+ TelephonyNetworkRequest leading = groupRequestList.getFirst();
+ // The unsatisfied request covers all the requested transports.
+ return leading.getTransportTypes().length == 0
+ || request.getTransportTypes().length == 0
+ || Arrays.stream(request.getTransportTypes())
+ .allMatch(leading::hasTransport);
+ }))
.forEach(requestList::add);
}
if (requestList.isEmpty()) {
@@ -3107,7 +3258,13 @@
return;
}
- if (dataNetwork.isInternetSupported()) {
+ // Only track the networks that require validation.
+ // The criteria is base on NetworkMonitorUtils.java.
+ NetworkCapabilities capabilities = dataNetwork.getNetworkCapabilities();
+ if (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
+ && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)) {
if (status == NetworkAgent.VALIDATION_STATUS_NOT_VALID
&& (dataNetwork.getCurrentState() == null || dataNetwork.isDisconnected())) {
log("Ignoring invalid validation status for disconnected DataNetwork");
@@ -3164,7 +3321,6 @@
if (mAnyDataNetworkExisting && mDataNetworkList.isEmpty()) {
log("All data networks disconnected now.");
- mPendingTearDownAllNetworks = false;
mAnyDataNetworkExisting = false;
mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor(
() -> callback.onAnyDataNetworkExistingChanged(mAnyDataNetworkExisting)));
@@ -3590,7 +3746,7 @@
return true;
}
- if (!oldNri.isNonTerrestrialNetwork() && newNri.isNonTerrestrialNetwork()) {
+ if (oldNri.isNonTerrestrialNetwork() != newNri.isNonTerrestrialNetwork()) {
return true;
}
@@ -3598,17 +3754,13 @@
DataSpecificRegistrationInfo newDsri = newNri.getDataSpecificInfo();
if (newDsri == null) return false;
- if ((oldDsri == null || oldDsri.getVopsSupportInfo() == null
+ // If previously VoPS was supported (or does not exist), and now the network reports
+ // VoPS not supported, we should evaluate existing data networks to see if they need
+ // to be torn down.
+ return (oldDsri == null || oldDsri.getVopsSupportInfo() == null
|| oldDsri.getVopsSupportInfo().isVopsSupported())
&& (newDsri.getVopsSupportInfo() != null && !newDsri.getVopsSupportInfo()
- .isVopsSupported())) {
- // If previously VoPS was supported (or does not exist), and now the network reports
- // VoPS not supported, we should evaluate existing data networks to see if they need
- // to be torn down.
- return true;
- }
-
- return false;
+ .isVopsSupported());
}
/**
@@ -3647,7 +3799,7 @@
return true;
}
- if (oldSS.isUsingNonTerrestrialNetwork() && !newSS.isUsingNonTerrestrialNetwork()) {
+ if (oldSS.isUsingNonTerrestrialNetwork() != newSS.isUsingNonTerrestrialNetwork()) {
return true;
}
@@ -3655,17 +3807,13 @@
DataSpecificRegistrationInfo newDsri = newPsNri.getDataSpecificInfo();
if (oldDsri == null) return false;
- if ((newDsri == null || newDsri.getVopsSupportInfo() == null
+ // If previously VoPS was not supported, and now the network reports
+ // VoPS supported (or does not report), we should evaluate the unsatisfied network
+ // request to see if the can be satisfied again.
+ return (newDsri == null || newDsri.getVopsSupportInfo() == null
|| newDsri.getVopsSupportInfo().isVopsSupported())
&& (oldDsri.getVopsSupportInfo() != null && !oldDsri.getVopsSupportInfo()
- .isVopsSupported())) {
- // If previously VoPS was not supported, and now the network reports
- // VoPS supported (or does not report), we should evaluate the unsatisfied network
- // request to see if the can be satisfied again.
- return true;
- }
-
- return false;
+ .isVopsSupported());
}
/**
@@ -3776,28 +3924,32 @@
/**
* @return Data config manager instance.
*/
- public @NonNull DataConfigManager getDataConfigManager() {
+ @NonNull
+ public DataConfigManager getDataConfigManager() {
return mDataConfigManager;
}
/**
* @return Data profile manager instance.
*/
- public @NonNull DataProfileManager getDataProfileManager() {
+ @NonNull
+ public DataProfileManager getDataProfileManager() {
return mDataProfileManager;
}
/**
* @return Data settings manager instance.
*/
- public @NonNull DataSettingsManager getDataSettingsManager() {
+ @NonNull
+ public DataSettingsManager getDataSettingsManager() {
return mDataSettingsManager;
}
/**
* @return Data retry manager instance.
*/
- public @NonNull DataRetryManager getDataRetryManager() {
+ @NonNull
+ public DataRetryManager getDataRetryManager() {
return mDataRetryManager;
}
@@ -3805,7 +3957,8 @@
* @return The list of SubscriptionPlans
*/
@VisibleForTesting
- public @NonNull List<SubscriptionPlan> getSubscriptionPlans() {
+ @NonNull
+ public List<SubscriptionPlan> getSubscriptionPlans() {
return mSubscriptionPlans;
}
@@ -3813,7 +3966,9 @@
* @return The set of network types an unmetered override applies to
*/
@VisibleForTesting
- public @NonNull @NetworkType Set<Integer> getUnmeteredOverrideNetworkTypes() {
+ @NonNull
+ @NetworkType
+ public Set<Integer> getUnmeteredOverrideNetworkTypes() {
return mUnmeteredOverrideNetworkTypes;
}
@@ -3821,7 +3976,9 @@
* @return The set of network types a congested override applies to
*/
@VisibleForTesting
- public @NonNull @NetworkType Set<Integer> getCongestedOverrideNetworkTypes() {
+ @NonNull
+ @NetworkType
+ public Set<Integer> getCongestedOverrideNetworkTypes() {
return mCongestedOverrideNetworkTypes;
}
@@ -3831,7 +3988,8 @@
* @param transport The transport.
* @return The current network type.
*/
- private @NetworkType int getDataNetworkType(@TransportType int transport) {
+ @NetworkType
+ private int getDataNetworkType(@TransportType int transport) {
NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_PS, transport);
if (nri != null) {
@@ -3847,8 +4005,8 @@
* @param transport The transport.
* @return The registration state.
*/
- private @RegistrationState int getDataRegistrationState(@NonNull ServiceState ss,
- @TransportType int transport) {
+ @RegistrationState
+ private int getDataRegistrationState(@NonNull ServiceState ss, @TransportType int transport) {
NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_PS, transport);
if (nri != null) {
@@ -3860,7 +4018,8 @@
/**
* @return The data activity. Note this is only updated when screen is on.
*/
- public @DataActivityType int getDataActivity() {
+ @DataActivityType
+ public int getDataActivity() {
return mDataActivity;
}
@@ -3898,14 +4057,13 @@
*
* @param reason The reason to tear down.
*/
- public void onTearDownAllDataNetworks(@TearDownReason int reason) {
+ private void onTearDownAllDataNetworks(@TearDownReason int reason) {
log("onTearDownAllDataNetworks: reason=" + DataNetwork.tearDownReasonToString(reason));
if (mDataNetworkList.isEmpty()) {
log("tearDownAllDataNetworks: No pending networks. All disconnected now.");
return;
}
- mPendingTearDownAllNetworks = true;
for (DataNetwork dataNetwork : mDataNetworkList) {
if (!dataNetwork.isDisconnecting()) {
tearDownGracefully(dataNetwork, reason);
@@ -4007,14 +4165,16 @@
*
* @return The data network state.
*/
- public @DataState int getInternetDataNetworkState() {
+ @DataState
+ public int getInternetDataNetworkState() {
return mInternetDataNetworkState;
}
/**
* @return List of bound data service packages name on WWAN and WLAN.
*/
- public @NonNull List<String> getDataServicePackages() {
+ @NonNull
+ public List<String> getDataServicePackages() {
List<String> packages = new ArrayList<>();
for (int i = 0; i < mDataServiceManagers.size(); i++) {
packages.add(mDataServiceManagers.valueAt(i).getDataServicePackageName());
@@ -4023,44 +4183,9 @@
}
/**
- * Check whether data is disallowed while using satellite
- * @param capabilities An array of the NetworkCapabilities to be checked
- * @return {@code true} if the capabilities contain any capability that are restricted
- * while using satellite else {@code false}
- */
- private boolean isDataDisallowedDueToSatellite(@NetCapability int[] capabilities) {
- if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
- return false;
- }
-
- if (!mServiceState.isUsingNonTerrestrialNetwork()) {
- // Device is not connected to satellite
- return false;
- }
-
- Set<Integer> restrictedCapabilities = Set.of(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- if (Arrays.stream(capabilities).noneMatch(restrictedCapabilities::contains)) {
- // Only internet data disallowed while using satellite
- return false;
- }
-
- for (NetworkRegistrationInfo nri : mServiceState.getNetworkRegistrationInfoList()) {
- if (nri.isNonTerrestrialNetwork()
- && nri.getAvailableServices().contains(
- NetworkRegistrationInfo.SERVICE_TYPE_DATA)) {
- // Data is supported while using satellite
- return false;
- }
- }
-
- // Data is disallowed while using satellite
- return true;
- }
-
- /**
* Request network validation.
- *
- * Nnetwork validation request is sent to the DataNetwork that matches the network capability
+ * <p>
+ * Network validation request is sent to the DataNetwork that matches the network capability
* in the list of DataNetwork owned by the DNC.
*
* @param capability network capability {@link NetCapability}
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index 51fc71b..c50d50a 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -45,6 +45,7 @@
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.util.LocalLog;
+import android.util.LruCache;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
@@ -81,42 +82,51 @@
private final LocalLog mLocalLog = new LocalLog(128);
/** Data network controller. */
- private final @NonNull DataNetworkController mDataNetworkController;
+ @NonNull
+ private final DataNetworkController mDataNetworkController;
/** Data config manager. */
- private final @NonNull DataConfigManager mDataConfigManager;
+ @NonNull
+ private final DataConfigManager mDataConfigManager;
/** Cellular data service. */
- private final @NonNull DataServiceManager mWwanDataServiceManager;
+ @NonNull
+ private final DataServiceManager mWwanDataServiceManager;
/**
* All data profiles for the current carrier. Note only data profiles loaded from the APN
* database will be stored here. The on-demand data profiles (generated dynamically, for
* example, enterprise data profiles with differentiator) are not stored here.
*/
- private final @NonNull List<DataProfile> mAllDataProfiles = new ArrayList<>();
+ @NonNull
+ private final List<DataProfile> mAllDataProfiles = new ArrayList<>();
/** The data profile used for initial attach. */
- private @Nullable DataProfile mInitialAttachDataProfile = null;
+ @Nullable
+ private DataProfile mInitialAttachDataProfile = null;
/** The preferred data profile used for internet. */
- private @Nullable DataProfile mPreferredDataProfile = null;
+ @Nullable
+ private DataProfile mPreferredDataProfile = null;
- /** The last data profile that's successful for internet connection. */
- private @Nullable DataProfile mLastInternetDataProfile = null;
+ /** The last data profile that's successful for internet connection by subscription id. */
+ @NonNull
+ private final LruCache<Integer, DataProfile> mLastInternetDataProfiles = new LruCache<>(256);
/** Preferred data profile set id. */
private int mPreferredDataProfileSetId = Telephony.Carriers.NO_APN_SET_ID;
/** Data profile manager callbacks. */
- private final @NonNull Set<DataProfileManagerCallback> mDataProfileManagerCallbacks =
- new ArraySet<>();
+ @NonNull
+ private final Set<DataProfileManagerCallback> mDataProfileManagerCallbacks = new ArraySet<>();
/** SIM state. */
- private @SimState int mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
+ @SimState
+ private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN;
/** Feature flags controlling which feature is enabled. */
- private final @NonNull FeatureFlags mFeatureFlags;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
/**
* Data profile manager callback. This should be only used by {@link DataNetworkController}.
@@ -452,9 +462,11 @@
}
}
- // Update a working internet data profile as a future candidate for preferred data profile
- // after APNs are reset to default
- mLastInternetDataProfile = defaultProfile;
+ // Update a working internet data profile by subid as a future candidate for preferred
+ // data profile after APNs are reset to default
+ if (defaultProfile != null) {
+ mLastInternetDataProfiles.put(mPhone.getSubId(), defaultProfile);
+ }
// If the live default internet network is not using the preferred data profile, since
// brought up a network means it passed sophisticated checks, update the preferred data
@@ -473,7 +485,8 @@
*
* @return The preferred data profile.
*/
- private @Nullable DataProfile getPreferredDataProfileFromDb() {
+ @Nullable
+ private DataProfile getPreferredDataProfileFromDb() {
Cursor cursor = mPhone.getContext().getContentResolver().query(
Uri.withAppendedPath(Telephony.Carriers.PREFERRED_APN_URI,
String.valueOf(mPhone.getSubId())), null, null, null,
@@ -498,7 +511,8 @@
/**
* @return The preferred data profile from carrier config.
*/
- private @Nullable DataProfile getPreferredDataProfileFromConfig() {
+ @Nullable
+ private DataProfile getPreferredDataProfileFromConfig() {
// Check if there is configured default preferred data profile.
String defaultPreferredApn = mDataConfigManager.getDefaultPreferredApn();
if (!TextUtils.isEmpty(defaultPreferredApn)) {
@@ -542,7 +556,8 @@
*/
private boolean updatePreferredDataProfile() {
DataProfile preferredDataProfile;
- if (SubscriptionManager.isValidSubscriptionId(mPhone.getSubId())) {
+ int subId = mPhone.getSubId();
+ if (SubscriptionManager.isValidSubscriptionId(subId)) {
preferredDataProfile = getPreferredDataProfileFromDb();
if (preferredDataProfile == null) {
preferredDataProfile = getPreferredDataProfileFromConfig();
@@ -551,7 +566,8 @@
setPreferredDataProfile(preferredDataProfile);
} else {
preferredDataProfile = mAllDataProfiles.stream()
- .filter(dp -> areDataProfilesSharingApn(dp, mLastInternetDataProfile))
+ .filter(dp -> areDataProfilesSharingApn(dp,
+ mLastInternetDataProfiles.get(subId)))
.findFirst()
.orElse(null);
if (preferredDataProfile != null) {
@@ -580,10 +596,10 @@
/**
* Update the data profile used for initial attach.
- *
+ * <p>
* Note that starting from Android 13 only APNs that supports "IA" type will be used for
* initial attach. Please update APN configuration file if needed.
- *
+ * <p>
* Some carriers might explicitly require that using "user-added" APN for initial
* attach. In this case, exception can be configured through
* {@link CarrierConfigManager#KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY}.
@@ -597,7 +613,7 @@
// Sort the data profiles so the preferred data profile is at the beginning.
List<DataProfile> allDataProfiles = mAllDataProfiles.stream()
.sorted(Comparator.comparing((DataProfile dp) -> !dp.equals(mPreferredDataProfile)))
- .collect(Collectors.toList());
+ .toList();
// Search in the order. "IA" type should be the first from getAllowedInitialAttachApnTypes.
for (int apnType : mDataConfigManager.getAllowedInitialAttachApnTypes()) {
initialAttachDataProfile = allDataProfiles.stream()
@@ -636,7 +652,8 @@
* @param apnTypeBitmask APN type
* @return The APN setting
*/
- private @NonNull ApnSetting buildDefaultApnSetting(@NonNull String entry,
+ @NonNull
+ private ApnSetting buildDefaultApnSetting(@NonNull String entry,
@NonNull String apn, @Annotation.ApnType int apnTypeBitmask) {
return new ApnSetting.Builder()
.setEntryName(entry)
@@ -659,7 +676,8 @@
* This should be set to true for condition-based retry/setup.
* @return The data profile. {@code null} if can't find any satisfiable data profile.
*/
- public @Nullable DataProfile getDataProfileForNetworkRequest(
+ @Nullable
+ public DataProfile getDataProfileForNetworkRequest(
@NonNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType,
boolean isNtn, boolean isEsimBootstrapProvisioning, boolean ignorePermanentFailure) {
ApnSetting apnSetting = null;
@@ -730,7 +748,8 @@
* This should be set to true for condition-based retry/setup.
* @return The APN setting. {@code null} if can't find any satisfiable data profile.
*/
- private @Nullable ApnSetting getApnSettingForNetworkRequest(
+ @Nullable
+ private ApnSetting getApnSettingForNetworkRequest(
@NonNull TelephonyNetworkRequest networkRequest, @NetworkType int networkType,
boolean isNtn, boolean isEsimBootStrapProvisioning, boolean ignorePermanentFailure) {
if (!networkRequest.hasAttribute(
@@ -793,7 +812,7 @@
logv("Satisfied profile: " + dataProfile + ", last setup="
+ DataUtils.elapsedTimeToString(dataProfile.getLastSetupTimestamp()));
}
- if (dataProfiles.size() == 0) {
+ if (dataProfiles.isEmpty()) {
log("Can't find any data profile that can satisfy " + networkRequest);
return null;
}
@@ -810,16 +829,14 @@
ApnSetting.INFRASTRUCTURE_SATELLITE)) {
return false;
}
- if (!isNtn && !dp.getApnSetting().isForInfrastructure(
- ApnSetting.INFRASTRUCTURE_CELLULAR)) {
- return false;
- }
+ return isNtn || dp.getApnSetting().isForInfrastructure(
+ ApnSetting.INFRASTRUCTURE_CELLULAR);
}
return true;
})
.collect(Collectors.toList());
- if (dataProfiles.size() == 0) {
+ if (dataProfiles.isEmpty()) {
String ntnReason = "";
if (mFeatureFlags.carrierEnabledSatelliteFlag()) {
ntnReason = " and infrastructure for "
@@ -837,7 +854,7 @@
== Telephony.Carriers.MATCH_ALL_APN_SET_ID
|| dp.getApnSetting().getApnSetId() == mPreferredDataProfileSetId))
.collect(Collectors.toList());
- if (dataProfiles.size() == 0) {
+ if (dataProfiles.isEmpty()) {
log("Can't find any data profile has APN set id matched. mPreferredDataProfileSetId="
+ mPreferredDataProfileSetId);
return null;
@@ -845,9 +862,10 @@
// Check if data profiles are permanently failed.
dataProfiles = dataProfiles.stream()
- .filter(dp -> ignorePermanentFailure || !dp.getApnSetting().getPermanentFailed())
+ .filter(dp -> ignorePermanentFailure || (dp.getApnSetting() != null
+ && !dp.getApnSetting().getPermanentFailed()))
.collect(Collectors.toList());
- if (dataProfiles.size() == 0) {
+ if (dataProfiles.isEmpty()) {
log("The suitable data profiles are all in permanent failed state.");
return null;
}
@@ -899,7 +917,7 @@
TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
return getDataProfileForNetworkRequest(networkRequest, networkType,
mPhone.getServiceState().isUsingNonTerrestrialNetwork(),
mDataNetworkController.isEsimBootStrapProvisioningActivated(),
@@ -939,7 +957,8 @@
* @param setting The Apn setting to be checked.
*/
private void checkApnSetting(@NonNull ApnSetting setting) {
- if (setting.canHandleType(ApnSetting.TYPE_MMS)) {
+ if (setting.canHandleType(ApnSetting.TYPE_MMS)
+ && setting.getEditedStatus() == Telephony.Carriers.UNEDITED) {
if (setting.getMmsc() == null) {
reportAnomaly("MMS is supported but no MMSC configured " + setting,
"9af73e18-b523-4dc5-adab-19d86c6a3685");
@@ -965,7 +984,7 @@
private void checkDataProfiles(List<DataProfile> profiles) {
for (int i = 0; i < profiles.size(); i++) {
ApnSetting a = profiles.get(i).getApnSetting();
- if (a == null) continue;
+ if (a == null || a.getEditedStatus() != Telephony.Carriers.UNEDITED) continue;
if (// Lingering network is not the default and doesn't cover all the regular networks
(int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN
!= a.getLingeringNetworkTypeBitmask()
@@ -979,23 +998,6 @@
a.getLingeringNetworkTypeBitmask()),
"9af73e18-b523-4dc5-adab-4bb24355d838");
}
- for (int j = i + 1; j < profiles.size(); j++) {
- ApnSetting b = profiles.get(j).getApnSetting();
- if (b == null) continue;
- String apnNameA = a.getApnName();
- String apnNameB = b.getApnName();
- if (TextUtils.equals(apnNameA, apnNameB)
- // TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN means all network types
- && (a.getNetworkTypeBitmask()
- == (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN
- || b.getNetworkTypeBitmask()
- == (int) TelephonyManager.NETWORK_TYPE_BITMASK_UNKNOWN
- || (a.getNetworkTypeBitmask() & b.getNetworkTypeBitmask()) != 0)) {
- reportAnomaly("Found overlapped network type under the APN name "
- + a.getApnName(),
- "9af73e18-b523-4dc5-adab-4bb24555d839");
- }
- }
}
}
@@ -1007,7 +1009,8 @@
*
* @return The merged data profile. {@code null} if merging is not possible.
*/
- private static @Nullable DataProfile mergeDataProfiles(
+ @Nullable
+ private static DataProfile mergeDataProfiles(
@NonNull DataProfile dp1, @NonNull DataProfile dp2) {
Objects.requireNonNull(dp1);
Objects.requireNonNull(dp2);
@@ -1106,10 +1109,6 @@
* @return {@code true} if the provided data profile can be still used in current environment.
*/
public boolean isDataProfileCompatible(@NonNull DataProfile dataProfile) {
- if (dataProfile == null) {
- return false;
- }
-
if (dataProfile.getApnSetting() == null && dataProfile.getTrafficDescriptor() != null) {
// A traffic descriptor only data profile can be always used. Traffic descriptors are
// always generated on the fly instead loaded from the database.
@@ -1224,7 +1223,10 @@
pw.println("Preferred data profile from db=" + getPreferredDataProfileFromDb());
pw.println("Preferred data profile from config=" + getPreferredDataProfileFromConfig());
pw.println("Preferred data profile set id=" + mPreferredDataProfileSetId);
- pw.println("Last internet data profile=" + mLastInternetDataProfile);
+ pw.println("Last internet data profile for=");
+ pw.increaseIndent();
+ mLastInternetDataProfiles.snapshot().forEach((key, value) -> pw.println(key + ":" + value));
+ pw.decreaseIndent();
pw.println("Initial attach data profile=" + mInitialAttachDataProfile);
pw.println("isTetheringDataProfileExisting=" + isTetheringDataProfileExisting(
TelephonyManager.NETWORK_TYPE_LTE));
diff --git a/src/java/com/android/internal/telephony/data/DataRetryManager.java b/src/java/com/android/internal/telephony/data/DataRetryManager.java
index 5933463..d35e9e8 100644
--- a/src/java/com/android/internal/telephony/data/DataRetryManager.java
+++ b/src/java/com/android/internal/telephony/data/DataRetryManager.java
@@ -150,53 +150,67 @@
private static final int RESET_REASON_TAC_CHANGED = 6;
/** The phone instance. */
- private final @NonNull Phone mPhone;
+ @NonNull
+ private final Phone mPhone;
/** Featureflags. */
- private final @NonNull FeatureFlags mFlags;
+ @NonNull
+ private final FeatureFlags mFlags;
/** The RIL instance. */
- private final @NonNull CommandsInterface mRil;
+ @NonNull
+ private final CommandsInterface mRil;
/** Logging tag. */
- private final @NonNull String mLogTag;
+ @NonNull
+ private final String mLogTag;
/** Local log. */
- private final @NonNull LocalLog mLocalLog = new LocalLog(128);
+ @NonNull
+ private final LocalLog mLocalLog = new LocalLog(128);
/** Alarm Manager used to schedule long set up or handover retries. */
- private final @NonNull AlarmManager mAlarmManager;
+ @NonNull
+ private final AlarmManager mAlarmManager;
/**
* The data retry callback. This is only used to notify {@link DataNetworkController} to retry
* setup data network.
*/
- private @NonNull Set<DataRetryManagerCallback> mDataRetryManagerCallbacks = new ArraySet<>();
+ @NonNull
+ private final Set<DataRetryManagerCallback> mDataRetryManagerCallbacks = new ArraySet<>();
/** Data service managers. */
- private @NonNull SparseArray<DataServiceManager> mDataServiceManagers;
+ @NonNull
+ private final SparseArray<DataServiceManager> mDataServiceManagers;
/** Data config manager instance. */
- private final @NonNull DataConfigManager mDataConfigManager;
+ @NonNull
+ private final DataConfigManager mDataConfigManager;
/** Data profile manager. */
- private final @NonNull DataProfileManager mDataProfileManager;
+ @NonNull
+ private final DataProfileManager mDataProfileManager;
/** Data setup retry rule list. */
- private @NonNull List<DataSetupRetryRule> mDataSetupRetryRuleList = new ArrayList<>();
+ @NonNull
+ private List<DataSetupRetryRule> mDataSetupRetryRuleList = new ArrayList<>();
/** Data handover retry rule list. */
- private @NonNull List<DataHandoverRetryRule> mDataHandoverRetryRuleList = new ArrayList<>();
+ @NonNull
+ private List<DataHandoverRetryRule> mDataHandoverRetryRuleList = new ArrayList<>();
/** Data retry entries. */
- private final @NonNull List<DataRetryEntry> mDataRetryEntries = new ArrayList<>();
+ @NonNull
+ private final List<DataRetryEntry> mDataRetryEntries = new ArrayList<>();
/**
* Data throttling entries. Note this only stores throttling requested by networks. We intended
* not to store frameworks-initiated throttling because they are not explicit/strong throttling
* requests.
*/
- private final @NonNull List<DataThrottlingEntry> mDataThrottlingEntries = new ArrayList<>();
+ @NonNull
+ private final List<DataThrottlingEntry> mDataThrottlingEntries = new ArrayList<>();
/**
* Represent a single data setup/handover throttling reported by networks.
@@ -205,31 +219,37 @@
/**
* The data profile that is being throttled for setup/handover retry.
*/
- public final @NonNull DataProfile dataProfile;
+ @NonNull
+ public final DataProfile dataProfile;
/**
* The associated network request list when throttling happened. Should be {@code null} when
* retry type is {@link ThrottleStatus#RETRY_TYPE_HANDOVER}.
*/
- public final @Nullable NetworkRequestList networkRequestList;
+ @Nullable
+ public final NetworkRequestList networkRequestList;
/**
- * @param dataNetwork The data network that is being throttled for handover retry. Should be
+ * The data network that is being throttled for handover retry. Should be
* {@code null} when retryType is {@link ThrottleStatus#RETRY_TYPE_NEW_CONNECTION}.
*/
- public final @Nullable DataNetwork dataNetwork;
+ @Nullable
+ public final DataNetwork dataNetwork;
/** The transport that the data profile has been throttled on. */
- public final @TransportType int transport;
+ @TransportType
+ public final int transport;
/** The retry type when throttling expires. */
- public final @RetryType int retryType;
+ @RetryType
+ public final int retryType;
/**
* The expiration time of data throttling. This is the time retrieved from
* {@link SystemClock#elapsedRealtime()}.
*/
- public final @ElapsedRealtimeLong long expirationTimeMillis;
+ @ElapsedRealtimeLong
+ public final long expirationTimeMillis;
/**
* Constructor.
@@ -257,7 +277,8 @@
}
@Override
- public @NonNull String toString() {
+ @NonNull
+ public String toString() {
return "[DataThrottlingEntry: dataProfile=" + dataProfile + ", request list="
+ networkRequestList + ", dataNetwork=" + dataNetwork + ", transport="
+ AccessNetworkConstants.transportTypeToString(transport) + ", expiration time="
@@ -293,13 +314,17 @@
* capabilities specified here, then retry will happen. Empty set indicates the retry rule
* is not using network capabilities.
*/
- protected @NonNull @NetCapability Set<Integer> mNetworkCapabilities = new ArraySet<>();
+ @NonNull
+ @NetCapability
+ protected Set<Integer> mNetworkCapabilities = new ArraySet<>();
/**
* The fail causes. If data setup failed with certain fail causes, then retry will happen.
* Empty set indicates the retry rule is not using the fail causes.
*/
- protected @NonNull @DataFailureCause Set<Integer> mFailCauses = new ArraySet<>();
+ @NonNull
+ @DataFailureCause
+ protected Set<Integer> mFailCauses = new ArraySet<>();
public DataRetryRule(@NonNull String ruleString) {
if (TextUtils.isEmpty(ruleString)) {
@@ -353,7 +378,8 @@
* @return The data network setup retry intervals in milliseconds. If this is empty, then
* {@link #getMaxRetries()} must return 0.
*/
- public @NonNull List<Long> getRetryIntervalsMillis() {
+ @NonNull
+ public List<Long> getRetryIntervalsMillis() {
return mRetryIntervalsMillis;
}
@@ -372,43 +398,44 @@
* happen. Empty set indicates the retry rule is not using the fail causes.
*/
@VisibleForTesting
- public @NonNull @DataFailureCause Set<Integer> getFailCauses() {
+ @NonNull
+ @DataFailureCause
+ public Set<Integer> getFailCauses() {
return mFailCauses;
}
}
/**
* Represent a rule for data setup retry.
- *
+ * <p>
* The syntax of the retry rule:
* 1. Retry based on {@link NetworkCapabilities}. Note that only APN-type network capabilities
* are supported. If the capabilities are not specified, then the retry rule only applies
* to the current failed APN used in setup data call request.
* "capabilities=[netCaps1|netCaps2|...], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
- *
+ * <p>
* 2. Retry based on {@link DataFailCause}
* "fail_causes=[cause1|cause2|cause3|..], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
- *
+ * <p>
* 3. Retry based on {@link NetworkCapabilities} and {@link DataFailCause}. Note that only
* APN-type network capabilities are supported.
* "capabilities=[netCaps1|netCaps2|...], fail_causes=[cause1|cause2|cause3|...],
* [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
- *
+ * <p>
* 4. Permanent fail causes (no timer-based retry) on the current failed APN. Retry interval
* is specified for retrying the next available APN.
* "permanent_fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|65543|65547|
* 2252|2253|2254, retry_interval=2500"
- *
+ * <p>
* For example,
* "capabilities=eims, retry_interval=1000, maximum_retries=20" means if the attached
* network request is emergency, then retry data network setup every 1 second for up to 20
* times.
- *
+ * <p>
* "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
* "5000|10000|15000|20000|40000|60000|120000|240000|600000|1200000|1800000"
* "1800000, maximum_retries=20" means for those capabilities, retry happens in 2.5s, 3s, 5s,
* 10s, 15s, 20s, 40s, 1m, 2m, 4m, 10m, 20m, 30m, 30m, 30m, until reaching 20 retries.
- *
*/
public static class DataSetupRetryRule extends DataRetryRule {
private static final String RULE_TAG_PERMANENT_FAIL_CAUSES = "permanent_fail_causes";
@@ -469,7 +496,9 @@
* capabilities.
*/
@VisibleForTesting
- public @NonNull @NetCapability Set<Integer> getNetworkCapabilities() {
+ @NonNull
+ @NetCapability
+ public Set<Integer> getNetworkCapabilities() {
return mNetworkCapabilities;
}
@@ -487,7 +516,7 @@
* @param cause Fail cause from previous setup data request.
* @return {@code true} if the retry rule can be matched.
*/
- public boolean canBeMatched(@NonNull @NetCapability int networkCapability,
+ public boolean canBeMatched(@NetCapability int networkCapability,
@DataFailureCause int cause) {
if (!mFailCauses.isEmpty() && !mFailCauses.contains(cause)) {
return false;
@@ -510,22 +539,22 @@
/**
* Represent a handover data network retry rule.
- *
+ * <p>
* The syntax of the retry rule:
* 1. Retry when handover fails.
* "retry_interval=[n1|n2|n3|...], [maximum_retries=n]"
- *
+ * <p>
* For example,
* "retry_interval=1000|3000|5000, maximum_retries=10" means handover retry will happen in 1s,
* 3s, 5s, 5s, 5s....up to 10 times.
- *
+ * <p>
* 2. Retry when handover fails with certain fail causes.
* "retry_interval=[n1|n2|n3|...], fail_causes=[cause1|cause2|cause3|...], [maximum_retries=n]
- *
+ * <p>
* For example,
* "retry_interval=1000, maximum_retries=3, fail_causes=5" means handover retry every 1 second
* for up to 3 times when handover fails with the cause 5.
- *
+ * <p>
* "maximum_retries=0, fail_causes=6|10|67" means handover retry should not happen for those
* causes.
*/
@@ -573,7 +602,8 @@
public @interface DataRetryState {}
/** The rule used for this data retry. {@code null} if the retry is requested by network. */
- public final @Nullable DataRetryRule appliedDataRetryRule;
+ @Nullable
+ public final DataRetryRule appliedDataRetryRule;
/** The retry delay in milliseconds. */
public final long retryDelayMillis;
@@ -582,13 +612,15 @@
* Retry elapsed time. This is the system elapsed time retrieved from
* {@link SystemClock#elapsedRealtime()}.
*/
- public final @ElapsedRealtimeLong long retryElapsedTime;
+ @ElapsedRealtimeLong
+ public final long retryElapsedTime;
/** The retry state. */
protected int mRetryState = RETRY_STATE_NOT_RETRIED;
/** Timestamp when a state is set. For debugging purposes only. */
- protected @ElapsedRealtimeLong long mRetryStateTimestamp = 0;
+ @ElapsedRealtimeLong
+ protected long mRetryStateTimestamp;
/**
* Constructor
@@ -617,7 +649,8 @@
/**
* @return Get the retry state.
*/
- public @DataRetryState int getState() {
+ @DataRetryState
+ public int getState() {
return mRetryState;
}
@@ -628,13 +661,13 @@
* @return Retry state in string format.
*/
public static String retryStateToString(@DataRetryState int retryState) {
- switch (retryState) {
- case RETRY_STATE_NOT_RETRIED: return "NOT_RETRIED";
- case RETRY_STATE_FAILED: return "FAILED";
- case RETRY_STATE_SUCCEEDED: return "SUCCEEDED";
- case RETRY_STATE_CANCELLED: return "CANCELLED";
- default: return "Unknown(" + retryState + ")";
- }
+ return switch (retryState) {
+ case RETRY_STATE_NOT_RETRIED -> "NOT_RETRIED";
+ case RETRY_STATE_FAILED -> "FAILED";
+ case RETRY_STATE_SUCCEEDED -> "SUCCEEDED";
+ case RETRY_STATE_CANCELLED -> "CANCELLED";
+ default -> "Unknown(" + retryState + ")";
+ };
}
/**
@@ -649,7 +682,8 @@
protected long mRetryDelayMillis = TimeUnit.SECONDS.toMillis(5);
/** The applied data retry rule. */
- protected @Nullable DataRetryRule mAppliedDataRetryRule;
+ @Nullable
+ protected DataRetryRule mAppliedDataRetryRule;
/**
* Set the data retry delay.
@@ -657,7 +691,8 @@
* @param retryDelayMillis The retry delay in milliseconds.
* @return This builder.
*/
- public @NonNull T setRetryDelay(long retryDelayMillis) {
+ @NonNull
+ public T setRetryDelay(long retryDelayMillis) {
mRetryDelayMillis = retryDelayMillis;
return (T) this;
}
@@ -668,7 +703,8 @@
* @param dataRetryRule The rule that used for this data retry.
* @return This builder.
*/
- public @NonNull T setAppliedRetryRule(@NonNull DataRetryRule dataRetryRule) {
+ @NonNull
+ public T setAppliedRetryRule(@NonNull DataRetryRule dataRetryRule) {
mAppliedDataRetryRule = dataRetryRule;
return (T) this;
}
@@ -703,16 +739,20 @@
public @interface SetupRetryType {}
/** Setup retry type. Could be retry by same data profile or same capability. */
- public final @SetupRetryType int setupRetryType;
+ @SetupRetryType
+ public final int setupRetryType;
/** The network requests to satisfy when retry happens. */
- public final @NonNull NetworkRequestList networkRequestList;
+ @NonNull
+ public final NetworkRequestList networkRequestList;
/** The data profile that will be used for retry. */
- public final @Nullable DataProfile dataProfile;
+ @Nullable
+ public final DataProfile dataProfile;
/** The transport to retry data setup. */
- public final @TransportType int transport;
+ @TransportType
+ public final int transport;
/**
* Constructor
@@ -743,11 +783,12 @@
* @return Retry type in string format.
*/
private static String retryTypeToString(@SetupRetryType int setupRetryType) {
- switch (setupRetryType) {
- case RETRY_TYPE_DATA_PROFILE: return "BY_PROFILE";
- case RETRY_TYPE_NETWORK_REQUESTS: return "BY_NETWORK_REQUESTS";
- default: return "Unknown(" + setupRetryType + ")";
- }
+ return switch (setupRetryType) {
+ case RETRY_TYPE_DATA_PROFILE -> "BY_PROFILE";
+ case RETRY_TYPE_NETWORK_REQUESTS -> "BY_NETWORK_REQUESTS";
+ case RETRY_TYPE_UNKNOWN -> "UNKNOWN";
+ default -> "Unknown(" + setupRetryType + ")";
+ };
}
@Override
@@ -768,16 +809,20 @@
*/
public static class Builder<T extends Builder<T>> extends DataRetryEntry.Builder<T> {
/** Data setup retry type. Could be retry by same data profile or same capabilities. */
- private @SetupRetryType int mSetupRetryType = RETRY_TYPE_UNKNOWN;
+ @SetupRetryType
+ private int mSetupRetryType = RETRY_TYPE_UNKNOWN;
/** The network requests to satisfy when retry happens. */
- private @NonNull NetworkRequestList mNetworkRequestList;
+ @NonNull
+ private NetworkRequestList mNetworkRequestList;
/** The data profile that will be used for retry. */
- private @Nullable DataProfile mDataProfile;
+ @Nullable
+ private DataProfile mDataProfile;
/** The transport to retry data setup. */
- private @TransportType int mTransport = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ @TransportType
+ private int mTransport = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
/**
* Set the data retry type.
@@ -786,7 +831,8 @@
* capabilities.
* @return This builder.
*/
- public @NonNull Builder<T> setSetupRetryType(@SetupRetryType int setupRetryType) {
+ @NonNull
+ public Builder<T> setSetupRetryType(@SetupRetryType int setupRetryType) {
mSetupRetryType = setupRetryType;
return this;
}
@@ -797,7 +843,8 @@
* @param networkRequestList The network requests to satisfy when retry happens.
* @return This builder.
*/
- public @NonNull Builder<T> setNetworkRequestList(
+ @NonNull
+ public Builder<T> setNetworkRequestList(
@NonNull NetworkRequestList networkRequestList) {
mNetworkRequestList = networkRequestList;
return this;
@@ -809,7 +856,8 @@
* @param dataProfile The data profile that will be used for retry.
* @return This builder.
*/
- public @NonNull Builder<T> setDataProfile(@NonNull DataProfile dataProfile) {
+ @NonNull
+ public Builder<T> setDataProfile(@NonNull DataProfile dataProfile) {
mDataProfile = dataProfile;
return this;
}
@@ -820,7 +868,8 @@
* @param transport The transport to retry data setup.
* @return This builder.
*/
- public @NonNull Builder<T> setTransport(@TransportType int transport) {
+ @NonNull
+ public Builder<T> setTransport(@TransportType int transport) {
mTransport = transport;
return this;
}
@@ -830,7 +879,8 @@
*
* @return The instance of {@link DataSetupRetryEntry}.
*/
- public @NonNull DataSetupRetryEntry build() {
+ @NonNull
+ public DataSetupRetryEntry build() {
if (mNetworkRequestList == null) {
throw new IllegalArgumentException("network request list is not specified.");
}
@@ -854,7 +904,8 @@
*/
public static class DataHandoverRetryEntry extends DataRetryEntry {
/** The data network to be retried for handover. */
- public final @NonNull DataNetwork dataNetwork;
+ @NonNull
+ public final DataNetwork dataNetwork;
/**
* Constructor.
@@ -886,7 +937,8 @@
*/
public static class Builder<T extends Builder<T>> extends DataRetryEntry.Builder<T> {
/** The data network to be retried for handover. */
- public @NonNull DataNetwork mDataNetwork;
+ @NonNull
+ public DataNetwork mDataNetwork;
/**
* Set the data retry type.
@@ -895,7 +947,8 @@
*
* @return This builder.
*/
- public @NonNull Builder<T> setDataNetwork(@NonNull DataNetwork dataNetwork) {
+ @NonNull
+ public Builder<T> setDataNetwork(@NonNull DataNetwork dataNetwork) {
mDataNetwork = dataNetwork;
return this;
}
@@ -905,7 +958,8 @@
*
* @return The instance of {@link DataHandoverRetryEntry}.
*/
- public @NonNull DataHandoverRetryEntry build() {
+ @NonNull
+ public DataHandoverRetryEntry build() {
return new DataHandoverRetryEntry(mDataNetwork,
(DataHandoverRetryRule) mAppliedDataRetryRule, mRetryDelayMillis);
}
@@ -1168,7 +1222,7 @@
// when unthrottling happens, we still want to retry and we'll need
// a type there so we know what to retry. Using RETRY_TYPE_NONE
// ThrottleStatus is just for API backwards compatibility reason.
- updateThrottleStatus(dataProfile, requestList, null,
+ throttleDataProfile(dataProfile, requestList, null,
ThrottleStatus.RETRY_TYPE_NEW_CONNECTION, transport, Long.MAX_VALUE);
return;
} else if (retryDelayMillis != DataCallResponse.RETRY_DURATION_UNDEFINED) {
@@ -1180,7 +1234,7 @@
.setDataProfile(dataProfile)
.setTransport(transport)
.build();
- updateThrottleStatus(dataProfile, requestList, null,
+ throttleDataProfile(dataProfile, requestList, null,
ThrottleStatus.RETRY_TYPE_NEW_CONNECTION, transport,
dataSetupRetryEntry.retryElapsedTime);
schedule(dataSetupRetryEntry);
@@ -1192,7 +1246,7 @@
boolean retryScheduled = false;
List<NetworkRequestList> groupedNetworkRequestLists =
- DataUtils.getGroupedNetworkRequestList(requestList);
+ DataUtils.getGroupedNetworkRequestList(requestList, mFlags);
for (DataSetupRetryRule retryRule : mDataSetupRetryRuleList) {
if (retryRule.isPermanentFailCauseRule() && retryRule.getFailCauses().contains(cause)) {
if (dataProfile.getApnSetting() != null) {
@@ -1298,7 +1352,7 @@
// when unthrottling happens, we still want to retry and we'll need
// a type there so we know what to retry. Using RETRY_TYPE_NONE
// ThrottleStatus is just for API backwards compatibility reason.
- updateThrottleStatus(dataNetwork.getDataProfile(),
+ throttleDataProfile(dataNetwork.getDataProfile(),
dataNetwork.getAttachedNetworkRequestList(), dataNetwork,
ThrottleStatus.RETRY_TYPE_HANDOVER, targetTransport, Long.MAX_VALUE);
} else if (retryDelayMillis != DataCallResponse.RETRY_DURATION_UNDEFINED) {
@@ -1308,7 +1362,7 @@
.setDataNetwork(dataNetwork)
.build();
- updateThrottleStatus(dataNetwork.getDataProfile(),
+ throttleDataProfile(dataNetwork.getDataProfile(),
dataNetwork.getAttachedNetworkRequestList(), dataNetwork,
ThrottleStatus.RETRY_TYPE_HANDOVER, targetTransport,
dataHandoverRetryEntry.retryElapsedTime);
@@ -1534,7 +1588,7 @@
* @param expirationTime The expiration time of data throttling. This is the time retrieved from
* {@link SystemClock#elapsedRealtime()}.
*/
- private void updateThrottleStatus(@NonNull DataProfile dataProfile,
+ private void throttleDataProfile(@NonNull DataProfile dataProfile,
@Nullable NetworkRequestList networkRequestList,
@Nullable DataNetwork dataNetwork, @RetryType int retryType,
@TransportType int transport, @ElapsedRealtimeLong long expirationTime) {
@@ -1565,21 +1619,7 @@
? ThrottleStatus.RETRY_TYPE_NONE : retryType;
// Report to the clients.
- final List<ThrottleStatus> throttleStatusList = new ArrayList<>();
- if (dataProfile.getApnSetting() != null) {
- throttleStatusList.addAll(dataProfile.getApnSetting().getApnTypes().stream()
- .map(apnType -> new ThrottleStatus.Builder()
- .setApnType(apnType)
- .setRetryType(dataRetryType)
- .setSlotIndex(mPhone.getPhoneId())
- .setThrottleExpiryTimeMillis(expirationTime)
- .setTransportType(transport)
- .build())
- .collect(Collectors.toList()));
- }
-
- mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
- () -> callback.onThrottleStatusChanged(throttleStatusList)));
+ notifyThrottleStatus(dataProfile, expirationTime, dataRetryType, transport);
}
/**
@@ -1650,23 +1690,9 @@
// Make it final so it can be used in the lambda function below.
final int dataRetryType = retryType;
- if (unthrottledProfile != null && unthrottledProfile.getApnSetting() != null) {
- unthrottledProfile.getApnSetting().setPermanentFailed(false);
- throttleStatusList.addAll(unthrottledProfile.getApnSetting().getApnTypes().stream()
- .map(apnType -> new ThrottleStatus.Builder()
- .setApnType(apnType)
- .setSlotIndex(mPhone.getPhoneId())
- .setNoThrottle()
- .setRetryType(dataRetryType)
- .setTransportType(transport)
- .build())
- .collect(Collectors.toList()));
- }
-
- mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
- () -> callback.onThrottleStatusChanged(throttleStatusList)));
-
if (unthrottledProfile != null) {
+ notifyThrottleStatus(unthrottledProfile, ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME,
+ dataRetryType, transport);
// cancel pending retries since we will soon schedule an immediate retry
cancelRetriesForDataProfile(unthrottledProfile, transport);
}
@@ -1799,6 +1825,60 @@
&& ((DataHandoverRetryEntry) entry).dataNetwork == dataNetwork
&& entry.getState() == DataRetryEntry.RETRY_STATE_NOT_RETRIED)
.forEach(entry -> entry.setState(DataRetryEntry.RETRY_STATE_CANCELLED));
+
+ long now = SystemClock.elapsedRealtime();
+ DataThrottlingEntry dataUnThrottlingEntry = mDataThrottlingEntries.stream()
+ .filter(entry -> dataNetwork == entry.dataNetwork
+ && entry.expirationTimeMillis > now).findAny().orElse(null);
+ if (dataUnThrottlingEntry == null) {
+ return;
+ }
+ log("onCancelPendingHandoverRetry removed throttling entry:" + dataUnThrottlingEntry);
+ DataProfile unThrottledProfile =
+ dataUnThrottlingEntry.dataNetwork.getDataProfile();
+ final int transport = dataUnThrottlingEntry.transport;
+
+ notifyThrottleStatus(unThrottledProfile, ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME,
+ ThrottleStatus.RETRY_TYPE_HANDOVER, transport);
+ mDataThrottlingEntries.removeIf(entry -> dataNetwork == entry.dataNetwork);
+ }
+
+ /**
+ * Notify listeners of throttle status for a given data profile
+ *
+ * @param dataProfile Data profile for this throttling status notification
+ * @param expirationTime Expiration time of throttling status. {@link
+ * ThrottleStatus.Builder#NO_THROTTLE_EXPIRY_TIME} indicates un-throttling.
+ * @param dataRetryType Retry type of this throttling notification.
+ * @param transportType Transport type of this throttling notification.
+ */
+ private void notifyThrottleStatus(
+ @NonNull DataProfile dataProfile, long expirationTime, @RetryType int dataRetryType,
+ @TransportType int transportType) {
+ if (dataProfile.getApnSetting() != null) {
+ final boolean unThrottled =
+ expirationTime == ThrottleStatus.Builder.NO_THROTTLE_EXPIRY_TIME;
+ if (unThrottled) {
+ dataProfile.getApnSetting().setPermanentFailed(false);
+ }
+ final List<ThrottleStatus> throttleStatusList = new ArrayList<>(
+ dataProfile.getApnSetting().getApnTypes().stream()
+ .map(apnType -> {
+ ThrottleStatus.Builder builder = new ThrottleStatus.Builder()
+ .setApnType(apnType)
+ .setSlotIndex(mPhone.getPhoneId())
+ .setRetryType(dataRetryType)
+ .setTransportType(transportType);
+ if (unThrottled) {
+ builder.setNoThrottle();
+ } else {
+ builder.setThrottleExpiryTimeMillis(expirationTime);
+ }
+ return builder.build();
+ }).toList());
+ mDataRetryManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
+ () -> callback.onThrottleStatusChanged(throttleStatusList)));
+ }
}
/**
@@ -1839,23 +1919,17 @@
* @param reason The reason
* @return The reason in string format.
*/
- private static @NonNull String resetReasonToString(int reason) {
- switch (reason) {
- case RESET_REASON_DATA_PROFILES_CHANGED:
- return "DATA_PROFILES_CHANGED";
- case RESET_REASON_RADIO_ON:
- return "RADIO_ON";
- case RESET_REASON_MODEM_RESTART:
- return "MODEM_RESTART";
- case RESET_REASON_DATA_SERVICE_BOUND:
- return "DATA_SERVICE_BOUND";
- case RESET_REASON_DATA_CONFIG_CHANGED:
- return "DATA_CONFIG_CHANGED";
- case RESET_REASON_TAC_CHANGED:
- return "TAC_CHANGED";
- default:
- return "UNKNOWN(" + reason + ")";
- }
+ @NonNull
+ private static String resetReasonToString(int reason) {
+ return switch (reason) {
+ case RESET_REASON_DATA_PROFILES_CHANGED -> "DATA_PROFILES_CHANGED";
+ case RESET_REASON_RADIO_ON -> "RADIO_ON";
+ case RESET_REASON_MODEM_RESTART -> "MODEM_RESTART";
+ case RESET_REASON_DATA_SERVICE_BOUND -> "DATA_SERVICE_BOUND";
+ case RESET_REASON_DATA_CONFIG_CHANGED -> "DATA_CONFIG_CHANGED";
+ case RESET_REASON_TAC_CHANGED -> "TAC_CHANGED";
+ default -> "UNKNOWN(" + reason + ")";
+ };
}
/**
diff --git a/src/java/com/android/internal/telephony/data/DataServiceManager.java b/src/java/com/android/internal/telephony/data/DataServiceManager.java
index ee66a6a..a71bd10 100644
--- a/src/java/com/android/internal/telephony/data/DataServiceManager.java
+++ b/src/java/com/android/internal/telephony/data/DataServiceManager.java
@@ -16,7 +16,6 @@
package com.android.internal.telephony.data;
-import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import android.annotation.NonNull;
@@ -61,6 +60,7 @@
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.telephony.Rlog;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -82,17 +82,12 @@
private static final int EVENT_BIND_DATA_SERVICE = 1;
- private static final int EVENT_WATCHDOG_TIMEOUT = 2;
-
- private static final long REQUEST_UNRESPONDED_TIMEOUT = 10 * MINUTE_IN_MILLIS; // 10 mins
-
private static final long CHANGE_PERMISSION_TIMEOUT_MS = 15 * SECOND_IN_MILLIS; // 15 secs
private final Phone mPhone;
private final String mTag;
- private final CarrierConfigManager mCarrierConfigManager;
private final AppOpsManager mAppOps;
private final LegacyPermissionManager mPermissionManager;
@@ -102,8 +97,6 @@
private IDataService mIDataService;
- private DataServiceManagerDeathRecipient mDeathRecipient;
-
private final RegistrantList mServiceBindingChangedRegistrants = new RegistrantList();
private final Map<IBinder, Message> mMessageMap = new ConcurrentHashMap<>();
@@ -118,7 +111,7 @@
private String mLastBoundPackageName;
- private List<DataCallResponse> mLastDataCallResponseList = Collections.EMPTY_LIST;
+ private List<DataCallResponse> mLastDataCallResponseList = new ArrayList<>();
private class DataServiceManagerDeathRecipient implements IBinder.DeathRecipient {
@Override
@@ -137,7 +130,7 @@
mMessageMap.clear();
// Tear down all connections
- mLastDataCallResponseList = Collections.EMPTY_LIST;
+ mLastDataCallResponseList = new ArrayList<>();
mDataCallListChangedRegistrants.notifyRegistrants(
new AsyncResult(null, Collections.EMPTY_LIST, null));
}
@@ -209,13 +202,11 @@
public void onServiceConnected(ComponentName name, IBinder service) {
if (DBG) log("onServiceConnected: " + name);
mIDataService = IDataService.Stub.asInterface(service);
- mDeathRecipient = new DataServiceManagerDeathRecipient();
mBound = true;
mLastBoundPackageName = getDataServicePackageName();
- removeMessages(EVENT_WATCHDOG_TIMEOUT);
try {
- service.linkToDeath(mDeathRecipient, 0);
+ service.linkToDeath(new DataServiceManagerDeathRecipient(), 0);
mIDataService.createDataServiceProvider(mPhone.getPhoneId());
mIDataService.registerForDataCallListChanged(mPhone.getPhoneId(),
new DataServiceCallbackWrapper("dataCallListChanged"));
@@ -230,7 +221,6 @@
@Override
public void onServiceDisconnected(ComponentName name) {
if (DBG) log("onServiceDisconnected");
- removeMessages(EVENT_WATCHDOG_TIMEOUT);
mIDataService = null;
mBound = false;
mServiceBindingChangedRegistrants.notifyResult(false);
@@ -257,7 +247,6 @@
log("onSetupDataCallComplete. resultCode = " + resultCode + ", response = "
+ response);
}
- removeMessages(EVENT_WATCHDOG_TIMEOUT, DataServiceCallbackWrapper.this);
Message msg = mMessageMap.remove(asBinder());
if (msg != null) {
msg.getData().putParcelable(DATA_CALL_RESPONSE, response);
@@ -270,7 +259,6 @@
@Override
public void onDeactivateDataCallComplete(@DataServiceCallback.ResultCode int resultCode) {
if (DBG) log("onDeactivateDataCallComplete. resultCode = " + resultCode);
- removeMessages(EVENT_WATCHDOG_TIMEOUT, DataServiceCallbackWrapper.this);
Message msg = mMessageMap.remove(asBinder());
sendCompleteMessage(msg, resultCode);
}
@@ -326,7 +314,7 @@
@Override
public void onDataCallListChanged(List<DataCallResponse> dataCallList) {
mLastDataCallResponseList =
- dataCallList != null ? dataCallList : Collections.EMPTY_LIST;
+ dataCallList != null ? dataCallList : new ArrayList<>();
mDataCallListChangedRegistrants.notifyRegistrants(
new AsyncResult(null, dataCallList, null));
}
@@ -334,7 +322,6 @@
@Override
public void onHandoverStarted(@DataServiceCallback.ResultCode int resultCode) {
if (DBG) log("onHandoverStarted. resultCode = " + resultCode);
- removeMessages(EVENT_WATCHDOG_TIMEOUT, DataServiceCallbackWrapper.this);
Message msg = mMessageMap.remove(asBinder());
sendCompleteMessage(msg, resultCode);
}
@@ -342,7 +329,6 @@
@Override
public void onHandoverCancelled(@DataServiceCallback.ResultCode int resultCode) {
if (DBG) log("onHandoverCancelled. resultCode = " + resultCode);
- removeMessages(EVENT_WATCHDOG_TIMEOUT, DataServiceCallbackWrapper.this);
Message msg = mMessageMap.remove(asBinder());
sendCompleteMessage(msg, resultCode);
}
@@ -383,8 +369,8 @@
mTag = "DSM-" + (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN ? "C-"
: "I-") + mPhone.getPhoneId();
mBound = false;
- mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService(
- Context.CARRIER_CONFIG_SERVICE);
+ CarrierConfigManager carrierConfigManager = phone.getContext().getSystemService(
+ CarrierConfigManager.class);
// NOTE: Do NOT use AppGlobals to retrieve the permission manager; AppGlobals
// caches the service instance, but we need to explicitly request a new service
// so it can be mocked out for tests
@@ -393,17 +379,18 @@
mAppOps = (AppOpsManager) phone.getContext().getSystemService(Context.APP_OPS_SERVICE);
// Callback is executed in handler thread to directly handle config change.
- mCarrierConfigManager.registerCarrierConfigChangeListener(this::post,
- (slotIndex, subId, carrierId, specificCarrierId) -> {
- if (slotIndex == mPhone.getPhoneId()) {
- // We should wait for carrier config changed event because the
- // target binding package name can come from the carrier config.
- // Note that we still get this event even when SIM is absent.
- if (DBG) log("Carrier config changed. Try to bind data service.");
- rebindDataService();
- }
- });
-
+ if (carrierConfigManager != null) {
+ carrierConfigManager.registerCarrierConfigChangeListener(this::post,
+ (slotIndex, subId, carrierId, specificCarrierId) -> {
+ if (slotIndex == mPhone.getPhoneId()) {
+ // We should wait for carrier config changed event because the
+ // target binding package name can come from the carrier config.
+ // Note that we still get this event even when SIM is absent.
+ if (DBG) log("Carrier config changed. Try to bind data service.");
+ rebindDataService();
+ }
+ });
+ }
PhoneConfigurationManager.registerForMultiSimConfigChange(
this, EVENT_BIND_DATA_SERVICE, null);
@@ -417,29 +404,13 @@
*/
@Override
public void handleMessage(Message msg) {
- switch (msg.what) {
- case EVENT_BIND_DATA_SERVICE:
- rebindDataService();
- break;
- case EVENT_WATCHDOG_TIMEOUT:
- handleRequestUnresponded((DataServiceCallbackWrapper) msg.obj);
- break;
- default:
- loge("Unhandled event " + msg.what);
+ if (msg.what == EVENT_BIND_DATA_SERVICE) {
+ rebindDataService();
+ } else {
+ loge("Unhandled event " + msg.what);
}
}
- private void handleRequestUnresponded(DataServiceCallbackWrapper callback) {
- String message = "Request " + callback.getTag() + " unresponded on transport "
- + AccessNetworkConstants.transportTypeToString(mTransportType) + " in "
- + REQUEST_UNRESPONDED_TIMEOUT / 1000 + " seconds.";
- log(message);
- // Using fixed UUID to avoid duplicate bugreport notification
- AnomalyReporter.reportAnomaly(
- UUID.fromString("f5d5cbe6-9bd6-4009-b764-42b1b649b1de"),
- message, mPhone.getCarrierId());
- }
-
private void unbindDataService() {
// Start by cleaning up all packages that *shouldn't* have permissions.
revokePermissionsFromUnusedDataServices();
@@ -473,7 +444,7 @@
return;
}
- Intent intent = null;
+ Intent intent;
String className = getDataServiceClassName();
if (TextUtils.isEmpty(className)) {
intent = new Intent(DataService.SERVICE_INTERFACE);
@@ -512,7 +483,8 @@
bindDataService(packageName);
}
- private @NonNull Set<String> getAllDataServicePackageNames() {
+ @NonNull
+ private Set<String> getAllDataServicePackageNames() {
// Cowardly using the public PackageManager interface here.
// Note: This matches only packages that were installed on the system image. If we ever
// expand the permissions model to allow CarrierPrivileged packages, then this will need
@@ -540,7 +512,7 @@
/**
* Get the data service package by transport type.
- *
+ * <p>
* When we bind to a DataService package, we need to revoke permissions from stale
* packages; we need to exclude data packages for all transport types, so we need to
* to be able to query by transport type.
@@ -552,21 +524,19 @@
String packageName;
int resourceId;
String carrierConfig;
-
switch (transportType) {
- case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
+ case AccessNetworkConstants.TRANSPORT_TYPE_WWAN -> {
resourceId = com.android.internal.R.string.config_wwan_data_service_package;
carrierConfig = CarrierConfigManager
.KEY_CARRIER_DATA_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING;
- break;
- case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
+ }
+ case AccessNetworkConstants.TRANSPORT_TYPE_WLAN -> {
resourceId = com.android.internal.R.string.config_wlan_data_service_package;
carrierConfig = CarrierConfigManager
.KEY_CARRIER_DATA_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING;
- break;
- default:
- throw new IllegalStateException("Transport type not WWAN or WLAN. type="
- + AccessNetworkConstants.transportTypeToString(mTransportType));
+ }
+ default -> throw new IllegalStateException("Transport type not WWAN or WLAN. type="
+ + AccessNetworkConstants.transportTypeToString(mTransportType));
}
// Read package name from resource overlay
@@ -604,19 +574,18 @@
int resourceId;
String carrierConfig;
switch (transportType) {
- case AccessNetworkConstants.TRANSPORT_TYPE_WWAN:
+ case AccessNetworkConstants.TRANSPORT_TYPE_WWAN -> {
resourceId = com.android.internal.R.string.config_wwan_data_service_class;
carrierConfig = CarrierConfigManager
.KEY_CARRIER_DATA_SERVICE_WWAN_CLASS_OVERRIDE_STRING;
- break;
- case AccessNetworkConstants.TRANSPORT_TYPE_WLAN:
+ }
+ case AccessNetworkConstants.TRANSPORT_TYPE_WLAN -> {
resourceId = com.android.internal.R.string.config_wlan_data_service_class;
carrierConfig = CarrierConfigManager
.KEY_CARRIER_DATA_SERVICE_WLAN_CLASS_OVERRIDE_STRING;
- break;
- default:
- throw new IllegalStateException("Transport type not WWAN or WLAN. type="
- + transportType);
+ }
+ default -> throw new IllegalStateException("Transport type not WWAN or WLAN. type="
+ + transportType);
}
// Read package name from resource overlay
@@ -680,8 +649,6 @@
mMessageMap.put(callback.asBinder(), onCompleteMessage);
}
try {
- sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
- REQUEST_UNRESPONDED_TIMEOUT);
mIDataService.setupDataCall(mPhone.getPhoneId(), accessNetworkType, dataProfile,
isRoaming, allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
trafficDescriptor, matchAllRuleAllowed, callback);
@@ -720,8 +687,6 @@
mMessageMap.put(callback.asBinder(), onCompleteMessage);
}
try {
- sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
- REQUEST_UNRESPONDED_TIMEOUT);
mIDataService.deactivateDataCall(mPhone.getPhoneId(), cid, reason, callback);
} catch (RemoteException e) {
loge("Cannot invoke deactivateDataCall on data service.");
@@ -732,13 +697,13 @@
/**
* Indicates that a handover has begun. This is called on the source transport.
- *
+ * <p>
* Any resources being transferred cannot be released while a
* handover is underway.
- *
+ * <p>
* If a handover was unsuccessful, then the framework calls DataServiceManager#cancelHandover.
* The target transport retains ownership over any of the resources being transferred.
- *
+ * <p>
* If a handover was successful, the framework calls DataServiceManager#deactivateDataCall with
* reason HANDOVER. The target transport now owns the transferred resources and is
* responsible for releasing them.
@@ -756,13 +721,9 @@
DataServiceCallbackWrapper callback =
new DataServiceCallbackWrapper("startHandover");
- if (onCompleteMessage != null) {
- mMessageMap.put(callback.asBinder(), onCompleteMessage);
- }
+ mMessageMap.put(callback.asBinder(), onCompleteMessage);
try {
- sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
- REQUEST_UNRESPONDED_TIMEOUT);
mIDataService.startHandover(mPhone.getPhoneId(), cid, callback);
} catch (RemoteException e) {
loge("Cannot invoke startHandover on data service.");
@@ -774,7 +735,7 @@
/**
* Indicates that a handover was cancelled after a call to DataServiceManager#startHandover.
* This is called on the source transport.
- *
+ * <p>
* Since the handover was unsuccessful, the source transport retains ownership over any of
* the resources being transferred and is still responsible for releasing them.
*
@@ -791,13 +752,9 @@
DataServiceCallbackWrapper callback =
new DataServiceCallbackWrapper("cancelHandover");
- if (onCompleteMessage != null) {
- mMessageMap.put(callback.asBinder(), onCompleteMessage);
- }
+ mMessageMap.put(callback.asBinder(), onCompleteMessage);
try {
- sendMessageDelayed(obtainMessage(EVENT_WATCHDOG_TIMEOUT, callback),
- REQUEST_UNRESPONDED_TIMEOUT);
mIDataService.cancelHandover(mPhone.getPhoneId(), cid, callback);
} catch (RemoteException e) {
loge("Cannot invoke cancelHandover on data service.");
@@ -894,9 +851,7 @@
mIDataService.requestDataCallList(mPhone.getPhoneId(), callback);
} catch (RemoteException e) {
loge("Cannot invoke requestDataCallList on data service.");
- if (callback != null) {
- mMessageMap.remove(callback.asBinder());
- }
+ mMessageMap.remove(callback.asBinder());
sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
}
}
@@ -937,17 +892,6 @@
}
/**
- * Unregister for apn unthrottled event
- *
- * @param h The handler
- */
- public void unregisterForApnUnthrottled(Handler h) {
- if (h != null) {
- mApnUnthrottledRegistrants.remove(h);
- }
- }
-
- /**
* Request data network validation.
*
* <p>Validates a given data network to ensure that the network can work properly.
@@ -981,9 +925,7 @@
mIDataService.requestNetworkValidation(mPhone.getPhoneId(), cid, callback);
} catch (RemoteException e) {
loge("Cannot invoke requestNetworkValidation on data service.");
- if (callback != null) {
- mMessageMap.remove(callback.asBinder());
- }
+ mMessageMap.remove(callback.asBinder());
sendCompleteMessage(onCompleteMessage, DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
}
}
@@ -1005,17 +947,6 @@
}
}
- /**
- * Unregister for data service binding status changed event.
- *
- * @param h The handler
- */
- public void unregisterForServiceBindingChanged(Handler h) {
- if (h != null) {
- mServiceBindingChangedRegistrants.remove(h);
- }
- }
-
private void log(String s) {
Rlog.d(mTag, s);
}
diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
index 51e5b7d..fb112d9 100644
--- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java
+++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
@@ -47,6 +47,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.SettingsObserver;
+import com.android.internal.telephony.TelephonyCapabilities;
import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.DeviceTelephonyPropertiesStats;
@@ -91,7 +92,8 @@
private static final int EVENT_INITIALIZE = 11;
private final Phone mPhone;
- private final @NonNull FeatureFlags mFeatureFlags;
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
private final ContentResolver mResolver;
private final SettingsObserver mSettingsObserver;
private final String mLogTag;
@@ -100,11 +102,12 @@
private int mSubId;
/** Data config manager */
- private final @NonNull DataConfigManager mDataConfigManager;
+ @NonNull
+ private final DataConfigManager mDataConfigManager;
/** Data settings manager callbacks. */
- private final @NonNull Set<DataSettingsManagerCallback> mDataSettingsManagerCallbacks =
- new ArraySet<>();
+ @NonNull
+ private final Set<DataSettingsManagerCallback> mDataSettingsManagerCallbacks = new ArraySet<>();
/** Mapping of {@link TelephonyManager.DataEnabledReason} to data enabled values. */
private final Map<Integer, Boolean> mDataEnabledSettings = new ArrayMap<>();
@@ -271,7 +274,7 @@
}
private boolean hasCalling() {
- if (!mFeatureFlags.minimalTelephonyCdmCheck()) return true;
+ if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
return mPhone.getContext().getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_CALLING);
}
@@ -718,8 +721,9 @@
* @param policies New mobile data policies in String format.
* @return A Set of parsed mobile data policies.
*/
- public @NonNull @MobileDataPolicy Set<Integer> getMobileDataPolicyEnabled(
- @NonNull String policies) {
+ @NonNull
+ @MobileDataPolicy
+ public Set<Integer> getMobileDataPolicyEnabled(@NonNull String policies) {
Set<Integer> mobileDataPolicies = new HashSet<>();
String[] rulesString = policies.trim().split("\\s*,\\s*");
for (String rule : rulesString) {
@@ -741,7 +745,8 @@
* @return Parsed mobile data policy. {@link #INVALID_MOBILE_DATA_POLICY} if string can't be
* parsed into a mobile data policy.
*/
- private @MobileDataPolicy int parsePolicyFrom(@NonNull String policy) {
+ @MobileDataPolicy
+ private int parsePolicyFrom(@NonNull String policy) {
int dataPolicy;
try {
// parse as new override policy
@@ -810,20 +815,14 @@
private static String dataEnabledChangedReasonToString(
@TelephonyManager.DataEnabledChangedReason int reason) {
- switch (reason) {
- case TelephonyManager.DATA_ENABLED_REASON_USER:
- return "USER";
- case TelephonyManager.DATA_ENABLED_REASON_POLICY:
- return "POLICY";
- case TelephonyManager.DATA_ENABLED_REASON_CARRIER:
- return "CARRIER";
- case TelephonyManager.DATA_ENABLED_REASON_THERMAL:
- return "THERMAL";
- case TelephonyManager.DATA_ENABLED_REASON_OVERRIDE:
- return "OVERRIDE";
- default:
- return "UNKNOWN";
- }
+ return switch (reason) {
+ case TelephonyManager.DATA_ENABLED_REASON_USER -> "USER";
+ case TelephonyManager.DATA_ENABLED_REASON_POLICY -> "POLICY";
+ case TelephonyManager.DATA_ENABLED_REASON_CARRIER -> "CARRIER";
+ case TelephonyManager.DATA_ENABLED_REASON_THERMAL -> "THERMAL";
+ case TelephonyManager.DATA_ENABLED_REASON_OVERRIDE -> "OVERRIDE";
+ default -> "UNKNOWN";
+ };
}
@Override
diff --git a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
index ee8890a..b9b60a0 100644
--- a/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
+++ b/src/java/com/android/internal/telephony/data/DataStallRecoveryManager.java
@@ -73,12 +73,11 @@
value = {
RECOVERY_ACTION_GET_DATA_CALL_LIST,
RECOVERY_ACTION_CLEANUP,
- RECOVERY_ACTION_REREGISTER,
RECOVERY_ACTION_RADIO_RESTART,
RECOVERY_ACTION_RESET_MODEM
})
@Retention(RetentionPolicy.SOURCE)
- public @interface RecoveryAction {};
+ public @interface RecoveryAction {}
/* DataStallRecoveryManager queries RIL for link properties (IP addresses, DNS server addresses
* etc) using RIL_REQUEST_GET_DATA_CALL_LIST. This will help in cases where the data stall
@@ -92,16 +91,6 @@
*/
public static final int RECOVERY_ACTION_CLEANUP = 1;
- /**
- * Add the RECOVERY_ACTION_REREGISTER to align the RecoveryActions between
- * DataStallRecoveryManager and atoms.proto. In Android T, This action will not process because
- * the boolean array for skip recovery action is default true in carrier config setting.
- *
- * @deprecated Do not use.
- */
- @java.lang.Deprecated
- public static final int RECOVERY_ACTION_REREGISTER = 2;
-
/* DataStallRecoveryManager will request ServiceStateTracker to send RIL_REQUEST_RADIO_POWER
* to restart radio. It will restart the radio and re-attch to the network.
*/
@@ -121,9 +110,9 @@
RECOVERED_REASON_USER
})
@Retention(RetentionPolicy.SOURCE)
- public @interface RecoveredReason {};
+ public @interface RecoveredReason {}
- /** The reason when data stall recovered. */
+ // The reason when data stall recovered.
/** The data stall not recovered yet. */
private static final int RECOVERED_REASON_NONE = 0;
/** The data stall recovered by our DataStallRecoveryManager. */
@@ -151,24 +140,33 @@
/** Event for duration milliseconds changed. */
private static final int EVENT_CONTENT_DSRM_DURATION_MILLIS_CHANGED = 5;
- private final @NonNull Phone mPhone;
- private final @NonNull String mLogTag;
- private final @NonNull LocalLog mLocalLog = new LocalLog(128);
- private final @NonNull FeatureFlags mFeatureFlags;
+ @NonNull
+ private final Phone mPhone;
+ @NonNull
+ private final String mLogTag;
+ @NonNull
+ private final LocalLog mLocalLog = new LocalLog(128);
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
/** Data network controller */
- private final @NonNull DataNetworkController mDataNetworkController;
+ @NonNull
+ private final DataNetworkController mDataNetworkController;
/** Data config manager */
- private final @NonNull DataConfigManager mDataConfigManager;
+ @NonNull
+ private final DataConfigManager mDataConfigManager;
/** Cellular data service */
- private final @NonNull DataServiceManager mWwanDataServiceManager;
+ @NonNull
+ private final DataServiceManager mWwanDataServiceManager;
/** The data stall recovery action. */
- private @RecoveryAction int mRecoveryAction;
+ @RecoveryAction
+ private int mRecoveryAction;
/** The elapsed real time of last recovery attempted */
- private @ElapsedRealtimeLong long mTimeLastRecoveryStartMs;
+ @ElapsedRealtimeLong
+ private long mTimeLastRecoveryStartMs;
/** Whether current network is good or not */
private boolean mIsValidNetwork;
/** Whether data stall recovery is triggered or not */
@@ -179,11 +177,14 @@
private boolean mLastActionReported;
/** The real time for data stall start. */
@VisibleForTesting
- public @ElapsedRealtimeLong long mDataStallStartMs;
+ @ElapsedRealtimeLong
+ public long mDataStallStartMs;
/** Last data stall recovery action. */
- private @RecoveryAction int mLastAction;
+ @RecoveryAction
+ private int mLastAction;
/** Last radio power state. */
- private @RadioPowerState int mRadioPowerState;
+ @RadioPowerState
+ private int mRadioPowerState;
/** Whether the NetworkCheckTimer start. */
private boolean mNetworkCheckTimerStarted = false;
/** Whether radio state changed during data stall. */
@@ -197,15 +198,18 @@
/** Whether internet network that require validation is connected. */
private boolean mIsInternetNetworkConnected;
/** The durations for current recovery action */
- private @ElapsedRealtimeLong long mTimeElapsedOfCurrentAction;
+ @ElapsedRealtimeLong
+ private long mTimeElapsedOfCurrentAction;
/** Tracks the total number of validation duration a data stall */
private int mValidationCount;
/** Tracks the number of validation for current action during a data stall */
private int mActionValidationCount;
/** The array for the timers between recovery actions. */
- private @NonNull long[] mDataStallRecoveryDelayMillisArray;
+ @NonNull
+ private long[] mDataStallRecoveryDelayMillisArray;
/** The boolean array for the flags. They are used to skip the recovery actions if needed. */
- private @NonNull boolean[] mSkipRecoveryActionArray;
+ @NonNull
+ private boolean[] mSkipRecoveryActionArray;
/**
* The content URI for the DSRM recovery actions.
@@ -224,12 +228,13 @@
Settings.Global.DSRM_DURATION_MILLIS);
- private DataStallRecoveryManagerCallback mDataStallRecoveryManagerCallback;
+ private final DataStallRecoveryManagerCallback mDataStallRecoveryManagerCallback;
private final DataStallRecoveryStats mStats;
/** The number of milliseconds to wait for the DSRM prediction to complete. */
- private @ElapsedRealtimeLong long mPredictWaitingMillis = 0L;
+ @ElapsedRealtimeLong
+ private long mPredictWaitingMillis = 0L;
/**
* The data stall recovery manager callback. Note this is only used for passing information
@@ -476,9 +481,8 @@
// Copy the values from the durationMillisArray array to the
// mDataStallRecoveryDelayMillisArray array.
- for (int i = 0; i < minLength; i++) {
- mDataStallRecoveryDelayMillisArray[i] = durationMillisArray[i];
- }
+ System.arraycopy(durationMillisArray, 0, mDataStallRecoveryDelayMillisArray,
+ 0, minLength);
log("DataStallRecoveryDelayMillis: "
+ Arrays.toString(mDataStallRecoveryDelayMillisArray));
mPredictWaitingMillis = DSRM_PREDICT_WAITING_MILLIS;
@@ -574,7 +578,7 @@
if (isValid) {
if (mFeatureFlags.dsrsDiagnosticsEnabled()) {
// Broadcast intent that data stall recovered.
- broadcastDataStallDetected(getRecoveryAction());
+ broadcastDataStallDetected(mLastAction);
}
reset();
} else if (isRecoveryNeeded(true)) {
@@ -695,7 +699,7 @@
// Get the information for DSRS state
final boolean isRecovered = !mDataStalled;
final int duration = (int) (SystemClock.elapsedRealtime() - mDataStallStartMs);
- final @RecoveredReason int reason = getRecoveredReason(mIsValidNetwork);
+ @RecoveredReason final int reason = getRecoveredReason(mIsValidNetwork);
final int durationOfAction = (int) getDurationOfCurrentRecoveryMs();
if (mFeatureFlags.dsrsDiagnosticsEnabled()) {
log("mValidationCount=" + mValidationCount
@@ -723,7 +727,7 @@
private void cleanUpDataNetwork() {
log("cleanUpDataNetwork: notify clean up data network");
mDataStallRecoveryManagerCallback.invokeFromExecutor(
- () -> mDataStallRecoveryManagerCallback.onDataStallReestablishInternet());
+ mDataStallRecoveryManagerCallback::onDataStallReestablishInternet);
}
/** Recovery Action: RECOVERY_ACTION_RADIO_RESTART */
@@ -828,7 +832,7 @@
private void setNetworkValidationState(boolean isValid) {
boolean isLogNeeded = false;
int timeDuration = 0;
- int timeDurationOfCurrentAction = 0;
+ int timeDurationOfCurrentAction;
boolean isFirstDataStall = false;
boolean isFirstValidationAfterDoRecovery = false;
@RecoveredReason int reason = getRecoveredReason(isValid);
@@ -872,7 +876,7 @@
isFirstValidationAfterDoRecovery, timeDurationOfCurrentAction);
logl(
"data stall: "
- + (isFirstDataStall == true ? "start" : isValid == false ? "in process" : "end")
+ + (isFirstDataStall ? "start" : !isValid ? "in process" : "end")
+ ", lastaction="
+ recoveryActionToString(mLastAction)
+ ", isRecovered="
@@ -902,9 +906,6 @@
if (mLastAction <= RECOVERY_ACTION_CLEANUP) {
ret = RECOVERED_REASON_MODEM;
}
- if (mLastAction > RECOVERY_ACTION_CLEANUP) {
- ret = RECOVERED_REASON_DSRM;
- }
if (mIsAirPlaneModeEnableDuringDataStall) {
ret = RECOVERED_REASON_USER;
}
@@ -964,19 +965,15 @@
* @param reason The recovered reason.
* @return The recovered reason in string format.
*/
- private static @NonNull String recoveredReasonToString(@RecoveredReason int reason) {
- switch (reason) {
- case RECOVERED_REASON_NONE:
- return "RECOVERED_REASON_NONE";
- case RECOVERED_REASON_DSRM:
- return "RECOVERED_REASON_DSRM";
- case RECOVERED_REASON_MODEM:
- return "RECOVERED_REASON_MODEM";
- case RECOVERED_REASON_USER:
- return "RECOVERED_REASON_USER";
- default:
- return "Unknown(" + reason + ")";
- }
+ @NonNull
+ private static String recoveredReasonToString(@RecoveredReason int reason) {
+ return switch (reason) {
+ case RECOVERED_REASON_NONE -> "RECOVERED_REASON_NONE";
+ case RECOVERED_REASON_DSRM -> "RECOVERED_REASON_DSRM";
+ case RECOVERED_REASON_MODEM -> "RECOVERED_REASON_MODEM";
+ case RECOVERED_REASON_USER -> "RECOVERED_REASON_USER";
+ default -> "Unknown(" + reason + ")";
+ };
}
/**
@@ -985,17 +982,14 @@
* @param state The radio power state
* @return The radio power state in string format.
*/
- private static @NonNull String radioPowerStateToString(@RadioPowerState int state) {
- switch (state) {
- case TelephonyManager.RADIO_POWER_OFF:
- return "RADIO_POWER_OFF";
- case TelephonyManager.RADIO_POWER_ON:
- return "RADIO_POWER_ON";
- case TelephonyManager.RADIO_POWER_UNAVAILABLE:
- return "RADIO_POWER_UNAVAILABLE";
- default:
- return "Unknown(" + state + ")";
- }
+ @NonNull
+ private static String radioPowerStateToString(@RadioPowerState int state) {
+ return switch (state) {
+ case TelephonyManager.RADIO_POWER_OFF -> "RADIO_POWER_OFF";
+ case TelephonyManager.RADIO_POWER_ON -> "RADIO_POWER_ON";
+ case TelephonyManager.RADIO_POWER_UNAVAILABLE -> "RADIO_POWER_UNAVAILABLE";
+ default -> "Unknown(" + state + ")";
+ };
}
/**
@@ -1004,19 +998,15 @@
* @param action The recovery action
* @return The recovery action in string format.
*/
- private static @NonNull String recoveryActionToString(@RecoveryAction int action) {
- switch (action) {
- case RECOVERY_ACTION_GET_DATA_CALL_LIST:
- return "RECOVERY_ACTION_GET_DATA_CALL_LIST";
- case RECOVERY_ACTION_CLEANUP:
- return "RECOVERY_ACTION_CLEANUP";
- case RECOVERY_ACTION_RADIO_RESTART:
- return "RECOVERY_ACTION_RADIO_RESTART";
- case RECOVERY_ACTION_RESET_MODEM:
- return "RECOVERY_ACTION_RESET_MODEM";
- default:
- return "Unknown(" + action + ")";
- }
+ @NonNull
+ private static String recoveryActionToString(@RecoveryAction int action) {
+ return switch (action) {
+ case RECOVERY_ACTION_GET_DATA_CALL_LIST -> "RECOVERY_ACTION_GET_DATA_CALL_LIST";
+ case RECOVERY_ACTION_CLEANUP -> "RECOVERY_ACTION_CLEANUP";
+ case RECOVERY_ACTION_RADIO_RESTART -> "RECOVERY_ACTION_RADIO_RESTART";
+ case RECOVERY_ACTION_RESET_MODEM -> "RECOVERY_ACTION_RESET_MODEM";
+ default -> "Unknown(" + action + ")";
+ };
}
/**
diff --git a/src/java/com/android/internal/telephony/data/DataUtils.java b/src/java/com/android/internal/telephony/data/DataUtils.java
index 0dda7b5..20da97f 100644
--- a/src/java/com/android/internal/telephony/data/DataUtils.java
+++ b/src/java/com/android/internal/telephony/data/DataUtils.java
@@ -27,6 +27,7 @@
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
import android.telephony.AccessNetworkConstants.TransportType;
+import android.telephony.Annotation.ConnectivityTransport;
import android.telephony.Annotation.DataActivityType;
import android.telephony.Annotation.NetCapability;
import android.telephony.Annotation.NetworkType;
@@ -36,11 +37,11 @@
import android.telephony.data.ApnSetting.ApnType;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataCallResponse.LinkStatus;
-import android.telephony.data.DataProfile;
import android.telephony.ims.feature.ImsFeature;
import android.util.ArrayMap;
import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.telephony.Rlog;
import java.text.SimpleDateFormat;
@@ -48,7 +49,6 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -59,6 +59,7 @@
* This class contains all the utility methods used by telephony data stack.
*/
public class DataUtils {
+ public static final int NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED = 37;
/** The time format for converting time to readable string. */
private static final SimpleDateFormat TIME_FORMAT =
new SimpleDateFormat("HH:mm:ss.SSS", Locale.US);
@@ -70,32 +71,30 @@
* @param capabilityString The capability in string format
* @return The network capability. -1 if not found.
*/
- public static @NetCapability int getNetworkCapabilityFromString(
- @NonNull String capabilityString) {
- switch (capabilityString.toUpperCase(Locale.ROOT)) {
- case "MMS": return NetworkCapabilities.NET_CAPABILITY_MMS;
- case "SUPL": return NetworkCapabilities.NET_CAPABILITY_SUPL;
- case "DUN": return NetworkCapabilities.NET_CAPABILITY_DUN;
- case "FOTA": return NetworkCapabilities.NET_CAPABILITY_FOTA;
- case "IMS": return NetworkCapabilities.NET_CAPABILITY_IMS;
- case "CBS": return NetworkCapabilities.NET_CAPABILITY_CBS;
- case "XCAP": return NetworkCapabilities.NET_CAPABILITY_XCAP;
- case "EIMS": return NetworkCapabilities.NET_CAPABILITY_EIMS;
- case "INTERNET": return NetworkCapabilities.NET_CAPABILITY_INTERNET;
- case "MCX": return NetworkCapabilities.NET_CAPABILITY_MCX;
- case "VSIM": return NetworkCapabilities.NET_CAPABILITY_VSIM;
- case "BIP" : return NetworkCapabilities.NET_CAPABILITY_BIP;
- case "ENTERPRISE": return NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
- case "PRIORITIZE_BANDWIDTH":
- return NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH;
- case "PRIORITIZE_LATENCY":
- return NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY;
- case "RCS":
- return NetworkCapabilities.NET_CAPABILITY_RCS;
- default:
+ @NetCapability
+ public static int getNetworkCapabilityFromString(@NonNull String capabilityString) {
+ return switch (capabilityString.toUpperCase(Locale.ROOT)) {
+ case "MMS" -> NetworkCapabilities.NET_CAPABILITY_MMS;
+ case "SUPL" -> NetworkCapabilities.NET_CAPABILITY_SUPL;
+ case "DUN" -> NetworkCapabilities.NET_CAPABILITY_DUN;
+ case "FOTA" -> NetworkCapabilities.NET_CAPABILITY_FOTA;
+ case "IMS" -> NetworkCapabilities.NET_CAPABILITY_IMS;
+ case "CBS" -> NetworkCapabilities.NET_CAPABILITY_CBS;
+ case "XCAP" -> NetworkCapabilities.NET_CAPABILITY_XCAP;
+ case "EIMS" -> NetworkCapabilities.NET_CAPABILITY_EIMS;
+ case "INTERNET" -> NetworkCapabilities.NET_CAPABILITY_INTERNET;
+ case "MCX" -> NetworkCapabilities.NET_CAPABILITY_MCX;
+ case "VSIM" -> NetworkCapabilities.NET_CAPABILITY_VSIM;
+ case "BIP" -> NetworkCapabilities.NET_CAPABILITY_BIP;
+ case "ENTERPRISE" -> NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
+ case "PRIORITIZE_BANDWIDTH" -> NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH;
+ case "PRIORITIZE_LATENCY" -> NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY;
+ case "RCS" -> NetworkCapabilities.NET_CAPABILITY_RCS;
+ default -> {
loge("Illegal network capability: " + capabilityString);
- return -1;
- }
+ yield -1;
+ }
+ };
}
/**
@@ -106,7 +105,8 @@
* @param capabilitiesString capability strings joined by {@code |}
* @return Set of capabilities
*/
- public static @NetCapability Set<Integer> getNetworkCapabilitiesFromString(
+ @NetCapability
+ public static Set<Integer> getNetworkCapabilitiesFromString(
@NonNull String capabilitiesString) {
// e.g. "IMS|" is not allowed
if (!capabilitiesString.matches("(\\s*[a-zA-Z_]+\\s*)(\\|\\s*[a-zA-Z_]+\\s*)*")) {
@@ -120,69 +120,108 @@
/**
* Convert a network capability to string.
- *
+ * <p>
* This is for debugging and logging purposes only.
*
* @param netCap Network capability.
* @return Network capability in string format.
*/
- public static @NonNull String networkCapabilityToString(@NetCapability int netCap) {
- switch (netCap) {
- case NetworkCapabilities.NET_CAPABILITY_MMS: return "MMS";
- case NetworkCapabilities.NET_CAPABILITY_SUPL: return "SUPL";
- case NetworkCapabilities.NET_CAPABILITY_DUN: return "DUN";
- case NetworkCapabilities.NET_CAPABILITY_FOTA: return "FOTA";
- case NetworkCapabilities.NET_CAPABILITY_IMS: return "IMS";
- case NetworkCapabilities.NET_CAPABILITY_CBS: return "CBS";
- case NetworkCapabilities.NET_CAPABILITY_WIFI_P2P: return "WIFI_P2P";
- case NetworkCapabilities.NET_CAPABILITY_IA: return "IA";
- case NetworkCapabilities.NET_CAPABILITY_RCS: return "RCS";
- case NetworkCapabilities.NET_CAPABILITY_XCAP: return "XCAP";
- case NetworkCapabilities.NET_CAPABILITY_EIMS: return "EIMS";
- case NetworkCapabilities.NET_CAPABILITY_NOT_METERED: return "NOT_METERED";
- case NetworkCapabilities.NET_CAPABILITY_INTERNET: return "INTERNET";
- case NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED: return "NOT_RESTRICTED";
- case NetworkCapabilities.NET_CAPABILITY_TRUSTED: return "TRUSTED";
- case NetworkCapabilities.NET_CAPABILITY_NOT_VPN: return "NOT_VPN";
- case NetworkCapabilities.NET_CAPABILITY_VALIDATED: return "VALIDATED";
- case NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL";
- case NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING: return "NOT_ROAMING";
- case NetworkCapabilities.NET_CAPABILITY_FOREGROUND: return "FOREGROUND";
- case NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED: return "NOT_CONGESTED";
- case NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED: return "NOT_SUSPENDED";
- case NetworkCapabilities.NET_CAPABILITY_OEM_PAID: return "OEM_PAID";
- case NetworkCapabilities.NET_CAPABILITY_MCX: return "MCX";
- case NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY:
- return "PARTIAL_CONNECTIVITY";
- case NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED:
- return "TEMPORARILY_NOT_METERED";
- case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE: return "OEM_PRIVATE";
- case NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL: return "VEHICLE_INTERNAL";
- case NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED: return "NOT_VCN_MANAGED";
- case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE: return "ENTERPRISE";
- case NetworkCapabilities.NET_CAPABILITY_VSIM: return "VSIM";
- case NetworkCapabilities.NET_CAPABILITY_BIP: return "BIP";
- case NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT: return "HEAD_UNIT";
- case NetworkCapabilities.NET_CAPABILITY_MMTEL: return "MMTEL";
- case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY:
- return "PRIORITIZE_LATENCY";
- case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH:
- return "PRIORITIZE_BANDWIDTH";
- default:
+ @NonNull
+ public static String networkCapabilityToString(@NetCapability int netCap) {
+ return switch (netCap) {
+ case NetworkCapabilities.NET_CAPABILITY_MMS -> "MMS";
+ case NetworkCapabilities.NET_CAPABILITY_SUPL -> "SUPL";
+ case NetworkCapabilities.NET_CAPABILITY_DUN -> "DUN";
+ case NetworkCapabilities.NET_CAPABILITY_FOTA -> "FOTA";
+ case NetworkCapabilities.NET_CAPABILITY_IMS -> "IMS";
+ case NetworkCapabilities.NET_CAPABILITY_CBS -> "CBS";
+ case NetworkCapabilities.NET_CAPABILITY_WIFI_P2P -> "WIFI_P2P";
+ case NetworkCapabilities.NET_CAPABILITY_IA -> "IA";
+ case NetworkCapabilities.NET_CAPABILITY_RCS -> "RCS";
+ case NetworkCapabilities.NET_CAPABILITY_XCAP -> "XCAP";
+ case NetworkCapabilities.NET_CAPABILITY_EIMS -> "EIMS";
+ case NetworkCapabilities.NET_CAPABILITY_NOT_METERED -> "NOT_METERED";
+ case NetworkCapabilities.NET_CAPABILITY_INTERNET -> "INTERNET";
+ case NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED -> "NOT_RESTRICTED";
+ case NetworkCapabilities.NET_CAPABILITY_TRUSTED -> "TRUSTED";
+ case NetworkCapabilities.NET_CAPABILITY_NOT_VPN -> "NOT_VPN";
+ case NetworkCapabilities.NET_CAPABILITY_VALIDATED -> "VALIDATED";
+ case NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL -> "CAPTIVE_PORTAL";
+ case NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING -> "NOT_ROAMING";
+ case NetworkCapabilities.NET_CAPABILITY_FOREGROUND -> "FOREGROUND";
+ case NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED -> "NOT_CONGESTED";
+ case NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED -> "NOT_SUSPENDED";
+ case NetworkCapabilities.NET_CAPABILITY_OEM_PAID -> "OEM_PAID";
+ case NetworkCapabilities.NET_CAPABILITY_MCX -> "MCX";
+ case NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY -> "PARTIAL_CONNECTIVITY";
+ case NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED ->
+ "TEMPORARILY_NOT_METERED";
+ case NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE -> "OEM_PRIVATE";
+ case NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL -> "VEHICLE_INTERNAL";
+ case NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED -> "NOT_VCN_MANAGED";
+ case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE -> "ENTERPRISE";
+ case NetworkCapabilities.NET_CAPABILITY_VSIM -> "VSIM";
+ case NetworkCapabilities.NET_CAPABILITY_BIP -> "BIP";
+ case NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT -> "HEAD_UNIT";
+ case NetworkCapabilities.NET_CAPABILITY_MMTEL -> "MMTEL";
+ case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY -> "PRIORITIZE_LATENCY";
+ case NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH -> "PRIORITIZE_BANDWIDTH";
+ case NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED -> "NOT_BANDWIDTH_CONSTRAINED";
+ default -> {
loge("Unknown network capability(" + netCap + ")");
- return "Unknown(" + netCap + ")";
- }
+ yield "Unknown(" + netCap + ")";
+ }
+ };
+ }
+
+ /**
+ * Concat an array of {@link NetworkCapabilities.Transport} in string format.
+ *
+ * @param transports an array of connectivity transports
+ * @return a string of the array of transports.
+ */
+ @NonNull
+ public static String connectivityTransportsToString(
+ @NonNull @ConnectivityTransport int[] transports) {
+ return Arrays.stream(transports).mapToObj(DataUtils::connectivityTransportToString)
+ .collect(Collectors.joining("|"));
+ }
+
+ /**
+ * Convert a {@link NetworkCapabilities.Transport} to a string.
+ *
+ * @param transport the connectivity transport
+ * @return the transport in string
+ */
+ @NonNull
+ public static String connectivityTransportToString(
+ @ConnectivityTransport int transport) {
+ return switch (transport) {
+ case NetworkCapabilities.TRANSPORT_CELLULAR -> "CELLULAR";
+ case NetworkCapabilities.TRANSPORT_WIFI -> "WIFI";
+ case NetworkCapabilities.TRANSPORT_BLUETOOTH -> "BLUETOOTH";
+ case NetworkCapabilities.TRANSPORT_ETHERNET -> "ETHERNET";
+ case NetworkCapabilities.TRANSPORT_VPN -> "VPN";
+ case NetworkCapabilities.TRANSPORT_WIFI_AWARE -> "WIFI_AWARE";
+ case NetworkCapabilities.TRANSPORT_LOWPAN -> "LOWPAN";
+ case NetworkCapabilities.TRANSPORT_TEST -> "TEST";
+ case NetworkCapabilities.TRANSPORT_USB -> "USB";
+ case NetworkCapabilities.TRANSPORT_THREAD -> "THREAD";
+ case NetworkCapabilities.TRANSPORT_SATELLITE -> "SATELLITE";
+ default -> "Unknown(" + transport + ")";
+ };
}
/**
* Convert network capabilities to string.
- *
+ * <p>
* This is for debugging and logging purposes only.
*
* @param netCaps Network capabilities.
* @return Network capabilities in string format.
*/
- public static @NonNull String networkCapabilitiesToString(
+ @NonNull
+ public static String networkCapabilitiesToString(
@NetCapability @Nullable Collection<Integer> netCaps) {
if (netCaps == null || netCaps.isEmpty()) return "";
return "[" + netCaps.stream()
@@ -192,13 +231,14 @@
/**
* Convert network capabilities to string.
- *
+ * <p>
* This is for debugging and logging purposes only.
*
* @param netCaps Network capabilities.
* @return Network capabilities in string format.
*/
- public static @NonNull String networkCapabilitiesToString(@NetCapability int[] netCaps) {
+ @NonNull
+ public static String networkCapabilitiesToString(@NetCapability int[] netCaps) {
if (netCaps == null) return "";
return "[" + Arrays.stream(netCaps)
.mapToObj(DataUtils::networkCapabilityToString)
@@ -211,14 +251,16 @@
* @param status The validation status.
* @return The validation status in string format.
*/
- public static @NonNull String validationStatusToString(@ValidationStatus int status) {
- switch (status) {
- case NetworkAgent.VALIDATION_STATUS_VALID: return "VALID";
- case NetworkAgent.VALIDATION_STATUS_NOT_VALID: return "INVALID";
- default:
+ @NonNull
+ public static String validationStatusToString(@ValidationStatus int status) {
+ return switch (status) {
+ case NetworkAgent.VALIDATION_STATUS_VALID -> "VALID";
+ case NetworkAgent.VALIDATION_STATUS_NOT_VALID -> "INVALID";
+ default -> {
loge("Unknown validation status(" + status + ")");
- return "UNKNOWN(" + status + ")";
- }
+ yield "UNKNOWN(" + status + ")";
+ }
+ };
}
/**
@@ -227,41 +269,26 @@
* @param networkCapability Network capability.
* @return APN type.
*/
- public static @ApnType int networkCapabilityToApnType(@NetCapability int networkCapability) {
- switch (networkCapability) {
- case NetworkCapabilities.NET_CAPABILITY_MMS:
- return ApnSetting.TYPE_MMS;
- case NetworkCapabilities.NET_CAPABILITY_SUPL:
- return ApnSetting.TYPE_SUPL;
- case NetworkCapabilities.NET_CAPABILITY_DUN:
- return ApnSetting.TYPE_DUN;
- case NetworkCapabilities.NET_CAPABILITY_FOTA:
- return ApnSetting.TYPE_FOTA;
- case NetworkCapabilities.NET_CAPABILITY_IMS:
- return ApnSetting.TYPE_IMS;
- case NetworkCapabilities.NET_CAPABILITY_CBS:
- return ApnSetting.TYPE_CBS;
- case NetworkCapabilities.NET_CAPABILITY_XCAP:
- return ApnSetting.TYPE_XCAP;
- case NetworkCapabilities.NET_CAPABILITY_EIMS:
- return ApnSetting.TYPE_EMERGENCY;
- case NetworkCapabilities.NET_CAPABILITY_INTERNET:
- return ApnSetting.TYPE_DEFAULT;
- case NetworkCapabilities.NET_CAPABILITY_MCX:
- return ApnSetting.TYPE_MCX;
- case NetworkCapabilities.NET_CAPABILITY_IA:
- return ApnSetting.TYPE_IA;
- case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE:
- return ApnSetting.TYPE_ENTERPRISE;
- case NetworkCapabilities.NET_CAPABILITY_VSIM:
- return ApnSetting.TYPE_VSIM;
- case NetworkCapabilities.NET_CAPABILITY_BIP:
- return ApnSetting.TYPE_BIP;
- case NetworkCapabilities.NET_CAPABILITY_RCS:
- return ApnSetting.TYPE_RCS;
- default:
- return ApnSetting.TYPE_NONE;
- }
+ @ApnType
+ public static int networkCapabilityToApnType(@NetCapability int networkCapability) {
+ return switch (networkCapability) {
+ case NetworkCapabilities.NET_CAPABILITY_MMS -> ApnSetting.TYPE_MMS;
+ case NetworkCapabilities.NET_CAPABILITY_SUPL -> ApnSetting.TYPE_SUPL;
+ case NetworkCapabilities.NET_CAPABILITY_DUN -> ApnSetting.TYPE_DUN;
+ case NetworkCapabilities.NET_CAPABILITY_FOTA -> ApnSetting.TYPE_FOTA;
+ case NetworkCapabilities.NET_CAPABILITY_IMS -> ApnSetting.TYPE_IMS;
+ case NetworkCapabilities.NET_CAPABILITY_CBS -> ApnSetting.TYPE_CBS;
+ case NetworkCapabilities.NET_CAPABILITY_XCAP -> ApnSetting.TYPE_XCAP;
+ case NetworkCapabilities.NET_CAPABILITY_EIMS -> ApnSetting.TYPE_EMERGENCY;
+ case NetworkCapabilities.NET_CAPABILITY_INTERNET -> ApnSetting.TYPE_DEFAULT;
+ case NetworkCapabilities.NET_CAPABILITY_MCX -> ApnSetting.TYPE_MCX;
+ case NetworkCapabilities.NET_CAPABILITY_IA -> ApnSetting.TYPE_IA;
+ case NetworkCapabilities.NET_CAPABILITY_ENTERPRISE -> ApnSetting.TYPE_ENTERPRISE;
+ case NetworkCapabilities.NET_CAPABILITY_VSIM -> ApnSetting.TYPE_VSIM;
+ case NetworkCapabilities.NET_CAPABILITY_BIP -> ApnSetting.TYPE_BIP;
+ case NetworkCapabilities.NET_CAPABILITY_RCS -> ApnSetting.TYPE_RCS;
+ default -> ApnSetting.TYPE_NONE;
+ };
}
/**
@@ -270,41 +297,26 @@
* @param apnType APN type.
* @return Network capability.
*/
- public static @NetCapability int apnTypeToNetworkCapability(@ApnType int apnType) {
- switch (apnType) {
- case ApnSetting.TYPE_MMS:
- return NetworkCapabilities.NET_CAPABILITY_MMS;
- case ApnSetting.TYPE_SUPL:
- return NetworkCapabilities.NET_CAPABILITY_SUPL;
- case ApnSetting.TYPE_DUN:
- return NetworkCapabilities.NET_CAPABILITY_DUN;
- case ApnSetting.TYPE_FOTA:
- return NetworkCapabilities.NET_CAPABILITY_FOTA;
- case ApnSetting.TYPE_IMS:
- return NetworkCapabilities.NET_CAPABILITY_IMS;
- case ApnSetting.TYPE_CBS:
- return NetworkCapabilities.NET_CAPABILITY_CBS;
- case ApnSetting.TYPE_XCAP:
- return NetworkCapabilities.NET_CAPABILITY_XCAP;
- case ApnSetting.TYPE_EMERGENCY:
- return NetworkCapabilities.NET_CAPABILITY_EIMS;
- case ApnSetting.TYPE_DEFAULT:
- return NetworkCapabilities.NET_CAPABILITY_INTERNET;
- case ApnSetting.TYPE_MCX:
- return NetworkCapabilities.NET_CAPABILITY_MCX;
- case ApnSetting.TYPE_IA:
- return NetworkCapabilities.NET_CAPABILITY_IA;
- case ApnSetting.TYPE_BIP:
- return NetworkCapabilities.NET_CAPABILITY_BIP;
- case ApnSetting.TYPE_VSIM:
- return NetworkCapabilities.NET_CAPABILITY_VSIM;
- case ApnSetting.TYPE_ENTERPRISE:
- return NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
- case ApnSetting.TYPE_RCS:
- return NetworkCapabilities.NET_CAPABILITY_RCS;
- default:
- return -1;
- }
+ @NetCapability
+ public static int apnTypeToNetworkCapability(@ApnType int apnType) {
+ return switch (apnType) {
+ case ApnSetting.TYPE_MMS -> NetworkCapabilities.NET_CAPABILITY_MMS;
+ case ApnSetting.TYPE_SUPL -> NetworkCapabilities.NET_CAPABILITY_SUPL;
+ case ApnSetting.TYPE_DUN -> NetworkCapabilities.NET_CAPABILITY_DUN;
+ case ApnSetting.TYPE_FOTA -> NetworkCapabilities.NET_CAPABILITY_FOTA;
+ case ApnSetting.TYPE_IMS -> NetworkCapabilities.NET_CAPABILITY_IMS;
+ case ApnSetting.TYPE_CBS -> NetworkCapabilities.NET_CAPABILITY_CBS;
+ case ApnSetting.TYPE_XCAP -> NetworkCapabilities.NET_CAPABILITY_XCAP;
+ case ApnSetting.TYPE_EMERGENCY -> NetworkCapabilities.NET_CAPABILITY_EIMS;
+ case ApnSetting.TYPE_DEFAULT -> NetworkCapabilities.NET_CAPABILITY_INTERNET;
+ case ApnSetting.TYPE_MCX -> NetworkCapabilities.NET_CAPABILITY_MCX;
+ case ApnSetting.TYPE_IA -> NetworkCapabilities.NET_CAPABILITY_IA;
+ case ApnSetting.TYPE_BIP -> NetworkCapabilities.NET_CAPABILITY_BIP;
+ case ApnSetting.TYPE_VSIM -> NetworkCapabilities.NET_CAPABILITY_VSIM;
+ case ApnSetting.TYPE_ENTERPRISE -> NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
+ case ApnSetting.TYPE_RCS -> NetworkCapabilities.NET_CAPABILITY_RCS;
+ default -> -1;
+ };
}
/**
@@ -313,37 +325,26 @@
* @param networkType The network type.
* @return The access network type.
*/
- public static @RadioAccessNetworkType int networkTypeToAccessNetworkType(
- @NetworkType int networkType) {
- switch (networkType) {
- case TelephonyManager.NETWORK_TYPE_GPRS:
- case TelephonyManager.NETWORK_TYPE_EDGE:
- case TelephonyManager.NETWORK_TYPE_GSM:
- return AccessNetworkType.GERAN;
- case TelephonyManager.NETWORK_TYPE_UMTS:
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- case TelephonyManager.NETWORK_TYPE_HSPA:
- case TelephonyManager.NETWORK_TYPE_TD_SCDMA:
- return AccessNetworkType.UTRAN;
- case TelephonyManager.NETWORK_TYPE_CDMA:
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- return AccessNetworkType.CDMA2000;
- case TelephonyManager.NETWORK_TYPE_LTE:
- case TelephonyManager.NETWORK_TYPE_LTE_CA:
- return AccessNetworkType.EUTRAN;
- case TelephonyManager.NETWORK_TYPE_IWLAN:
- return AccessNetworkType.IWLAN;
- case TelephonyManager.NETWORK_TYPE_NR:
- return AccessNetworkType.NGRAN;
- default:
- return AccessNetworkType.UNKNOWN;
- }
+ @RadioAccessNetworkType
+ public static int networkTypeToAccessNetworkType(@NetworkType int networkType) {
+ return switch (networkType) {
+ case TelephonyManager.NETWORK_TYPE_GPRS, TelephonyManager.NETWORK_TYPE_EDGE,
+ TelephonyManager.NETWORK_TYPE_GSM ->
+ AccessNetworkType.GERAN;
+ case TelephonyManager.NETWORK_TYPE_UMTS, TelephonyManager.NETWORK_TYPE_HSDPA,
+ TelephonyManager.NETWORK_TYPE_HSPAP, TelephonyManager.NETWORK_TYPE_HSUPA,
+ TelephonyManager.NETWORK_TYPE_HSPA, TelephonyManager.NETWORK_TYPE_TD_SCDMA ->
+ AccessNetworkType.UTRAN;
+ case TelephonyManager.NETWORK_TYPE_CDMA, TelephonyManager.NETWORK_TYPE_EVDO_0,
+ TelephonyManager.NETWORK_TYPE_EVDO_A, TelephonyManager.NETWORK_TYPE_EVDO_B,
+ TelephonyManager.NETWORK_TYPE_1xRTT, TelephonyManager.NETWORK_TYPE_EHRPD ->
+ AccessNetworkType.CDMA2000;
+ case TelephonyManager.NETWORK_TYPE_LTE, TelephonyManager.NETWORK_TYPE_LTE_CA ->
+ AccessNetworkType.EUTRAN;
+ case TelephonyManager.NETWORK_TYPE_IWLAN -> AccessNetworkType.IWLAN;
+ case TelephonyManager.NETWORK_TYPE_NR -> AccessNetworkType.NGRAN;
+ default -> AccessNetworkType.UNKNOWN;
+ };
}
/**
@@ -352,7 +353,8 @@
* @param elapsedTime The elapsed time retrieved from {@link SystemClock#elapsedRealtime()}.
* @return The string format time.
*/
- public static @NonNull String elapsedTimeToString(@ElapsedRealtimeLong long elapsedTime) {
+ @NonNull
+ public static String elapsedTimeToString(@ElapsedRealtimeLong long elapsedTime) {
return (elapsedTime != 0) ? systemTimeToString(System.currentTimeMillis()
- SystemClock.elapsedRealtime() + elapsedTime) : "never";
}
@@ -363,7 +365,8 @@
* @param systemTime The system time retrieved from {@link System#currentTimeMillis()}.
* @return The string format time.
*/
- public static @NonNull String systemTimeToString(@CurrentTimeMillisLong long systemTime) {
+ @NonNull
+ public static String systemTimeToString(@CurrentTimeMillisLong long systemTime) {
return (systemTime != 0) ? TIME_FORMAT.format(systemTime) : "never";
}
@@ -373,68 +376,75 @@
* @param imsFeature IMS feature.
* @return IMS feature in string format.
*/
- public static @NonNull String imsFeatureToString(@ImsFeature.FeatureType int imsFeature) {
- switch (imsFeature) {
- case ImsFeature.FEATURE_MMTEL: return "MMTEL";
- case ImsFeature.FEATURE_RCS: return "RCS";
- default:
+ @NonNull
+ public static String imsFeatureToString(@ImsFeature.FeatureType int imsFeature) {
+ return switch (imsFeature) {
+ case ImsFeature.FEATURE_MMTEL -> "MMTEL";
+ case ImsFeature.FEATURE_RCS -> "RCS";
+ default -> {
loge("Unknown IMS feature(" + imsFeature + ")");
- return "Unknown(" + imsFeature + ")";
- }
- }
-
- /**
- * Get the highest priority supported network capability from the specified data profile.
- *
- * @param dataConfigManager The data config that contains network priority information.
- * @param dataProfile The data profile
- * @return The highest priority network capability. -1 if cannot find one.
- */
- public static @NetCapability int getHighestPriorityNetworkCapabilityFromDataProfile(
- @NonNull DataConfigManager dataConfigManager, @NonNull DataProfile dataProfile) {
- if (dataProfile.getApnSetting() == null
- || dataProfile.getApnSetting().getApnTypes().isEmpty()) return -1;
- return dataProfile.getApnSetting().getApnTypes().stream()
- .map(DataUtils::apnTypeToNetworkCapability)
- .sorted(Comparator.comparing(dataConfigManager::getNetworkCapabilityPriority)
- .reversed())
- .collect(Collectors.toList())
- .get(0);
+ yield "Unknown(" + imsFeature + ")";
+ }
+ };
}
/**
* Group the network requests into several list that contains the same network capabilities.
*
* @param networkRequestList The provided network requests.
+ * @param featureFlags The feature flag.
+ *
* @return The network requests after grouping.
*/
- public static @NonNull List<NetworkRequestList> getGroupedNetworkRequestList(
- @NonNull NetworkRequestList networkRequestList) {
- // Key is the capabilities set.
- Map<Set<Integer>, NetworkRequestList> requestsMap = new ArrayMap<>();
- for (TelephonyNetworkRequest networkRequest : networkRequestList) {
- requestsMap.computeIfAbsent(Arrays.stream(networkRequest.getCapabilities())
- .boxed().collect(Collectors.toSet()),
- v -> new NetworkRequestList()).add(networkRequest);
- }
+ @NonNull
+ public static List<NetworkRequestList> getGroupedNetworkRequestList(
+ @NonNull NetworkRequestList networkRequestList, @NonNull FeatureFlags featureFlags) {
List<NetworkRequestList> requests = new ArrayList<>();
- // Create separate groups for enterprise requests with different enterprise IDs.
- for (NetworkRequestList requestList : requestsMap.values()) {
- List<TelephonyNetworkRequest> enterpriseRequests = requestList.stream()
- .filter(request ->
- request.hasCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE))
- .collect(Collectors.toList());
- if (enterpriseRequests.isEmpty()) {
- requests.add(requestList);
- continue;
+ if (featureFlags.satelliteInternet()) {
+ record NetworkCapabilitiesKey(Set<Integer> caps, Set<Integer> enterpriseIds,
+ Set<Integer> transportTypes) { }
+
+ // Key is the combination of capabilities, enterprise ids, and transport types.
+ Map<NetworkCapabilitiesKey, NetworkRequestList> requestsMap = new ArrayMap<>();
+ for (TelephonyNetworkRequest networkRequest : networkRequestList) {
+ requestsMap.computeIfAbsent(new NetworkCapabilitiesKey(
+ Arrays.stream(networkRequest.getCapabilities())
+ .boxed().collect(Collectors.toSet()),
+ Arrays.stream(networkRequest.getNativeNetworkRequest()
+ .getEnterpriseIds())
+ .boxed().collect(Collectors.toSet()),
+ Arrays.stream(networkRequest.getTransportTypes())
+ .boxed().collect(Collectors.toSet())
+ ),
+ v -> new NetworkRequestList()).add(networkRequest);
}
- // Key is the enterprise ID
- Map<Integer, NetworkRequestList> enterpriseRequestsMap = new ArrayMap<>();
- for (TelephonyNetworkRequest request : enterpriseRequests) {
- enterpriseRequestsMap.computeIfAbsent(request.getCapabilityDifferentiator(),
- v -> new NetworkRequestList()).add(request);
+ requests.addAll(requestsMap.values());
+ } else {
+ // Key is the capabilities set.
+ Map<Set<Integer>, NetworkRequestList> requestsMap = new ArrayMap<>();
+ for (TelephonyNetworkRequest networkRequest : networkRequestList) {
+ requestsMap.computeIfAbsent(Arrays.stream(networkRequest.getCapabilities())
+ .boxed().collect(Collectors.toSet()),
+ v -> new NetworkRequestList()).add(networkRequest);
}
- requests.addAll(enterpriseRequestsMap.values());
+ // Create separate groups for enterprise requests with different enterprise IDs.
+ for (NetworkRequestList requestList : requestsMap.values()) {
+ List<TelephonyNetworkRequest> enterpriseRequests = requestList.stream()
+ .filter(request -> request.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_ENTERPRISE))
+ .toList();
+ if (enterpriseRequests.isEmpty()) {
+ requests.add(requestList);
+ continue;
+ }
+ // Key is the enterprise ID
+ Map<Integer, NetworkRequestList> enterpriseRequestsMap = new ArrayMap<>();
+ for (TelephonyNetworkRequest request : enterpriseRequests) {
+ enterpriseRequestsMap.computeIfAbsent(request.getCapabilityDifferentiator(),
+ v -> new NetworkRequestList()).add(request);
+ }
+ requests.addAll(enterpriseRequestsMap.values());
+ }
}
// Sort the requests so the network request list with higher priority will be at the front.
return requests.stream()
@@ -450,41 +460,31 @@
* @param sourceTransport The source transport.
* @return The target transport.
*/
- public static @TransportType int getTargetTransport(@TransportType int sourceTransport) {
+ @TransportType
+ public static int getTargetTransport(@TransportType int sourceTransport) {
return sourceTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
? AccessNetworkConstants.TRANSPORT_TYPE_WLAN
: AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
}
/**
- * Get the source transport from target transport. This is only used for handover between
- * IWLAN and cellular scenario.
- *
- * @param targetTransport The target transport.
- * @return The source transport.
- */
- public static @TransportType int getSourceTransport(@TransportType int targetTransport) {
- return targetTransport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
- ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN
- : AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
- }
-
- /**
* Convert link status to string.
*
* @param linkStatus The link status.
* @return The link status in string format.
*/
- public static @NonNull String linkStatusToString(@LinkStatus int linkStatus) {
- switch (linkStatus) {
- case DataCallResponse.LINK_STATUS_UNKNOWN: return "UNKNOWN";
- case DataCallResponse.LINK_STATUS_INACTIVE: return "INACTIVE";
- case DataCallResponse.LINK_STATUS_ACTIVE: return "ACTIVE";
- case DataCallResponse.LINK_STATUS_DORMANT: return "DORMANT";
- default:
+ @NonNull
+ public static String linkStatusToString(@LinkStatus int linkStatus) {
+ return switch (linkStatus) {
+ case DataCallResponse.LINK_STATUS_UNKNOWN -> "UNKNOWN";
+ case DataCallResponse.LINK_STATUS_INACTIVE -> "INACTIVE";
+ case DataCallResponse.LINK_STATUS_ACTIVE -> "ACTIVE";
+ case DataCallResponse.LINK_STATUS_DORMANT -> "DORMANT";
+ default -> {
loge("Unknown link status(" + linkStatus + ")");
- return "UNKNOWN(" + linkStatus + ")";
- }
+ yield "UNKNOWN(" + linkStatus + ")";
+ }
+ };
}
/**
@@ -494,17 +494,12 @@
* @return {@code true} if the access network type is valid.
*/
public static boolean isValidAccessNetwork(@RadioAccessNetworkType int accessNetworkType) {
- switch (accessNetworkType) {
- case AccessNetworkType.GERAN:
- case AccessNetworkType.UTRAN:
- case AccessNetworkType.EUTRAN:
- case AccessNetworkType.CDMA2000:
- case AccessNetworkType.IWLAN:
- case AccessNetworkType.NGRAN:
- return true;
- default:
- return false;
- }
+ return switch (accessNetworkType) {
+ case AccessNetworkType.GERAN, AccessNetworkType.UTRAN, AccessNetworkType.EUTRAN,
+ AccessNetworkType.CDMA2000, AccessNetworkType.IWLAN, AccessNetworkType.NGRAN ->
+ true;
+ default -> false;
+ };
}
/**
@@ -513,17 +508,19 @@
* @param dataActivity The data activity.
* @return The data activity in string format.
*/
- public static @NonNull String dataActivityToString(@DataActivityType int dataActivity) {
- switch (dataActivity) {
- case TelephonyManager.DATA_ACTIVITY_NONE: return "NONE";
- case TelephonyManager.DATA_ACTIVITY_IN: return "IN";
- case TelephonyManager.DATA_ACTIVITY_OUT: return "OUT";
- case TelephonyManager.DATA_ACTIVITY_INOUT: return "INOUT";
- case TelephonyManager.DATA_ACTIVITY_DORMANT: return "DORMANT";
- default:
+ @NonNull
+ public static String dataActivityToString(@DataActivityType int dataActivity) {
+ return switch (dataActivity) {
+ case TelephonyManager.DATA_ACTIVITY_NONE -> "NONE";
+ case TelephonyManager.DATA_ACTIVITY_IN -> "IN";
+ case TelephonyManager.DATA_ACTIVITY_OUT -> "OUT";
+ case TelephonyManager.DATA_ACTIVITY_INOUT -> "INOUT";
+ case TelephonyManager.DATA_ACTIVITY_DORMANT -> "DORMANT";
+ default -> {
loge("Unknown data activity(" + dataActivity + ")");
- return "UNKNOWN(" + dataActivity + ")";
- }
+ yield "UNKNOWN(" + dataActivity + ")";
+ }
+ };
}
private static void loge(String msg) {
diff --git a/src/java/com/android/internal/telephony/data/KeepaliveStatus.java b/src/java/com/android/internal/telephony/data/KeepaliveStatus.java
index 818de96..7b6c38d 100644
--- a/src/java/com/android/internal/telephony/data/KeepaliveStatus.java
+++ b/src/java/com/android/internal/telephony/data/KeepaliveStatus.java
@@ -23,7 +23,7 @@
/**
* This class serves to pass around the parameters of Keepalive session
* status within the telephony framework.
- *
+ * <p>
* {@hide}
*/
public class KeepaliveStatus implements Parcelable {
@@ -54,7 +54,8 @@
* A status code indicating whether this Keepalive session is
* active, inactive, or pending activation
*/
- public final @KeepaliveStatusCode int statusCode;
+ @KeepaliveStatusCode
+ public final int statusCode;
/** An error code indicating a lower layer failure, if any */
public final int errorCode;
@@ -98,7 +99,7 @@
}
public static final Parcelable.Creator<KeepaliveStatus> CREATOR =
- new Parcelable.Creator<KeepaliveStatus>() {
+ new Parcelable.Creator<>() {
@Override
public KeepaliveStatus createFromParcel(Parcel source) {
return new KeepaliveStatus(source);
diff --git a/src/java/com/android/internal/telephony/data/KeepaliveTracker.java b/src/java/com/android/internal/telephony/data/KeepaliveTracker.java
index f9139ec..f221779 100644
--- a/src/java/com/android/internal/telephony/data/KeepaliveTracker.java
+++ b/src/java/com/android/internal/telephony/data/KeepaliveTracker.java
@@ -56,19 +56,24 @@
private static final int EVENT_UNREGISTER_FOR_KEEPALIVE_STATUS = 5;
/** The phone instance. */
- private final @NonNull Phone mPhone;
+ @NonNull
+ private final Phone mPhone;
/** The parent data network. */
- private final @NonNull DataNetwork mDataNetwork;
+ @NonNull
+ private final DataNetwork mDataNetwork;
/** The associated network agent. */
- private final @NonNull TelephonyNetworkAgent mNetworkAgent;
+ @NonNull
+ private final TelephonyNetworkAgent mNetworkAgent;
/** The log tag. */
- private final @NonNull String mLogTag;
+ @NonNull
+ private final String mLogTag;
/** The keepalive records. */
- private final @NonNull SparseArray<KeepaliveRecord> mKeepalives = new SparseArray<>();
+ @NonNull
+ private final SparseArray<KeepaliveRecord> mKeepalives = new SparseArray<>();
/**
* Keepalive session record
@@ -78,7 +83,8 @@
public int slotIndex;
/** The current status. */
- public @KeepaliveStatusCode int currentStatus;
+ @KeepaliveStatusCode
+ public int currentStatus;
/**
* Constructor
@@ -254,17 +260,12 @@
* @return The socket alive error.
*/
private int keepaliveStatusErrorToPacketKeepaliveError(int error) {
- switch(error) {
- case KeepaliveStatus.ERROR_NONE:
- return SocketKeepalive.SUCCESS;
- case KeepaliveStatus.ERROR_UNSUPPORTED:
- return SocketKeepalive.ERROR_UNSUPPORTED;
- case KeepaliveStatus.ERROR_NO_RESOURCES:
- return SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES;
- case KeepaliveStatus.ERROR_UNKNOWN:
- default:
- return SocketKeepalive.ERROR_HARDWARE_ERROR;
- }
+ return switch (error) {
+ case KeepaliveStatus.ERROR_NONE -> SocketKeepalive.SUCCESS;
+ case KeepaliveStatus.ERROR_UNSUPPORTED -> SocketKeepalive.ERROR_UNSUPPORTED;
+ case KeepaliveStatus.ERROR_NO_RESOURCES -> SocketKeepalive.ERROR_INSUFFICIENT_RESOURCES;
+ default -> SocketKeepalive.ERROR_HARDWARE_ERROR;
+ };
}
/**
diff --git a/src/java/com/android/internal/telephony/data/LinkBandwidthEstimator.java b/src/java/com/android/internal/telephony/data/LinkBandwidthEstimator.java
index de8c48c..534f191 100644
--- a/src/java/com/android/internal/telephony/data/LinkBandwidthEstimator.java
+++ b/src/java/com/android/internal/telephony/data/LinkBandwidthEstimator.java
@@ -30,6 +30,7 @@
import android.os.AsyncResult;
import android.os.Handler;
import android.os.HandlerExecutor;
+import android.os.Looper;
import android.os.Message;
import android.os.OutcomeReceiver;
import android.preference.PreferenceManager;
@@ -165,7 +166,6 @@
private final Phone mPhone;
private final TelephonyFacade mTelephonyFacade;
private final TelephonyManager mTelephonyManager;
- private final ConnectivityManager mConnectivityManager;
private final LocalLog mLocalLog = new LocalLog(512);
private boolean mScreenOn = false;
private boolean mIsOnDefaultRoute = false;
@@ -185,22 +185,23 @@
private int mTac;
@NonNull private String mPlmn = UNKNOWN_PLMN;
private NetworkCapabilities mNetworkCapabilities;
- private NetworkBandwidth mPlaceholderNetwork;
+ private final NetworkBandwidth mPlaceholderNetwork;
private long mFilterUpdateTimeMs;
private int mBandwidthUpdateSignalDbm = -1;
private int mBandwidthUpdateSignalLevel = -1;
private int mBandwidthUpdateDataRat = TelephonyManager.NETWORK_TYPE_UNKNOWN;
private String mBandwidthUpdatePlmn = UNKNOWN_PLMN;
- private BandwidthState mTxState = new BandwidthState(LINK_TX);
- private BandwidthState mRxState = new BandwidthState(LINK_RX);
+ private final BandwidthState mTxState = new BandwidthState(LINK_TX);
+ private final BandwidthState mRxState = new BandwidthState(LINK_RX);
private long mLastPlmnOrRatChangeTimeMs;
private long mLastDrsOrRatChangeTimeMs;
private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE;
/** Link bandwidth estimator callbacks. */
- private final @NonNull Set<LinkBandwidthEstimatorCallback> mLinkBandwidthEstimatorCallbacks =
+ @NonNull
+ private final Set<LinkBandwidthEstimatorCallback> mLinkBandwidthEstimatorCallbacks =
new ArraySet<>();
/**
@@ -270,14 +271,14 @@
private final OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>
mOutcomeReceiver =
- new OutcomeReceiver<ModemActivityInfo, TelephonyManager.ModemActivityInfoException>() {
+ new OutcomeReceiver<>() {
@Override
public void onResult(ModemActivityInfo result) {
obtainMessage(MSG_MODEM_ACTIVITY_RETURNED, result).sendToTarget();
}
@Override
- public void onError(TelephonyManager.ModemActivityInfoException e) {
+ public void onError(@NonNull TelephonyManager.ModemActivityInfoException e) {
Rlog.e(TAG, "error reading modem stats:" + e);
obtainMessage(MSG_MODEM_ACTIVITY_RETURNED, null).sendToTarget();
}
@@ -296,20 +297,26 @@
}
};
- public LinkBandwidthEstimator(Phone phone, TelephonyFacade telephonyFacade) {
+ public LinkBandwidthEstimator(Phone phone, Looper looper, TelephonyFacade telephonyFacade) {
+ super(looper);
mPhone = phone;
mTelephonyFacade = telephonyFacade;
mTelephonyManager = phone.getContext()
.getSystemService(TelephonyManager.class)
.createForSubscriptionId(phone.getSubId());
- mConnectivityManager = phone.getContext().getSystemService(ConnectivityManager.class);
DisplayManager dm = (DisplayManager) phone.getContext().getSystemService(
Context.DISPLAY_SERVICE);
- dm.registerDisplayListener(mDisplayListener, null);
+ if (dm != null) {
+ dm.registerDisplayListener(mDisplayListener, null);
+ }
handleScreenStateChanged(isScreenOn());
- mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this);
- mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(this),
- mTelephonyCallback);
+
+ ConnectivityManager cm = phone.getContext()
+ .getSystemService(ConnectivityManager.class);
+ if (cm != null) {
+ cm.registerDefaultNetworkCallback(mDefaultNetworkCallback, this);
+ }
+ mTelephonyManager.registerTelephonyCallback(new HandlerExecutor(this), mTelephonyCallback);
mPlaceholderNetwork = new NetworkBandwidth(UNKNOWN_PLMN);
initAvgBwPerRatTable();
registerNrStateFrequencyChange();
@@ -382,6 +389,7 @@
// the screen is turned off transiently such as due to the proximity sensor.
final DisplayManager dm = (DisplayManager) mPhone.getContext().getSystemService(
Context.DISPLAY_SERVICE);
+ if (dm == null) return false;
Display[] displays = dm.getDisplays();
if (displays != null) {
@@ -432,6 +440,7 @@
handleTrafficStatsPollConditionChanged();
}
+ @SuppressWarnings("unchecked")
private void handleDrsOrRatChanged(AsyncResult ar) {
Pair<Integer, Integer> drsRatPair = (Pair<Integer, Integer>) ar.result;
logd("DrsOrRatChanged dataRegState " + drsRatPair.first + " rilRat " + drsRatPair.second);
@@ -729,7 +738,7 @@
return;
}
long filterOutKbps = (long) mFilterKbps * alpha
- + filterInKbps * FILTER_SCALE - filterInKbps * alpha;
+ + (long) filterInKbps * FILTER_SCALE - (long) filterInKbps * alpha;
filterOutKbps = filterOutKbps / FILTER_SCALE;
mFilterKbps = (int) Math.min(filterOutKbps, Integer.MAX_VALUE);
@@ -877,8 +886,8 @@
StringBuilder sb = new StringBuilder();
logd(sb.append(mLink)
- .append(" sampKbps ").append(mBwSampleKbps)
- .append(" filtKbps ").append(mFilterKbps)
+ .append(" sampleKbps ").append(mBwSampleKbps)
+ .append(" filterKbps ").append(mFilterKbps)
.append(" reportKbps ").append(mLastReportedBwKbps)
.append(" avgUsedKbps ").append(mAvgUsedKbps)
.append(" csKbps ").append(mStaticBwKbps)
@@ -944,7 +953,8 @@
/**
* @return The data activity.
*/
- public @DataActivityType int getDataActivity() {
+ @DataActivityType
+ public int getDataActivity() {
return mDataActivity;
}
@@ -1048,7 +1058,7 @@
/* ss should always be non-null */
if (!TextUtils.isEmpty(ss.getOperatorNumeric())) {
plmn = ss.getOperatorNumeric();
- } else if (cellIdentity != null && !TextUtils.isEmpty(cellIdentity.getPlmn())) {
+ } else if (!TextUtils.isEmpty(cellIdentity.getPlmn())) {
plmn = cellIdentity.getPlmn();
} else {
plmn = UNKNOWN_PLMN;
@@ -1059,7 +1069,6 @@
mPlmn = plmn;
}
- boolean updatedRat = false;
NetworkRegistrationInfo nri = getDataNri();
if (nri != null) {
int dataRat = nri.getAccessNetworkTechnology();
@@ -1133,7 +1142,7 @@
}
@Override
public boolean equals(@Nullable Object o) {
- if (o == null || !(o instanceof NetworkKey) || hashCode() != o.hashCode()) {
+ if (!(o instanceof NetworkKey that) || hashCode() != o.hashCode()) {
return false;
}
@@ -1141,7 +1150,6 @@
return true;
}
- NetworkKey that = (NetworkKey) o;
return mPlmn.equals(that.mPlmn)
&& mTac == that.mTac
&& mDataRat.equals(that.mDataRat);
@@ -1153,11 +1161,7 @@
}
@Override
public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("Plmn").append(mPlmn)
- .append("Rat").append(mDataRat)
- .append("Tac").append(mTac);
- return sb.toString();
+ return "Plmn" + mPlmn + "Rat" + mDataRat + "Tac" + mTac;
}
}
@@ -1216,11 +1220,7 @@
}
private String getDataKey(int link, int level) {
- StringBuilder sb = new StringBuilder();
- return sb.append(mKey)
- .append("Link").append(link)
- .append("Level").append(level)
- .toString();
+ return mKey + "Link" + link + "Level" + level;
}
/** Get the accumulated bandwidth value */
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index 8dc8098..27b4331 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -16,7 +16,6 @@
package com.android.internal.telephony.data;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.telephony.CarrierConfigManager.KEY_DATA_SWITCH_VALIDATION_TIMEOUT_LONG;
import static android.telephony.SubscriptionManager.DEFAULT_PHONE_INDEX;
import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
@@ -33,7 +32,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.compat.annotation.UnsupportedAppUsage;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -47,7 +45,6 @@
import android.net.NetworkSpecifier;
import android.net.TelephonyNetworkSpecifier;
import android.os.AsyncResult;
-import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -56,7 +53,6 @@
import android.os.RegistrantList;
import android.os.RemoteException;
import android.telephony.CarrierConfigManager;
-import android.telephony.PhoneCapability;
import android.telephony.PhoneStateListener;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -69,6 +65,7 @@
import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.Log;
+import android.util.SparseIntArray;
import com.android.ims.ImsException;
import com.android.ims.ImsManager;
@@ -85,6 +82,7 @@
import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyEvent.DataSwitch;
@@ -104,11 +102,12 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
/**
* Utility singleton to monitor subscription changes and incoming NetworkRequests
* and determine which phone/phones are active.
- *
+ * <p>
* Manages the ALLOW_DATA calls to modems and notifies phones about changes to
* the active phones. Note we don't wait for data attach (which may not happen anyway).
*/
@@ -183,10 +182,12 @@
}
}
- private final @NonNull NetworkRequestList mNetworkRequestList = new NetworkRequestList();
+ @NonNull
+ private final NetworkRequestList mNetworkRequestList = new NetworkRequestList();
protected final RegistrantList mActivePhoneRegistrants;
private final SubscriptionManagerService mSubscriptionManagerService;
- private final @NonNull FeatureFlags mFlags;
+ @NonNull
+ private final FeatureFlags mFlags;
protected final Context mContext;
private final LocalLog mLocalLog;
protected PhoneState[] mPhoneStates;
@@ -215,7 +216,6 @@
}
};
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
// How many phones (correspondingly logical modems) are allowed for PS attach. This is used
// when we specifically use setDataAllowed to initiate on-demand PS(data) attach for each phone.
protected int mMaxDataAttachModemCount;
@@ -311,7 +311,7 @@
private static final int MAX_LOCAL_LOG_LINES = 256;
// Default timeout value of network validation in millisecond.
- private final static int DEFAULT_VALIDATION_EXPIRATION_TIME = 2000;
+ private static final int DEFAULT_VALIDATION_EXPIRATION_TIME = 2000;
/** Controller that tracks {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH} */
@NonNull private final AutoDataSwitchController mAutoDataSwitchController;
@@ -319,22 +319,25 @@
@NonNull private final AutoDataSwitchController.AutoDataSwitchControllerCallback
mAutoDataSwitchCallback;
- private ConnectivityManager mConnectivityManager;
+ private final ConnectivityManager mConnectivityManager;
private int mImsRegistrationTech = REGISTRATION_TECH_NONE;
-
- private List<Set<CommandException.Error>> mCurrentDdsSwitchFailure;
+ @VisibleForTesting
+ public final SparseIntArray mImsRegistrationRadioTechMap = new SparseIntArray();
+ @NonNull
+ private final List<Set<CommandException.Error>> mCurrentDdsSwitchFailure;
/** Data settings manager callback. Key is the phone id. */
- private final @NonNull Map<Integer, DataSettingsManagerCallback> mDataSettingsManagerCallbacks =
+ @NonNull
+ private final Map<Integer, DataSettingsManagerCallback> mDataSettingsManagerCallbacks =
new ArrayMap<>();
private class DefaultNetworkCallback extends ConnectivityManager.NetworkCallback {
public int mExpectedSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
public int mSwitchReason = TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN;
@Override
- public void onCapabilitiesChanged(Network network,
+ public void onCapabilitiesChanged(@NonNull Network network,
NetworkCapabilities networkCapabilities) {
- if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
if (SubscriptionManager.isValidSubscriptionId(mExpectedSubId)
&& mExpectedSubId == getSubIdFromNetworkSpecifier(
networkCapabilities.getNetworkSpecifier())) {
@@ -350,15 +353,15 @@
}
@Override
- public void onLost(Network network) {
+ public void onLost(@NonNull Network network) {
mAutoDataSwitchController.updateDefaultNetworkCapabilities(null);
}
}
- private RegistrationManager.RegistrationCallback mRegistrationCallback =
+ private final RegistrationManager.RegistrationCallback mRegistrationCallback =
new RegistrationManager.RegistrationCallback() {
@Override
- public void onRegistered(ImsRegistrationAttributes attributes) {
+ public void onRegistered(@NonNull ImsRegistrationAttributes attributes) {
int imsRegistrationTech = attributes.getRegistrationTechnology();
if (imsRegistrationTech != mImsRegistrationTech) {
mImsRegistrationTech = imsRegistrationTech;
@@ -367,7 +370,7 @@
}
@Override
- public void onUnregistered(ImsReasonInfo info) {
+ public void onUnregistered(@NonNull ImsReasonInfo info) {
if (mImsRegistrationTech != REGISTRATION_TECH_NONE) {
mImsRegistrationTech = REGISTRATION_TECH_NONE;
sendMessage(obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED));
@@ -391,6 +394,21 @@
(context, phoneId) -> ImsManager.getInstance(context, phoneId).getRegistrationTech();
/**
+ * Interface to register RegistrationCallback. It's a wrapper of
+ * ImsManager#addRegistrationCallback, to make it mock-able in unittests.
+ */
+ public interface ImsRegisterCallback {
+ /** Set RegistrationCallback. */
+ void setCallback(Context context, int phoneId, RegistrationManager.RegistrationCallback cb,
+ Executor executor) throws ImsException;
+ }
+
+ @VisibleForTesting
+ public ImsRegisterCallback mImsRegisterCallback =
+ (context, phoneId, cb, executor)-> ImsManager.getInstance(context, phoneId)
+ .addRegistrationCallback(cb, executor);
+
+ /**
* Method to get singleton instance.
*/
public static PhoneSwitcher getInstance() {
@@ -433,8 +451,7 @@
private void registerForImsRadioTechChange(Context context, int phoneId) {
try {
- ImsManager.getInstance(context, phoneId).addRegistrationCallback(
- mRegistrationCallback, this::post);
+ mImsRegisterCallback.setCallback(context, phoneId, mRegistrationCallback, this::post);
mIsRegisteredForImsRadioTechChange = true;
} catch (ImsException imsException) {
mIsRegisteredForImsRadioTechChange = false;
@@ -477,7 +494,7 @@
mRadioConfig = RadioConfig.getInstance();
mValidator = CellularNetworkValidator.getInstance();
- mCurrentDdsSwitchFailure = new ArrayList<Set<CommandException.Error>>();
+ mCurrentDdsSwitchFailure = new ArrayList<>();
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
mContext.registerReceiver(mSimStateIntentReceiver, filter);
@@ -495,6 +512,14 @@
if (phone.getImsPhone() != null) {
phone.getImsPhone().registerForPreciseCallStateChanged(
this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
+ if (mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ // Initialize IMS registration tech
+ mImsRegistrationRadioTechMap.put(phoneId, REGISTRATION_TECH_NONE);
+ ((ImsPhone) phone.getImsPhone()).registerForImsRegistrationChanges(
+ this, EVENT_IMS_RADIO_TECH_CHANGED, null);
+
+ log("register handler to receive IMS registration : " + phoneId);
+ }
}
mDataSettingsManagerCallbacks.computeIfAbsent(phoneId,
v -> new DataSettingsManagerCallback(this::post) {
@@ -512,9 +537,12 @@
}});
phone.getDataSettingsManager().registerCallback(
mDataSettingsManagerCallbacks.get(phoneId));
- registerForImsRadioTechChange(context, phoneId);
+
+ if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ registerForImsRadioTechChange(context, phoneId);
+ }
}
- Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>();
+ Set<CommandException.Error> ddsFailure = new HashSet<>();
mCurrentDdsSwitchFailure.add(ddsFailure);
}
@@ -569,7 +597,7 @@
mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback, this);
final NetworkCapabilities.Builder builder = new NetworkCapabilities.Builder()
- .addTransportType(TRANSPORT_CELLULAR)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)
.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
@@ -594,6 +622,15 @@
.addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
.setNetworkSpecifier(new MatchAllNetworkSpecifier());
+ if (mFlags.satelliteInternet()) {
+ // TODO: b/328622096 remove the try/catch
+ try {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ } catch (IllegalArgumentException exception) {
+ loge("TRANSPORT_SATELLITE is not supported.");
+ }
+ }
+
NetworkFactory networkFactory = new PhoneSwitcherNetworkRequestListener(looper, context,
builder.build(), this);
// we want to see all requests
@@ -612,7 +649,7 @@
}
};
- private BroadcastReceiver mSimStateIntentReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver mSimStateIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -713,7 +750,18 @@
case EVENT_IMS_RADIO_TECH_CHANGED: {
// register for radio tech change to listen to radio tech handover in case previous
// attempt was not successful
- registerForImsRadioTechChange();
+ if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ registerForImsRadioTechChange();
+ } else {
+ if (msg.obj == null) {
+ log("EVENT_IMS_RADIO_TECH_CHANGED but parameter is not available");
+ break;
+ }
+ if (!onImsRadioTechChanged((AsyncResult) (msg.obj))) {
+ break;
+ }
+ }
+
// if voice call state changes or in voice call didn't change
// but RAT changes(e.g. Iwlan -> cross sim), reevaluate for data switch.
if (updatesIfPhoneInVoiceCallChanged() || isAnyVoiceCallActiveOnDevice()) {
@@ -725,7 +773,9 @@
case EVENT_PRECISE_CALL_STATE_CHANGED: {
// register for radio tech change to listen to radio tech handover in case previous
// attempt was not successful
- registerForImsRadioTechChange();
+ if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ registerForImsRadioTechChange();
+ }
// If the phoneId in voice call didn't change, do nothing.
if (!updatesIfPhoneInVoiceCallChanged()) {
@@ -821,10 +871,8 @@
mEmergencyOverride.mOverrideCompleteFuture.complete(false);
}
}
- mEmergencyOverride = req;
- } else {
- mEmergencyOverride = req;
}
+ mEmergencyOverride = req;
logl("new emergency override - " + mEmergencyOverride);
// a new request has been created, remove any previous override complete scheduled.
@@ -877,6 +925,41 @@
}
}
+ /**
+ * Only provide service for the handler of PhoneSwitcher.
+ * @return true if the radio tech changed, otherwise false
+ */
+ private boolean onImsRadioTechChanged(@NonNull AsyncResult asyncResult) {
+ ImsPhone.ImsRegistrationRadioTechInfo imsRegistrationRadioTechInfo =
+ (ImsPhone.ImsRegistrationRadioTechInfo) asyncResult.result;
+ if (imsRegistrationRadioTechInfo == null
+ || imsRegistrationRadioTechInfo.phoneId() == INVALID_PHONE_INDEX
+ || imsRegistrationRadioTechInfo.imsRegistrationState()
+ == RegistrationManager.REGISTRATION_STATE_REGISTERING) {
+ // Ignore REGISTERING state, handle only REGISTERED and NOT_REGISTERED
+ log("onImsRadioTechChanged : result is not available");
+ return false;
+ }
+
+ int phoneId = imsRegistrationRadioTechInfo.phoneId();
+ int subId = SubscriptionManager.getSubscriptionId(phoneId);
+ int tech = imsRegistrationRadioTechInfo.imsRegistrationTech();
+ log("onImsRadioTechChanged phoneId : " + phoneId + " subId : " + subId + " old tech : "
+ + mImsRegistrationRadioTechMap.get(phoneId, REGISTRATION_TECH_NONE)
+ + " new tech : " + tech);
+
+ if (mImsRegistrationRadioTechMap.get(phoneId, REGISTRATION_TECH_NONE) == tech) {
+ // Registration tech not changed
+ return false;
+ }
+
+ mImsRegistrationRadioTechMap.put(phoneId, tech);
+
+ // Need to update the cached IMS registration tech but no need to do any of the
+ // following. When the SIM removed, REGISTRATION_STATE_NOT_REGISTERED is notified.
+ return subId != INVALID_SUBSCRIPTION_ID;
+ }
+
private synchronized void onMultiSimConfigChanged(int activeModemCount) {
// No change.
if (mActiveModemCount == activeModemCount) return;
@@ -903,6 +986,14 @@
if (phone.getImsPhone() != null) {
phone.getImsPhone().registerForPreciseCallStateChanged(
this, EVENT_PRECISE_CALL_STATE_CHANGED, null);
+ if (mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ // Initialize IMS registration tech for new phoneId
+ mImsRegistrationRadioTechMap.put(phoneId, REGISTRATION_TECH_NONE);
+ ((ImsPhone) phone.getImsPhone()).registerForImsRegistrationChanges(
+ this, EVENT_IMS_RADIO_TECH_CHANGED, null);
+
+ log("register handler to receive IMS registration : " + phoneId);
+ }
}
mDataSettingsManagerCallbacks.computeIfAbsent(phone.getPhoneId(),
@@ -923,9 +1014,12 @@
phone.getDataSettingsManager().registerCallback(
mDataSettingsManagerCallbacks.get(phone.getPhoneId()));
- Set<CommandException.Error> ddsFailure = new HashSet<CommandException.Error>();
+ Set<CommandException.Error> ddsFailure = new HashSet<>();
mCurrentDdsSwitchFailure.add(ddsFailure);
- registerForImsRadioTechChange(mContext, phoneId);
+
+ if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ registerForImsRadioTechChange(mContext, phoneId);
+ }
}
mAutoDataSwitchController.onMultiSimConfigChanged(activeModemCount);
@@ -969,7 +1063,7 @@
}
@Override
- protected void needNetworkFor(NetworkRequest networkRequest) {
+ protected void needNetworkFor(@NonNull NetworkRequest networkRequest) {
if (VDBG) log("needNetworkFor " + networkRequest);
Message msg = mPhoneSwitcher.obtainMessage(EVENT_REQUEST_NETWORK);
msg.obj = networkRequest;
@@ -977,7 +1071,7 @@
}
@Override
- protected void releaseNetworkFor(NetworkRequest networkRequest) {
+ protected void releaseNetworkFor(@NonNull NetworkRequest networkRequest) {
if (VDBG) log("releaseNetworkFor " + networkRequest);
Message msg = mPhoneSwitcher.obtainMessage(EVENT_RELEASE_NETWORK);
msg.obj = networkRequest;
@@ -987,7 +1081,7 @@
private void onRequestNetwork(NetworkRequest networkRequest) {
TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest(
- networkRequest, PhoneFactory.getDefaultPhone());
+ networkRequest, PhoneFactory.getDefaultPhone(), mFlags);
if (!mNetworkRequestList.contains(telephonyNetworkRequest)) {
mNetworkRequestList.add(telephonyNetworkRequest);
onEvaluate(REQUESTS_CHANGED, "netRequest");
@@ -996,7 +1090,7 @@
private void onReleaseNetwork(NetworkRequest networkRequest) {
TelephonyNetworkRequest telephonyNetworkRequest = new TelephonyNetworkRequest(
- networkRequest, PhoneFactory.getDefaultPhone());
+ networkRequest, PhoneFactory.getDefaultPhone(), mFlags);
if (mNetworkRequestList.remove(telephonyNetworkRequest)) {
onEvaluate(REQUESTS_CHANGED, "netReleased");
collectReleaseNetworkMetrics(networkRequest);
@@ -1054,7 +1148,7 @@
protected static final boolean REQUESTS_UNCHANGED = false;
/**
* Re-evaluate things. Do nothing if nothing's changed.
- *
+ * <p>
* Otherwise, go through the requests in priority order adding their phone until we've added up
* to the max allowed. Then go through shutting down phones that aren't in the active phone
* list. Finally, activate all phones in the active phone list.
@@ -1092,10 +1186,14 @@
mAutoSelectedDataSubId = DEFAULT_SUBSCRIPTION_ID;
}
mPhoneSubscriptions[i] = sub;
- // Listen to IMS radio tech change for new sub
- if (SubscriptionManager.isValidSubscriptionId(sub)) {
- registerForImsRadioTechChange(mContext, i);
+
+ if (!mFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ // Listen to IMS radio tech change for new sub
+ if (SubscriptionManager.isValidSubscriptionId(sub)) {
+ registerForImsRadioTechChange(mContext, i);
+ }
}
+
diffDetected = true;
mAutoDataSwitchController.notifySubscriptionsMappingChanged();
}
@@ -1144,13 +1242,11 @@
}
sendRilCommands(mPreferredDataPhoneId);
} else {
- List<Integer> newActivePhones = new ArrayList<Integer>();
+ List<Integer> newActivePhones = new ArrayList<>();
- /**
- * If all phones can have PS attached, activate all.
- * Otherwise, choose to activate phones according to requests. And
- * if list is not full, add mPreferredDataPhoneId.
- */
+ // If all phones can have PS attached, activate all.
+ // Otherwise, choose to activate phones according to requests. And
+ // if list is not full, add mPreferredDataPhoneId.
if (mMaxDataAttachModemCount == mActiveModemCount) {
for (int i = 0; i < mMaxDataAttachModemCount; i++) {
newActivePhones.add(i);
@@ -1208,12 +1304,10 @@
public long lastRequested = 0;
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
protected void activate(int phoneId) {
switchPhone(phoneId, true);
}
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
protected void deactivate(int phoneId) {
switchPhone(phoneId, false);
}
@@ -1240,7 +1334,7 @@
/**
* Switch the Default data for the context of an outgoing emergency call.
- *
+ * <p>
* In some cases, we need to try to switch the Default Data subscription before placing the
* emergency call on DSDS devices. This includes the following situation:
* - The modem does not support processing GNSS SUPL requests on the non-default data
@@ -1286,16 +1380,6 @@
}
}
- private void onPhoneCapabilityChangedInternal(PhoneCapability capability) {
- int newMaxDataAttachModemCount = TelephonyManager.getDefault()
- .getNumberOfModemsWithSimultaneousDataConnections();
- if (mMaxDataAttachModemCount != newMaxDataAttachModemCount) {
- mMaxDataAttachModemCount = newMaxDataAttachModemCount;
- logl("Max active phones changed to " + mMaxDataAttachModemCount);
- onEvaluate(REQUESTS_UNCHANGED, "phoneCfgChanged");
- }
- }
-
private int phoneIdForRequest(TelephonyNetworkRequest networkRequest) {
NetworkRequest netRequest = networkRequest.getNativeNetworkRequest();
int subId = getSubIdFromNetworkSpecifier(netRequest.getNetworkSpecifier());
@@ -1484,10 +1568,6 @@
r.notifyRegistrant();
}
- public void unregisterForActivePhoneSwitch(Handler h) {
- mActivePhoneRegistrants.remove(h);
- }
-
/**
* Set opportunistic data subscription. It's an indication to switch Internet data to this
* subscription. It has to be an active subscription, and PhoneSwitcher will try to validate
@@ -1554,6 +1634,9 @@
mPendingSwitchSubId = INVALID_SUBSCRIPTION_ID;
if (subIdToValidate == mPreferredDataSubId.get()) {
+ if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ mAutoSelectedDataSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+ }
sendSetOpptCallbackHelper(callback, SET_OPPORTUNISTIC_SUB_SUCCESS);
return;
}
@@ -1673,7 +1756,7 @@
/**
* Notify PhoneSwitcher to try to switch data to an opportunistic subscription.
- *
+ * <p>
* Set opportunistic data subscription. It's an indication to switch Internet data to this
* subscription. It has to be an active subscription, and PhoneSwitcher will try to validate
* it first if needed. If subId is DEFAULT_SUBSCRIPTION_ID, it means we are un-setting
@@ -1724,7 +1807,6 @@
* Log debug messages and also log into the local log.
* @param l debug messages
*/
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
protected void logl(String l) {
log(l);
mLocalLog.log(l);
@@ -1753,20 +1835,16 @@
* @param reason The switch reason.
* @return The switch reason in string format.
*/
- private static @NonNull String switchReasonToString(int reason) {
- switch(reason) {
- case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN:
- return "UNKNOWN";
- case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL:
- return "MANUAL";
- case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL:
- return "IN_CALL";
- case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_CBRS:
- return "CBRS";
- case TelephonyEvent.DataSwitch.Reason.DATA_SWITCH_REASON_AUTO:
- return "AUTO";
- default: return "UNKNOWN(" + reason + ")";
- }
+ @NonNull
+ private static String switchReasonToString(int reason) {
+ return switch (reason) {
+ case DataSwitch.Reason.DATA_SWITCH_REASON_UNKNOWN -> "UNKNOWN";
+ case DataSwitch.Reason.DATA_SWITCH_REASON_MANUAL -> "MANUAL";
+ case DataSwitch.Reason.DATA_SWITCH_REASON_IN_CALL -> "IN_CALL";
+ case DataSwitch.Reason.DATA_SWITCH_REASON_CBRS -> "CBRS";
+ case DataSwitch.Reason.DATA_SWITCH_REASON_AUTO -> "AUTO";
+ default -> "UNKNOWN(" + reason + ")";
+ };
}
/**
@@ -1775,16 +1853,14 @@
* @param state The switching state.
* @return The switching state in string format.
*/
- private static @NonNull String switchStateToString(int state) {
- switch(state) {
- case TelephonyEvent.EventState.EVENT_STATE_UNKNOWN:
- return "UNKNOWN";
- case TelephonyEvent.EventState.EVENT_STATE_START:
- return "START";
- case TelephonyEvent.EventState.EVENT_STATE_END:
- return "END";
- default: return "UNKNOWN(" + state + ")";
- }
+ @NonNull
+ private static String switchStateToString(int state) {
+ return switch (state) {
+ case TelephonyEvent.EventState.EVENT_STATE_UNKNOWN -> "UNKNOWN";
+ case TelephonyEvent.EventState.EVENT_STATE_START -> "START";
+ case TelephonyEvent.EventState.EVENT_STATE_END -> "END";
+ default -> "UNKNOWN(" + state + ")";
+ };
}
/**
@@ -1827,12 +1903,6 @@
return mAutoSelectedDataSubId;
}
- // TODO (b/148396668): add an internal callback method to monitor phone capability change,
- // and hook this call to that callback.
- private void onPhoneCapabilityChanged(PhoneCapability capability) {
- onPhoneCapabilityChangedInternal(capability);
- }
-
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
pw.println("PhoneSwitcher:");
diff --git a/src/java/com/android/internal/telephony/data/QosCallbackTracker.java b/src/java/com/android/internal/telephony/data/QosCallbackTracker.java
index ac04627..a1ac379 100644
--- a/src/java/com/android/internal/telephony/data/QosCallbackTracker.java
+++ b/src/java/com/android/internal/telephony/data/QosCallbackTracker.java
@@ -53,13 +53,18 @@
private static final int DEDICATED_BEARER_EVENT_STATE_MODIFIED = 2;
private static final int DEDICATED_BEARER_EVENT_STATE_DELETED = 3;
- private final @NonNull String mLogTag;
- private final @NonNull TelephonyNetworkAgent mNetworkAgent;
- private final @NonNull Map<Integer, QosBearerSession> mQosBearerSessions;
- private final @NonNull RcsStats mRcsStats;
+ @NonNull
+ private final String mLogTag;
+ @NonNull
+ private final TelephonyNetworkAgent mNetworkAgent;
+ @NonNull
+ private final Map<Integer, QosBearerSession> mQosBearerSessions;
+ @NonNull
+ private final RcsStats mRcsStats;
// We perform an exact match on the address
- private final @NonNull Map<Integer, IFilter> mCallbacksToFilter;
+ @NonNull
+ private final Map<Integer, IFilter> mCallbacksToFilter;
private final int mPhoneId;
@@ -139,11 +144,6 @@
}
});
}
-
- @Override
- public void onQosCallbackUnregistered(int qosCallbackId) {
-
- }
});
}
@@ -255,7 +255,6 @@
// The filter matches which means it was previously available, and now is
// lost
if (doFiltersMatch(existingSession, filter)) {
- bearerState = DEDICATED_BEARER_EVENT_STATE_DELETED;
sendSessionLost(callbackId, existingSession);
notifyMetricDedicatedBearerEvent(existingSession, bearerState, true);
sessionsReportedToMetric.add(sessionId);
@@ -281,13 +280,13 @@
});
}
- private boolean doFiltersMatch(final @NonNull QosBearerSession qosBearerSession,
- final @NonNull IFilter filter) {
+ private boolean doFiltersMatch(@NonNull final QosBearerSession qosBearerSession,
+ @NonNull final IFilter filter) {
return getMatchingQosBearerFilter(qosBearerSession, filter) != null;
}
- private boolean matchesByLocalAddress(final @NonNull QosBearerFilter sessionFilter,
- final @NonNull IFilter filter) {
+ private boolean matchesByLocalAddress(@NonNull final QosBearerFilter sessionFilter,
+ @NonNull final IFilter filter) {
int portStart;
int portEnd;
if (sessionFilter.getLocalPortRange() == null) {
@@ -316,7 +315,7 @@
}
private boolean matchesByRemoteAddress(@NonNull QosBearerFilter sessionFilter,
- final @NonNull IFilter filter) {
+ @NonNull final IFilter filter) {
int portStart;
int portEnd;
boolean result = false;
@@ -346,8 +345,8 @@
}
private boolean matchesByProtocol(@NonNull QosBearerFilter sessionFilter,
- final @NonNull IFilter filter, boolean hasMatchedFilter) {
- boolean result = false;
+ @NonNull final IFilter filter, boolean hasMatchedFilter) {
+ boolean result;
int protocol = sessionFilter.getProtocol();
if (protocol == QosBearerFilter.QOS_PROTOCOL_TCP
|| protocol == QosBearerFilter.QOS_PROTOCOL_UDP) {
@@ -367,8 +366,9 @@
? sessionFilter : qosFilter;
}
- private @Nullable QosBearerFilter getMatchingQosBearerFilter(
- @NonNull QosBearerSession qosBearerSession, final @NonNull IFilter filter) {
+ @Nullable
+ private QosBearerFilter getMatchingQosBearerFilter(
+ @NonNull QosBearerSession qosBearerSession, @NonNull final IFilter filter) {
QosBearerFilter qosFilter = null;
for (final QosBearerFilter sessionFilter : qosBearerSession.getQosBearerFilterList()) {
@@ -406,11 +406,11 @@
return qosFilter;
}
- private void sendSessionAvailable(final int callbackId, final @NonNull QosBearerSession session,
- @NonNull IFilter filter) {
+ private void sendSessionAvailable(final int callbackId, @NonNull final QosBearerSession session,
+ @NonNull IFilter filter) {
QosBearerFilter qosBearerFilter = getMatchingQosBearerFilter(session, filter);
List<InetSocketAddress> remoteAddresses = new ArrayList<>();
- if (qosBearerFilter.getRemoteAddresses().size() > 0
+ if (qosBearerFilter != null && !qosBearerFilter.getRemoteAddresses().isEmpty()
&& qosBearerFilter.getRemotePortRange() != null) {
remoteAddresses.add(
new InetSocketAddress(qosBearerFilter.getRemoteAddresses().get(0).getAddress(),
@@ -455,17 +455,16 @@
}
private void notifyMetricDedicatedBearerListenerAdded(final int callbackId,
- final @NonNull QosBearerSession session) {
+ @NonNull final QosBearerSession session) {
- final int slotId = mPhoneId;
final int rat = getRatInfoFromSessionInfo(session);
final int qci = getQCIFromSessionInfo(session);
- mRcsStats.onImsDedicatedBearerListenerAdded(callbackId, slotId, rat, qci);
+ mRcsStats.onImsDedicatedBearerListenerAdded(callbackId, mPhoneId, rat, qci);
}
private void notifyMetricDedicatedBearerListenerBearerUpdateSession(
- final int callbackId, final @NonNull QosBearerSession session) {
+ final int callbackId, @NonNull final QosBearerSession session) {
mRcsStats.onImsDedicatedBearerListenerUpdateSession(callbackId, mPhoneId,
getRatInfoFromSessionInfo(session), getQCIFromSessionInfo(session), true);
}
@@ -518,13 +517,12 @@
private void notifyMetricDedicatedBearerEvent(final QosBearerSession session,
final int bearerState, final boolean hasListener) {
- final int slotId = mPhoneId;
int ratAtEnd = getRatInfoFromSessionInfo(session);
int qci = getQCIFromSessionInfo(session);
boolean localConnectionInfoReceived = doesLocalConnectionInfoExist(session);
boolean remoteConnectionInfoReceived = doesRemoteConnectionInfoExist(session);
- mRcsStats.onImsDedicatedBearerEvent(slotId, ratAtEnd, qci, bearerState,
+ mRcsStats.onImsDedicatedBearerEvent(mPhoneId, ratAtEnd, qci, bearerState,
localConnectionInfoReceived, remoteConnectionInfoReceived, hasListener);
}
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java
index 5ed09e6..5a81f19 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java
@@ -54,10 +54,8 @@
private static final int NETWORK_AGENT_TEARDOWN_DELAY_MS = 5_000;
/** The parent data network. */
- private final @NonNull DataNetwork mDataNetwork;
-
- /** Network agent config. For unit test use only. */
- private final @NonNull NetworkAgentConfig mNetworkAgentConfig;
+ @NonNull
+ private final DataNetwork mDataNetwork;
/** This is the id from {@link NetworkAgent#register()}. */
private final int mId;
@@ -72,7 +70,8 @@
* The callbacks that are used to pass information to {@link DataNetwork} and
* {@link QosCallbackTracker}.
*/
- private final @NonNull Set<TelephonyNetworkAgentCallback> mTelephonyNetworkAgentCallbacks =
+ @NonNull
+ private final Set<TelephonyNetworkAgentCallback> mTelephonyNetworkAgentCallbacks =
new ArraySet<>();
/**
@@ -112,7 +111,7 @@
/**
* Called when a qos callback is registered with a filter.
- *
+ * <p>
* Any QoS events that are sent with the same callback id after this method is called are a
* no-op.
*
@@ -165,7 +164,6 @@
config, provider);
register();
mDataNetwork = dataNetwork;
- mNetworkAgentConfig = config;
mTelephonyNetworkAgentCallbacks.add(callback);
mId = getNetwork().getNetId();
mLogTag = "TNA-" + mId;
@@ -270,7 +268,7 @@
* @param filter the filter being registered
*/
@Override
- public void onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter) {
+ public void onQosCallbackRegistered(final int qosCallbackId, @NonNull final QosFilter filter) {
if (mAbandoned) {
log("The agent is already abandoned. Ignored onQosCallbackRegistered.");
return;
@@ -281,7 +279,7 @@
/**
* Called when a qos callback is registered with a filter.
- *
+ * <p>
* Any QoS events that are sent with the same callback id after this method is called are a
* no-op.
*
@@ -345,15 +343,6 @@
}
/**
- * Log debug messages and also log into the local log.
- * @param s debug messages
- */
- private void logl(@NonNull String s) {
- log(s);
- mLocalLog.log(s);
- }
-
- /**
* Dump the state of TelephonyNetworkAgent
*
* @param fd File descriptor
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
index 377c219..ca34ca7 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkFactory.java
@@ -72,14 +72,15 @@
private final Phone mPhone;
- private AccessNetworksManager mAccessNetworksManager;
+ private final AccessNetworksManager mAccessNetworksManager;
private int mSubscriptionId;
@VisibleForTesting
public final Handler mInternalHandler;
- private final @NonNull FeatureFlags mFlags;
+ @NonNull
+ private final FeatureFlags mFlags;
/**
@@ -109,20 +110,19 @@
null);
mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- SubscriptionManager.from(mPhone.getContext()).addOnSubscriptionsChangedListener(
- mSubscriptionsChangedListener);
+ SubscriptionManager.OnSubscriptionsChangedListener subscriptionsChangedListener =
+ new SubscriptionManager.OnSubscriptionsChangedListener() {
+ @Override
+ public void onSubscriptionsChanged() {
+ mInternalHandler.sendEmptyMessage(EVENT_SUBSCRIPTION_CHANGED);
+ }};
+
+ mPhone.getContext().getSystemService(SubscriptionManager.class)
+ .addOnSubscriptionsChangedListener(subscriptionsChangedListener);
register();
}
- private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
- new SubscriptionManager.OnSubscriptionsChangedListener() {
- @Override
- public void onSubscriptionsChanged() {
- mInternalHandler.sendEmptyMessage(EVENT_SUBSCRIPTION_CHANGED);
- }
- };
-
private NetworkCapabilities makeNetworkFilterByPhoneId(int phoneId) {
return makeNetworkFilter(SubscriptionManager.getSubscriptionId(phoneId));
}
@@ -163,6 +163,16 @@
.addEnterpriseId(NetworkCapabilities.NET_ENTERPRISE_ID_5)
.setNetworkSpecifier(new TelephonyNetworkSpecifier.Builder()
.setSubscriptionId(subscriptionId).build());
+
+ if (mFlags.satelliteInternet()) {
+ // TODO: b/328622096 remove the try/catch
+ try {
+ builder.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ } catch (IllegalArgumentException exception) {
+ log("TRANSPORT_SATELLITE is not supported.");
+ }
+ }
+
return builder.build();
}
@@ -255,15 +265,15 @@
}
@Override
- public void needNetworkFor(NetworkRequest networkRequest) {
+ public void needNetworkFor(@NonNull NetworkRequest networkRequest) {
Message msg = mInternalHandler.obtainMessage(EVENT_NETWORK_REQUEST);
msg.obj = networkRequest;
msg.sendToTarget();
}
- private void onNeedNetworkFor(Message msg) {
+ private void onNeedNetworkFor(@NonNull Message msg) {
TelephonyNetworkRequest networkRequest =
- new TelephonyNetworkRequest((NetworkRequest) msg.obj, mPhone);
+ new TelephonyNetworkRequest((NetworkRequest) msg.obj, mPhone, mFlags);
boolean shouldApply = mPhoneSwitcher.shouldApplyNetworkRequest(
networkRequest, mPhone.getPhoneId());
@@ -281,15 +291,15 @@
}
@Override
- public void releaseNetworkFor(NetworkRequest networkRequest) {
+ public void releaseNetworkFor(@NonNull NetworkRequest networkRequest) {
Message msg = mInternalHandler.obtainMessage(EVENT_NETWORK_RELEASE);
msg.obj = networkRequest;
msg.sendToTarget();
}
- private void onReleaseNetworkFor(Message msg) {
+ private void onReleaseNetworkFor(@NonNull Message msg) {
TelephonyNetworkRequest networkRequest =
- new TelephonyNetworkRequest((NetworkRequest) msg.obj, mPhone);
+ new TelephonyNetworkRequest((NetworkRequest) msg.obj, mPhone, mFlags);
boolean applied = mNetworkRequests.get(networkRequest)
!= AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
diff --git a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
index 2668302..117eb36 100644
--- a/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
+++ b/src/java/com/android/internal/telephony/data/TelephonyNetworkRequest.java
@@ -24,6 +24,7 @@
import android.net.NetworkRequest;
import android.net.NetworkSpecifier;
import android.os.SystemClock;
+import android.telephony.Annotation.ConnectivityTransport;
import android.telephony.Annotation.NetCapability;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataProfile;
@@ -31,6 +32,7 @@
import android.telephony.data.TrafficDescriptor.OsAppId;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -136,19 +138,22 @@
);
/** The phone instance. */
- private final @NonNull Phone mPhone;
+ @NonNull
+ private final Phone mPhone;
/**
* Native network request from the clients. See {@link NetworkRequest};
*/
- private final @NonNull NetworkRequest mNativeNetworkRequest;
+ @NonNull
+ private final NetworkRequest mNativeNetworkRequest;
/**
* The attributes of the network capabilities in this network request. This describes how this
* network request can be translated to different fields in {@link DataProfile} or perform
* special actions in telephony.
*/
- private final @NetCapabilityAttribute int mCapabilitiesAttributes;
+ @NetCapabilityAttribute
+ private final int mCapabilitiesAttributes;
/**
* Priority of the network request. The network request has higher priority will be satisfied
@@ -159,13 +164,15 @@
/**
* Data config manager for retrieving data config.
*/
- private final @NonNull DataConfigManager mDataConfigManager;
+ @NonNull
+ private final DataConfigManager mDataConfigManager;
/**
* The attached data network. Note that the data network could be in any state. {@code null}
* indicates this network request is not satisfied.
*/
- private @Nullable DataNetwork mAttachedDataNetwork;
+ @Nullable
+ private DataNetwork mAttachedDataNetwork;
/**
* The state of the network request.
@@ -174,23 +181,33 @@
* @see #REQUEST_STATE_SATISFIED
*/
// This is not a boolean because there might be more states in the future.
- private @RequestState int mState;
+ @RequestState
+ private int mState;
/** The timestamp when this network request enters telephony. */
- private final @ElapsedRealtimeLong long mCreatedTimeMillis;
+ @ElapsedRealtimeLong
+ private final long mCreatedTimeMillis;
/** The data evaluation result. */
- private @Nullable DataEvaluation mEvaluation;
+ @Nullable
+ private DataEvaluation mEvaluation;
+
+ /** Feature flag. */
+ @NonNull
+ private final FeatureFlags mFeatureFlags;
/**
* Constructor
*
* @param request The native network request from the clients.
* @param phone The phone instance
+ * @param featureFlags The feature flag
*/
- public TelephonyNetworkRequest(NetworkRequest request, Phone phone) {
+ public TelephonyNetworkRequest(@NonNull NetworkRequest request, @NonNull Phone phone,
+ @NonNull FeatureFlags featureFlags) {
mPhone = phone;
mNativeNetworkRequest = request;
+ mFeatureFlags = featureFlags;
int capabilitiesAttributes = CAPABILITY_ATTRIBUTE_NONE;
for (int networkCapability : mNativeNetworkRequest.getCapabilities()) {
@@ -212,14 +229,17 @@
/**
* @see NetworkRequest#getNetworkSpecifier()
*/
- public @Nullable NetworkSpecifier getNetworkSpecifier() {
+ @Nullable
+ public NetworkSpecifier getNetworkSpecifier() {
return mNativeNetworkRequest.getNetworkSpecifier();
}
/**
* @see NetworkRequest#getCapabilities()
*/
- public @NonNull @NetCapability int[] getCapabilities() {
+ @NonNull
+ @NetCapability
+ public int[] getCapabilities() {
return mNativeNetworkRequest.getCapabilities();
}
@@ -231,6 +251,23 @@
}
/**
+ * @see NetworkRequest#getTransportTypes()
+ */
+ @NonNull
+ @ConnectivityTransport
+ public int[] getTransportTypes() {
+ return mNativeNetworkRequest.getTransportTypes();
+ }
+
+ /**
+ * @return {@code true} if the request can be served on the specified transport.
+ * @see NetworkRequest#hasTransport
+ */
+ public boolean hasTransport(@ConnectivityTransport int transport) {
+ return mNativeNetworkRequest.hasTransport(transport);
+ }
+
+ /**
* @see NetworkRequest#canBeSatisfiedBy(NetworkCapabilities)
*/
public boolean canBeSatisfiedBy(@Nullable NetworkCapabilities nc) {
@@ -274,6 +311,31 @@
if ((hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)
|| hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_DNN))
&& dataProfile.getApnSetting() != null) {
+ if (mFeatureFlags.satelliteInternet()) {
+ if (mNativeNetworkRequest.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+ && !mNativeNetworkRequest.hasTransport(
+ NetworkCapabilities.TRANSPORT_SATELLITE)) {
+ if (Arrays.stream(getCapabilities()).noneMatch(mDataConfigManager
+ .getForcedCellularTransportCapabilities()::contains)) {
+ // If the request is explicitly for the cellular, then the data profile
+ // needs to support cellular.
+ if (!dataProfile.getApnSetting().isForInfrastructure(
+ ApnSetting.INFRASTRUCTURE_CELLULAR)) {
+ return false;
+ }
+ }
+ } else if (mNativeNetworkRequest.hasTransport(
+ NetworkCapabilities.TRANSPORT_SATELLITE)
+ && !mNativeNetworkRequest.hasTransport(
+ NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ // If the request is explicitly for the satellite, then the data profile needs
+ // to support satellite.
+ if (!dataProfile.getApnSetting().isForInfrastructure(
+ ApnSetting.INFRASTRUCTURE_SATELLITE)) {
+ return false;
+ }
+ }
+ }
// Fallback to the legacy APN type matching.
List<Integer> apnTypes = Arrays.stream(getCapabilities()).boxed()
.map(DataUtils::networkCapabilityToApnType)
@@ -322,7 +384,8 @@
* @return The highest priority APN type based network capability from this network request. -1
* if there is no APN type capabilities in this network request.
*/
- public @NetCapability int getApnTypeNetworkCapability() {
+ @NetCapability
+ public int getApnTypeNetworkCapability() {
if (!hasAttribute(CAPABILITY_ATTRIBUTE_APN_SETTING)) return -1;
return Arrays.stream(getCapabilities()).boxed()
.filter(cap -> DataUtils.networkCapabilityToApnType(cap) != ApnSetting.TYPE_NONE)
@@ -332,7 +395,8 @@
/**
* @return The native network request.
*/
- public @NonNull NetworkRequest getNativeNetworkRequest() {
+ @NonNull
+ public NetworkRequest getNativeNetworkRequest() {
return mNativeNetworkRequest;
}
@@ -341,7 +405,7 @@
*
* @param dataNetwork The data network.
*/
- public void setAttachedNetwork(@NonNull DataNetwork dataNetwork) {
+ public void setAttachedNetwork(@Nullable DataNetwork dataNetwork) {
mAttachedDataNetwork = dataNetwork;
}
@@ -349,7 +413,8 @@
* @return The attached network. {@code null} indicates the request is not attached to any
* network (i.e. the request is unsatisfied).
*/
- public @Nullable DataNetwork getAttachedNetwork() {
+ @Nullable
+ public DataNetwork getAttachedNetwork() {
return mAttachedDataNetwork;
}
@@ -365,7 +430,8 @@
/**
* @return The state of the network request.
*/
- public @RequestState int getState() {
+ @RequestState
+ public int getState() {
return mState;
}
@@ -408,7 +474,8 @@
* @return Os/App id. {@code null} if the request does not have traffic descriptor based network
* capabilities.
*/
- public @Nullable OsAppId getOsAppId() {
+ @Nullable
+ public OsAppId getOsAppId() {
if (!hasAttribute(CAPABILITY_ATTRIBUTE_TRAFFIC_DESCRIPTOR_OS_APP_ID)) return null;
// We do not support multiple network capabilities translated to Os/App id at this time.
@@ -439,18 +506,19 @@
* @param state The request state.
* @return The request state in string format.
*/
- private static @NonNull String requestStateToString(
+ @NonNull
+ private static String requestStateToString(
@TelephonyNetworkRequest.RequestState int state) {
- switch (state) {
- case TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED: return "UNSATISFIED";
- case TelephonyNetworkRequest.REQUEST_STATE_SATISFIED: return "SATISFIED";
- default: return "UNKNOWN(" + state + ")";
- }
+ return switch (state) {
+ case TelephonyNetworkRequest.REQUEST_STATE_UNSATISFIED -> "UNSATISFIED";
+ case TelephonyNetworkRequest.REQUEST_STATE_SATISFIED -> "SATISFIED";
+ default -> "UNKNOWN(" + state + ")";
+ };
}
@Override
public String toString() {
- return "[" + mNativeNetworkRequest.toString() + ", mPriority=" + mPriority
+ return "[" + mNativeNetworkRequest + ", mPriority=" + mPriority
+ ", state=" + requestStateToString(mState)
+ ", mAttachedDataNetwork=" + (mAttachedDataNetwork != null
? mAttachedDataNetwork.name() : null) + ", isMetered=" + isMeteredRequest()
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
index e3eed00..fddeb06 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionConnection.java
@@ -35,7 +35,9 @@
import android.telephony.DomainSelector;
import android.telephony.EmergencyRegistrationResult;
import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PreciseDisconnectCause;
import android.telephony.data.ApnSetting;
+import android.telephony.ims.ImsReasonInfo;
import android.util.LocalLog;
import android.util.Log;
@@ -351,6 +353,10 @@
private boolean mIsTestMode = false;
+ private int mDisconnectCause = DisconnectCause.NOT_VALID;
+ private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
+ private String mReasonMessage = null;
+
/**
* Creates an instance.
*
@@ -789,6 +795,51 @@
}
/**
+ * Save call disconnect info for error propagation.
+ * @param disconnectCause The code for the reason for the disconnect.
+ * @param preciseDisconnectCause The code for the precise reason for the disconnect.
+ * @param reasonMessage Description of the reason for the disconnect, not intended for the user
+ * to see.
+ */
+ public void setDisconnectCause(int disconnectCause, int preciseDisconnectCause,
+ String reasonMessage) {
+ mDisconnectCause = disconnectCause;
+ mPreciseDisconnectCause = preciseDisconnectCause;
+ mReasonMessage = reasonMessage;
+ }
+
+ public int getDisconnectCause() {
+ return mDisconnectCause;
+ }
+
+ public int getPreciseDisconnectCause() {
+ return mPreciseDisconnectCause;
+ }
+
+ public String getReasonMessage() {
+ return mReasonMessage;
+ }
+
+ /**
+ * @return imsReasonInfo Reason for the IMS call failure.
+ */
+ public @Nullable ImsReasonInfo getImsReasonInfo() {
+ if (getSelectionAttributes() == null) {
+ // Neither selectDomain(...) nor reselectDomain(...) has been called yet.
+ return null;
+ }
+
+ return getSelectionAttributes().getPsDisconnectCause();
+ }
+
+ /**
+ * @return phoneId To support localized message based on phoneId
+ */
+ public int getPhoneId() {
+ return getPhone().getPhoneId();
+ }
+
+ /**
* Dumps local log.
*/
public void dump(@NonNull PrintWriter printWriter) {
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
index ee8517d..e4ae592 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionController.java
@@ -271,7 +271,9 @@
mHandler,
mRestartBindingRunnable);
- int numPhones = TelephonyManager.getDefault().getActiveModemCount();
+ TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
+ int numPhones = tm.getSupportedModemCount();
+ logi("numPhones=" + numPhones);
mConnectionCounts = new int[numPhones];
for (int i = 0; i < numPhones; i++) {
mConnectionCounts[i] = 0;
diff --git a/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java b/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
index 410f89b..1b66e54 100644
--- a/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
+++ b/src/java/com/android/internal/telephony/domainselection/DomainSelectionResolver.java
@@ -64,8 +64,7 @@
* to be bound to the domain selection controller.
*/
public static void make(Context context, String flattenedComponentName) {
- Log.i(TAG, "make flag=" + Flags.apDomainSelectionEnabled()
- + ", useOem=" + Flags.useOemDomainSelectionService());
+ Log.i(TAG, "make useOem=" + Flags.useOemDomainSelectionService());
if (sInstance == null) {
sInstance = new DomainSelectionResolver(context, flattenedComponentName);
}
diff --git a/src/java/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnection.java b/src/java/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnection.java
index 0fd9201..095d61f 100644
--- a/src/java/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnection.java
+++ b/src/java/com/android/internal/telephony/domainselection/NormalCallDomainSelectionConnection.java
@@ -24,11 +24,9 @@
import android.telecom.PhoneAccount;
import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
import android.telephony.Annotation.DisconnectCauses;
-import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.DomainSelectionService.EmergencyScanType;
import android.telephony.NetworkRegistrationInfo;
-import android.telephony.PreciseDisconnectCause;
import android.telephony.ims.ImsReasonInfo;
import com.android.internal.telephony.Phone;
@@ -41,9 +39,6 @@
public class NormalCallDomainSelectionConnection extends DomainSelectionConnection {
private static final boolean DBG = false;
- private int mDisconnectCause = DisconnectCause.NOT_VALID;
- private int mPreciseDisconnectCause = PreciseDisconnectCause.NOT_VALID;
- private String mReasonMessage = null;
private @Nullable DomainSelectionConnectionCallback mCallback;
@@ -130,49 +125,4 @@
}
return builder.build();
}
-
- /**
- * Save call disconnect info for error propagation.
- * @param disconnectCause The code for the reason for the disconnect.
- * @param preciseDisconnectCause The code for the precise reason for the disconnect.
- * @param reasonMessage Description of the reason for the disconnect, not intended for the user
- * to see.
- */
- public void setDisconnectCause(int disconnectCause, int preciseDisconnectCause,
- String reasonMessage) {
- mDisconnectCause = disconnectCause;
- mPreciseDisconnectCause = preciseDisconnectCause;
- mReasonMessage = reasonMessage;
- }
-
- public int getDisconnectCause() {
- return mDisconnectCause;
- }
-
- public int getPreciseDisconnectCause() {
- return mPreciseDisconnectCause;
- }
-
- public String getReasonMessage() {
- return mReasonMessage;
- }
-
- /**
- * @return imsReasonInfo Reason for the IMS call failure.
- */
- public @Nullable ImsReasonInfo getImsReasonInfo() {
- if (getSelectionAttributes() == null) {
- // Neither selectDomain(...) nor reselectDomain(...) has been called yet.
- return null;
- }
-
- return getSelectionAttributes().getPsDisconnectCause();
- }
-
- /**
- * @return phoneId To support localized message based on phoneId
- */
- public int getPhoneId() {
- return getPhone().getPhoneId();
- }
}
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
index 02dd613..06ebff2 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyNumberTracker.java
@@ -50,6 +50,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyCapabilities;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.EmergencyNumberStats;
import com.android.internal.telephony.metrics.TelephonyMetrics;
@@ -186,7 +187,7 @@
mFeatureFlags = featureFlags;
mResources = ctx.getResources();
- if (mFeatureFlags.minimalTelephonyCdmCheck()
+ if (TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)
&& !ctx.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_CALLING)) {
throw new UnsupportedOperationException("EmergencyNumberTracker requires calling");
diff --git a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
index c4d5355..8478cff 100644
--- a/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
+++ b/src/java/com/android/internal/telephony/emergency/EmergencyStateTracker.java
@@ -16,8 +16,12 @@
package com.android.internal.telephony.emergency;
+import static android.telecom.Connection.STATE_ACTIVE;
+import static android.telecom.Connection.STATE_DISCONNECTED;
import static android.telephony.CarrierConfigManager.ImsEmergency.KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL;
+import static android.telephony.CarrierConfigManager.KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL;
+import static com.android.internal.telephony.TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_CALLBACK;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_NONE;
import static com.android.internal.telephony.emergency.EmergencyConstants.MODE_EMERGENCY_WWAN;
@@ -53,12 +57,15 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.data.PhoneSwitcher;
+import com.android.internal.telephony.imsphone.ImsPhoneConnection;
import com.android.internal.telephony.satellite.SatelliteController;
import com.android.telephony.Rlog;
@@ -77,6 +84,19 @@
private static final String TAG = "EmergencyStateTracker";
+ private static class OnDisconnectListener extends Connection.ListenerBase {
+ private final CompletableFuture<Boolean> mFuture;
+
+ OnDisconnectListener(CompletableFuture<Boolean> future) {
+ mFuture = future;
+ }
+
+ @Override
+ public void onDisconnect(int cause) {
+ mFuture.complete(true);
+ }
+ };
+
/**
* Timeout before we continue with the emergency call without waiting for DDS switch response
* from the modem.
@@ -91,6 +111,9 @@
private static final int DEFAULT_TRANSPORT_CHANGE_TIMEOUT_MS = 1 * 1000;
+ // Timeout to wait for the termination of incoming call before continue with the emergency call.
+ private static final int DEFAULT_REJECT_INCOMING_CALL_TIMEOUT_MS = 3 * 1000; // 3 seconds.
+
/** The emergency types used when setting the emergency mode on modem. */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "EMERGENCY_TYPE_",
@@ -120,6 +143,7 @@
private EmergencyRegistrationResult mLastEmergencyRegistrationResult;
private boolean mIsEmergencyModeInProgress;
private boolean mIsEmergencyCallStartedDuringEmergencySms;
+ private boolean mIsWaitingForRadioOff;
/** For emergency calls */
private final long mEcmExitTimeoutMs;
@@ -138,6 +162,8 @@
private boolean mIsTestEmergencyNumber;
private Runnable mOnEcmExitCompleteRunnable;
private int mOngoingCallProperties;
+ private boolean mSentEmergencyCallState;
+ private android.telecom.Connection mNormalRoutingEmergencyConnection;
/** For emergency SMS */
private final Set<String> mOngoingEmergencySmsIds = new ArraySet<>();
@@ -149,9 +175,12 @@
private boolean mIsEmergencySmsStartedDuringScbm;
private CompletableFuture<Boolean> mEmergencyTransportChangedFuture;
+ private final Object mRegistrantidentifier = new Object();
private final android.util.ArrayMap<Integer, Boolean> mNoSimEcbmSupported =
new android.util.ArrayMap<>();
+ private final android.util.ArrayMap<Integer, Boolean> mBroadcastEmergencyCallStateChanges =
+ new android.util.ArrayMap<>();
private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
(slotIndex, subId, carrierId, specificCarrierId) -> onCarrierConfigurationChanged(
slotIndex, subId);
@@ -200,6 +229,7 @@
@VisibleForTesting
public interface TelephonyManagerProxy {
int getPhoneCount();
+ int getSimState(int slotIndex);
}
private final TelephonyManagerProxy mTelephonyManagerProxy;
@@ -215,6 +245,11 @@
public int getPhoneCount() {
return mTelephonyManager.getActiveModemCount();
}
+
+ @Override
+ public int getSimState(int slotIndex) {
+ return mTelephonyManager.getSimState(slotIndex);
+ }
}
/**
@@ -233,6 +268,10 @@
public static final int MSG_SET_EMERGENCY_CALLBACK_MODE_DONE = 3;
/** A message which is used to automatically exit from SCBM after a period of time. */
private static final int MSG_EXIT_SCBM = 4;
+ @VisibleForTesting
+ public static final int MSG_NEW_RINGING_CONNECTION = 5;
+ @VisibleForTesting
+ public static final int MSG_VOICE_REG_STATE_CHANGED = 6;
private class MyHandler extends Handler {
@@ -325,11 +364,26 @@
mOnEcmExitCompleteRunnable.run();
mOnEcmExitCompleteRunnable = null;
}
+ if (mPhone != null && mEmergencyMode == MODE_EMERGENCY_WWAN) {
+ // In cross sim redialing.
+ setEmergencyModeInProgress(true);
+ mWasEmergencyModeSetOnModem = true;
+ mPhone.setEmergencyMode(MODE_EMERGENCY_WWAN,
+ mHandler.obtainMessage(MSG_SET_EMERGENCY_MODE_DONE,
+ Integer.valueOf(EMERGENCY_TYPE_CALL)));
+ }
} else if (emergencyType == EMERGENCY_TYPE_SMS) {
if (mIsEmergencyCallStartedDuringEmergencySms) {
mIsEmergencyCallStartedDuringEmergencySms = false;
turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL,
mIsTestEmergencyNumber);
+ } else if (mPhone != null && mEmergencyMode == MODE_EMERGENCY_WWAN) {
+ // Starting emergency call while exiting emergency mode
+ setEmergencyModeInProgress(true);
+ mWasEmergencyModeSetOnModem = true;
+ mPhone.setEmergencyMode(MODE_EMERGENCY_WWAN,
+ mHandler.obtainMessage(MSG_SET_EMERGENCY_MODE_DONE,
+ Integer.valueOf(EMERGENCY_TYPE_CALL)));
} else if (mIsEmergencySmsStartedDuringScbm) {
mIsEmergencySmsStartedDuringScbm = false;
setEmergencyMode(mSmsPhone, emergencyType,
@@ -377,6 +431,20 @@
exitEmergencySmsCallbackModeAndEmergencyMode();
break;
}
+ case MSG_NEW_RINGING_CONNECTION: {
+ handleNewRingingConnection(msg);
+ break;
+ }
+ case MSG_VOICE_REG_STATE_CHANGED: {
+ if (mIsWaitingForRadioOff && isPowerOff()) {
+ unregisterForVoiceRegStateOrRatChanged();
+ if (mPhone != null) {
+ turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL,
+ mIsTestEmergencyNumber);
+ }
+ }
+ break;
+ }
default:
break;
}
@@ -436,6 +504,11 @@
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
context.registerReceiver(mEcmExitReceiver, filter, null, mHandler);
mTelephonyManagerProxy = new TelephonyManagerProxyImpl(context);
+
+ registerForNewRingingConnection();
+
+ // To recover the abnormal state after crash of com.android.phone process
+ maybeResetEmergencyCallStateChangedIntent();
}
/**
@@ -471,6 +544,7 @@
IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
context.registerReceiver(mEcmExitReceiver, filter, null, mHandler);
+ registerForNewRingingConnection();
}
/**
@@ -550,6 +624,8 @@
mPhone = phone;
mOngoingConnection = c;
mIsTestEmergencyNumber = isTestEmergencyNumber;
+ sendEmergencyCallStateChange(mPhone, true);
+ maybeRejectIncomingCall(null);
return mCallEmergencyModeFuture;
}
}
@@ -557,7 +633,17 @@
mPhone = phone;
mOngoingConnection = c;
mIsTestEmergencyNumber = isTestEmergencyNumber;
- turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL, mIsTestEmergencyNumber);
+ sendEmergencyCallStateChange(mPhone, true);
+ final android.telecom.Connection expectedConnection = mOngoingConnection;
+ maybeRejectIncomingCall(result -> {
+ Rlog.i(TAG, "maybeRejectIncomingCall : result = " + result);
+ if (!Objects.equals(mOngoingConnection, expectedConnection)) {
+ Rlog.i(TAG, "maybeRejectIncomingCall "
+ + expectedConnection.getTelecomCallId() + " canceled.");
+ return;
+ }
+ turnOnRadioAndSwitchDds(mPhone, EMERGENCY_TYPE_CALL, mIsTestEmergencyNumber);
+ });
return mCallEmergencyModeFuture;
}
@@ -576,6 +662,8 @@
if (Objects.equals(mOngoingConnection, c)) {
mOngoingConnection = null;
mOngoingCallProperties = 0;
+ sendEmergencyCallStateChange(mPhone, false);
+ unregisterForVoiceRegStateOrRatChanged();
}
if (wasActive && mActiveEmergencyCalls.isEmpty()
@@ -667,6 +755,16 @@
maybeNotifyTransportChangeCompleted(emergencyType, false);
return;
}
+
+ if (emergencyType == EMERGENCY_TYPE_CALL
+ && mode == MODE_EMERGENCY_WWAN
+ && isEmergencyModeInProgress() && !isInEmergencyMode()) {
+ // In cross sim redialing or ending emergency SMS, exitEmergencyMode is not completed.
+ mEmergencyMode = mode;
+ Rlog.i(TAG, "setEmergencyMode wait for the completion of exitEmergencyMode");
+ return;
+ }
+
mEmergencyMode = mode;
setEmergencyModeInProgress(true);
@@ -1000,11 +1098,14 @@
*/
@VisibleForTesting
public boolean isEmergencyCallbackModeSupported(Phone phone) {
+ if (phone == null) {
+ return false;
+ }
int subId = phone.getSubId();
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ int phoneId = phone.getPhoneId();
+ if (!isSimReady(phoneId, subId)) {
// If there is no SIM, refer to the saved last carrier configuration with valid
// subscription.
- int phoneId = phone.getPhoneId();
Boolean savedConfig = mNoSimEcbmSupported.get(Integer.valueOf(phoneId));
if (savedConfig == null) {
// Exceptional case such as with poor boot performance.
@@ -1165,6 +1266,27 @@
}
/**
+ * Returns {@code true} if currently in emergency callback mode with the given {@link Phone}.
+ *
+ * @param phone the {@link Phone} for the emergency call.
+ */
+ public boolean isInEcm(Phone phone) {
+ return isInEcm() && isSamePhone(mPhone, phone);
+ }
+
+ private void sendEmergencyCallStateChange(Phone phone, boolean isAlive) {
+ if ((isAlive && !mSentEmergencyCallState && getBroadcastEmergencyCallStateChanges(phone))
+ || (!isAlive && mSentEmergencyCallState)) {
+ mSentEmergencyCallState = isAlive;
+ Rlog.i(TAG, "sendEmergencyCallStateChange: " + isAlive);
+ Intent intent = new Intent(ACTION_EMERGENCY_CALL_STATE_CHANGED);
+ intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, isAlive);
+ SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phone.getPhoneId());
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+ }
+
+ /**
* Starts the process of an emergency SMS.
*
* @param phone the {@code Phone} on which to process the emergency SMS.
@@ -1251,10 +1373,17 @@
* @param success the flag specifying whether an emergency SMS is successfully sent or not.
* {@code true} if SMS is successfully sent, {@code false} otherwise.
* @param domain the domain that MO SMS was sent.
+ * @param isLastSmsPart the flag specifying whether this result is for the last SMS part or not.
*/
public void endSms(@NonNull String smsId, boolean success,
- @NetworkRegistrationInfo.Domain int domain) {
- mOngoingEmergencySmsIds.remove(smsId);
+ @NetworkRegistrationInfo.Domain int domain, boolean isLastSmsPart) {
+ if (success && !isLastSmsPart) {
+ // Waits until all SMS parts are sent successfully.
+ // Ensures that all SMS parts are sent while in the emergency mode.
+ Rlog.i(TAG, "endSms: wait for additional SMS parts to be sent.");
+ } else {
+ mOngoingEmergencySmsIds.remove(smsId);
+ }
// If the outgoing emergency SMSs are empty, we can try to exit the emergency mode.
if (mOngoingEmergencySmsIds.isEmpty()) {
@@ -1277,7 +1406,9 @@
// Sets the emergency mode to CALLBACK without re-initiating SCBM timer.
setEmergencyCallbackMode(mSmsPhone, EMERGENCY_TYPE_SMS);
} else {
- exitEmergencyMode(mSmsPhone, EMERGENCY_TYPE_SMS);
+ if (mSmsPhone != null) {
+ exitEmergencyMode(mSmsPhone, EMERGENCY_TYPE_SMS);
+ }
clearEmergencySmsInfo();
}
}
@@ -1397,6 +1528,34 @@
}
/**
+ * Returns {@code true} if service states of all phones from PhoneFactory are radio off.
+ */
+ private boolean isPowerOff() {
+ for (Phone phone : mPhoneFactoryProxy.getPhones()) {
+ ServiceState ss = phone.getServiceStateTracker().getServiceState();
+ if (ss.getState() != ServiceState.STATE_POWER_OFF) return false;
+ }
+ return true;
+ }
+
+ private void registerForVoiceRegStateOrRatChanged() {
+ if (mIsWaitingForRadioOff) return;
+ for (Phone phone : mPhoneFactoryProxy.getPhones()) {
+ phone.getServiceStateTracker().registerForVoiceRegStateOrRatChanged(mHandler,
+ MSG_VOICE_REG_STATE_CHANGED, null);
+ }
+ mIsWaitingForRadioOff = true;
+ }
+
+ private void unregisterForVoiceRegStateOrRatChanged() {
+ if (!mIsWaitingForRadioOff) return;
+ for (Phone phone : mPhoneFactoryProxy.getPhones()) {
+ phone.getServiceStateTracker().unregisterForVoiceRegStateOrRatChanged(mHandler);
+ }
+ mIsWaitingForRadioOff = false;
+ }
+
+ /**
* Returns {@code true} if airplane mode is on.
*/
private boolean isAirplaneModeOn(Context context) {
@@ -1426,6 +1585,14 @@
final SatelliteController satelliteController = SatelliteController.getInstance();
boolean needToTurnOffSatellite = satelliteController.isSatelliteEnabled();
+ if (isAirplaneModeOn && !isPowerOff()
+ && !phone.getServiceStateTracker().getDesiredPowerState()) {
+ // power off is delayed to disconnect data connections
+ Rlog.i(TAG, "turnOnRadioAndSwitchDds: wait for the delayed power off");
+ registerForVoiceRegStateOrRatChanged();
+ return;
+ }
+
if (needToTurnOnRadio || needToTurnOffSatellite) {
Rlog.i(TAG, "turnOnRadioAndSwitchDds: phoneId=" + phone.getPhoneId() + " for "
+ emergencyTypeToString(emergencyType));
@@ -1463,6 +1630,11 @@
@Override
public boolean isOkToCall(Phone phone, int serviceState, boolean imsVoiceCapable) {
+ if (!Objects.equals(mOngoingConnection, expectedConnection)) {
+ Rlog.i(TAG, "isOkToCall "
+ + expectedConnection.getTelecomCallId() + " canceled.");
+ return true;
+ }
// Wait for normal service state or timeout if required.
if (phone == phoneForEmergency
&& waitForInServiceTimeout > 0
@@ -1475,6 +1647,11 @@
@Override
public boolean onTimeout(Phone phone, int serviceState, boolean imsVoiceCapable) {
+ if (!Objects.equals(mOngoingConnection, expectedConnection)) {
+ Rlog.i(TAG, "onTimeout "
+ + expectedConnection.getTelecomCallId() + " canceled.");
+ return true;
+ }
// onTimeout shall be called only with the Phone for emergency
return phone.getServiceStateTracker().isRadioOn()
&& !satelliteController.isSatelliteEnabled();
@@ -1619,9 +1796,9 @@
private boolean getConfig(int subId, String key, boolean defVal) {
return getConfigBundle(subId, key).getBoolean(key, defVal);
}
- private PersistableBundle getConfigBundle(int subId, String key) {
+ private PersistableBundle getConfigBundle(int subId, String... keys) {
if (mConfigManager == null) return new PersistableBundle();
- return mConfigManager.getConfigForSubId(subId, key);
+ return mConfigManager.getConfigForSubId(subId, keys);
}
/**
@@ -1675,10 +1852,6 @@
return;
}
- updateNoSimEcbmSupported(slotIndex, subId);
- }
-
- private void updateNoSimEcbmSupported(int slotIndex, int subId) {
SharedPreferences sp = null;
Boolean savedConfig = mNoSimEcbmSupported.get(Integer.valueOf(slotIndex));
if (savedConfig == null) {
@@ -1686,26 +1859,37 @@
savedConfig = Boolean.valueOf(
sp.getBoolean(KEY_NO_SIM_ECBM_SUPPORT + slotIndex, false));
mNoSimEcbmSupported.put(Integer.valueOf(slotIndex), savedConfig);
- Rlog.i(TAG, "updateNoSimEcbmSupported load from preference slotIndex=" + slotIndex
- + ", supported=" + savedConfig);
+ Rlog.i(TAG, "onCarrierConfigChanged load from preference slotIndex=" + slotIndex
+ + ", ecbmSupported=" + savedConfig);
}
- if (!SubscriptionManager.isValidSubscriptionId(subId)) {
- // invalid subId
+ if (!isSimReady(slotIndex, subId)) {
+ Rlog.i(TAG, "onCarrierConfigChanged SIM not ready");
return;
}
- PersistableBundle b = getConfigBundle(subId, KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL);
+ PersistableBundle b = getConfigBundle(subId,
+ KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL,
+ KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL);
if (b.isEmpty()) {
- Rlog.e(TAG, "updateNoSimEcbmSupported empty result");
+ Rlog.e(TAG, "onCarrierConfigChanged empty result");
return;
}
if (!CarrierConfigManager.isConfigForIdentifiedCarrier(b)) {
- Rlog.i(TAG, "updateNoSimEcbmSupported not carrier specific configuration");
+ Rlog.i(TAG, "onCarrierConfigChanged not carrier specific configuration");
return;
}
+ // KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL
+ boolean broadcast = b.getBoolean(KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL);
+ mBroadcastEmergencyCallStateChanges.put(
+ Integer.valueOf(slotIndex), Boolean.valueOf(broadcast));
+
+ Rlog.i(TAG, "onCarrierConfigChanged slotIndex=" + slotIndex
+ + ", broadcastEmergencyCallStateChanges=" + broadcast);
+
+ // KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL
boolean carrierConfig = b.getBoolean(KEY_EMERGENCY_CALLBACK_MODE_SUPPORTED_BOOL);
if (carrierConfig == savedConfig) {
return;
@@ -1720,7 +1904,205 @@
editor.putBoolean(KEY_NO_SIM_ECBM_SUPPORT + slotIndex, carrierConfig);
editor.apply();
- Rlog.i(TAG, "updateNoSimEcbmSupported preference updated slotIndex=" + slotIndex
- + ", supported=" + carrierConfig);
+ Rlog.i(TAG, "onCarrierConfigChanged preference updated slotIndex=" + slotIndex
+ + ", ecbmSupported=" + carrierConfig);
+ }
+
+ private boolean isSimReady(int slotIndex, int subId) {
+ return SubscriptionManager.isValidSubscriptionId(subId)
+ && mTelephonyManagerProxy.getSimState(slotIndex)
+ == TelephonyManager.SIM_STATE_READY;
+ }
+
+ private boolean getBroadcastEmergencyCallStateChanges(Phone phone) {
+ Boolean broadcast = mBroadcastEmergencyCallStateChanges.get(
+ Integer.valueOf(phone.getPhoneId()));
+ return (broadcast == null) ? false : broadcast;
+ }
+
+ /**
+ * Resets the emergency call state if it's in alive state.
+ */
+ @VisibleForTesting
+ public void maybeResetEmergencyCallStateChangedIntent() {
+ Intent intent = mContext.registerReceiver(null,
+ new IntentFilter(ACTION_EMERGENCY_CALL_STATE_CHANGED), Context.RECEIVER_NOT_EXPORTED);
+ if (intent != null
+ && ACTION_EMERGENCY_CALL_STATE_CHANGED.equals(intent.getAction())) {
+ boolean isAlive = intent.getBooleanExtra(
+ TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, false);
+ Rlog.i(TAG, "maybeResetEmergencyCallStateChangedIntent isAlive=" + isAlive);
+ if (isAlive) {
+ intent = new Intent(ACTION_EMERGENCY_CALL_STATE_CHANGED);
+ intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, false);
+ mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+ }
+ }
+
+ private Call getRingingCall(Phone phone) {
+ if (phone == null) return null;
+ Call ringingCall = phone.getRingingCall();
+ if (ringingCall != null
+ && ringingCall.getState() != Call.State.IDLE
+ && ringingCall.getState() != Call.State.DISCONNECTED) {
+ return ringingCall;
+ }
+ // Check the ImsPhoneCall in DISCONNECTING state.
+ Phone imsPhone = phone.getImsPhone();
+ if (imsPhone != null) {
+ ringingCall = imsPhone.getRingingCall();
+ }
+ if (imsPhone != null && ringingCall != null
+ && ringingCall.getState() != Call.State.IDLE
+ && ringingCall.getState() != Call.State.DISCONNECTED) {
+ return ringingCall;
+ }
+ return null;
+ }
+
+ /**
+ * Ensures that there is no incoming call.
+ *
+ * @param completeConsumer The consumer to call once rejecting incoming call completes,
+ * provides {@code true} result if operation completes successfully
+ * or {@code false} if the operation timed out/failed.
+ */
+ private void maybeRejectIncomingCall(Consumer<Boolean> completeConsumer) {
+ Phone[] phones = mPhoneFactoryProxy.getPhones();
+ if (phones == null) {
+ if (completeConsumer != null) {
+ completeConsumer.accept(true);
+ }
+ return;
+ }
+
+ Call ringingCall = null;
+ for (Phone phone : phones) {
+ ringingCall = getRingingCall(phone);
+ if (ringingCall != null) {
+ Rlog.i(TAG, "maybeRejectIncomingCall found a ringing call");
+ break;
+ }
+ }
+
+ if (ringingCall == null) {
+ if (completeConsumer != null) {
+ completeConsumer.accept(true);
+ }
+ return;
+ }
+
+ try {
+ ringingCall.hangup();
+ if (completeConsumer == null) return;
+
+ CompletableFuture<Boolean> future = new CompletableFuture<>();
+ com.android.internal.telephony.Connection cn = ringingCall.getLatestConnection();
+ cn.addListener(new OnDisconnectListener(future));
+ // A timeout that will complete the future to not block the outgoing call indefinitely.
+ CompletableFuture<Boolean> timeout = new CompletableFuture<>();
+ mHandler.postDelayed(
+ () -> timeout.complete(false), DEFAULT_REJECT_INCOMING_CALL_TIMEOUT_MS);
+ // Ensure that the Consumer is completed on the main thread.
+ CompletableFuture<Void> unused = future.acceptEitherAsync(timeout, completeConsumer,
+ mHandler::post).exceptionally((ex) -> {
+ Rlog.w(TAG, "maybeRejectIncomingCall - exceptionally= " + ex);
+ return null;
+ });
+ } catch (Exception e) {
+ Rlog.w(TAG, "maybeRejectIncomingCall - exception= " + e.getMessage());
+ if (completeConsumer != null) {
+ completeConsumer.accept(false);
+ }
+ }
+ }
+
+ private void registerForNewRingingConnection() {
+ Phone[] phones = mPhoneFactoryProxy.getPhones();
+ if (phones == null) {
+ // unit testing
+ return;
+ }
+ for (Phone phone : phones) {
+ phone.registerForNewRingingConnection(mHandler, MSG_NEW_RINGING_CONNECTION,
+ mRegistrantidentifier);
+ }
+ }
+
+ /**
+ * Hangup the new ringing call if there is an ongoing emergency call not connected.
+ */
+ private void handleNewRingingConnection(Message msg) {
+ Connection c = (Connection) ((AsyncResult) msg.obj).result;
+ if (c == null) return;
+ if ((mNormalRoutingEmergencyConnection == null
+ || mNormalRoutingEmergencyConnection.getState() == STATE_ACTIVE
+ || mNormalRoutingEmergencyConnection.getState() == STATE_DISCONNECTED)
+ && (mOngoingConnection == null
+ || mOngoingConnection.getState() == STATE_ACTIVE
+ || mOngoingConnection.getState() == STATE_DISCONNECTED)) {
+ return;
+ }
+ if ((c.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS)
+ && ((ImsPhoneConnection) c).isIncomingCallAutoRejected()) {
+ Rlog.i(TAG, "handleNewRingingConnection auto rejected call");
+ } else {
+ try {
+ Rlog.i(TAG, "handleNewRingingConnection silently drop incoming call");
+ c.getCall().hangup();
+ } catch (CallStateException e) {
+ Rlog.w(TAG, "handleNewRingingConnection", e);
+ }
+ }
+ }
+
+ /**
+ * Indicates the start of a normal routing emergency call.
+ *
+ * <p>
+ * Handles turning on radio and switching DDS.
+ *
+ * @param phone the {@code Phone} on which to process the emergency call.
+ * @param c the {@code Connection} on which to process the emergency call.
+ * @param completeConsumer The consumer to call once rejecting incoming call completes,
+ * provides {@code true} result if operation completes successfully
+ * or {@code false} if the operation timed out/failed.
+ */
+ public void startNormalRoutingEmergencyCall(@NonNull Phone phone,
+ @NonNull android.telecom.Connection c, @NonNull Consumer<Boolean> completeConsumer) {
+ Rlog.i(TAG, "startNormalRoutingEmergencyCall: phoneId=" + phone.getPhoneId()
+ + ", callId=" + c.getTelecomCallId());
+
+ mNormalRoutingEmergencyConnection = c;
+ maybeRejectIncomingCall(completeConsumer);
+ }
+
+ /**
+ * Indicates the termination of a normal routing emergency call.
+ *
+ * @param c the normal routing emergency call disconnected.
+ */
+ public void endNormalRoutingEmergencyCall(@NonNull android.telecom.Connection c) {
+ if (c != mNormalRoutingEmergencyConnection) return;
+ Rlog.i(TAG, "endNormalRoutingEmergencyCall: callId=" + c.getTelecomCallId());
+ mNormalRoutingEmergencyConnection = null;
+ }
+
+ /**
+ * Handles the normal routing emergency call state change.
+ *
+ * @param c the call whose state has changed
+ * @param state the new call state
+ */
+ public void onNormalRoutingEmergencyCallStateChanged(android.telecom.Connection c,
+ @android.telecom.Connection.ConnectionState int state) {
+ if (c != mNormalRoutingEmergencyConnection) return;
+
+ // If the call is connected, we don't need to monitor incoming call any more.
+ if (state == android.telecom.Connection.STATE_ACTIVE
+ || state == android.telecom.Connection.STATE_DISCONNECTED) {
+ endNormalRoutingEmergencyCall(c);
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java b/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
index 384112d..306f6bb 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnHelper.java
@@ -153,7 +153,7 @@
private void powerOffSatellite(Phone phoneForEmergencyCall) {
SatelliteController satelliteController = SatelliteController.getInstance();
satelliteController.requestSatelliteEnabled(phoneForEmergencyCall.getSubId(),
- false /* enableSatellite */, false /* enableDemoMode */,
+ false /* enableSatellite */, false /* enableDemoMode */, false /* isEmergency */,
new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
diff --git a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
index 5949f66..fa0610a 100644
--- a/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
+++ b/src/java/com/android/internal/telephony/emergency/RadioOnStateListener.java
@@ -395,6 +395,7 @@
if (mSatelliteController.isSatelliteEnabled()) {
mSatelliteController.requestSatelliteEnabled(mPhone.getSubId(),
false /* enableSatellite */, false /* enableDemoMode */,
+ false /* isEmergency*/,
new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
diff --git a/src/java/com/android/internal/telephony/euicc/EuiccController.java b/src/java/com/android/internal/telephony/euicc/EuiccController.java
index e527a14..1a5b99e 100644
--- a/src/java/com/android/internal/telephony/euicc/EuiccController.java
+++ b/src/java/com/android/internal/telephony/euicc/EuiccController.java
@@ -620,25 +620,32 @@
void downloadSubscription(int cardId, int portIndex, DownloadableSubscription subscription,
boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim,
Bundle resolvedBundle, PendingIntent callbackIntent) {
- boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions();
- boolean callerCanDownloadAdminManagedSubscription =
- Flags.esimManagementEnabled()
- && callerCanManageDevicePolicyManagedSubscriptions(callingPackage);
+ mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
+
+ boolean callerHasAdminPrivileges = false;
if (Flags.esimManagementEnabled()) {
- if (mContext
- .getSystemService(UserManager.class)
- .hasUserRestriction(UserManager.DISALLOW_SIM_GLOBALLY)
- && !callerCanDownloadAdminManagedSubscription) {
+ callerHasAdminPrivileges = callerCanManageDevicePolicyManagedSubscriptions(
+ callingPackage);
+ if (callerHasAdminPrivileges && (switchAfterDownload && !shouldAllowSwitchAfterDownload(
+ callingPackage))) {
+ // Throw error if calling admin does not have privileges to enable
+ // subscription silently after download but switchAfterDownload is passed as true.
+ sendResult(callbackIntent, ERROR, null);
+ return;
+ }
+ if (mContext.getSystemService(UserManager.class).hasUserRestriction(
+ UserManager.DISALLOW_SIM_GLOBALLY) && !callerHasAdminPrivileges) {
// Only admin managed subscriptions are allowed, but the caller is not authorised to
// download admin managed subscriptions. Abort.
- throw new SecurityException("Caller is not authorized to download subscriptions");
+ sendResult(callbackIntent, ERROR, null);
+ return;
}
}
- mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage);
// Don't try to resolve the port index for apps which are not targeting on T for backward
// compatibility. instead always use default port 0.
boolean shouldResolvePortIndex = isCompatChangeEnabled(callingPackage,
EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS);
+ boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions();
long token = Binder.clearCallingIdentity();
try {
@@ -651,26 +658,19 @@
isConsentNeededToResolvePortIndex = (portIndex
== TelephonyManager.INVALID_PORT_INDEX);
}
- // Caller has admin privileges if they can download admin managed subscription,
- // and are not switching the subscription after download (admins cannot silently
- // enable the subscription).
- boolean hasAdminPrivileges =
- callerCanDownloadAdminManagedSubscription && !switchAfterDownload;
Log.d(TAG, " downloadSubscription cardId: " + cardId + " switchAfterDownload: "
- + switchAfterDownload + " portIndex: " + portIndex
- + " forceDeactivateSim: " + forceDeactivateSim + " callingPackage: "
- + callingPackage
+ + switchAfterDownload + " portIndex: " + portIndex + " forceDeactivateSim: "
+ + forceDeactivateSim + " callingPackage: " + callingPackage
+ " isConsentNeededToResolvePortIndex: " + isConsentNeededToResolvePortIndex
+ " shouldResolvePortIndex:" + shouldResolvePortIndex
- + " hasAdminPrivileges:" + hasAdminPrivileges);
- if (!isConsentNeededToResolvePortIndex
- && (callerCanWriteEmbeddedSubscriptions
- || hasAdminPrivileges)) {
+ + " callerHasAdminPrivileges:" + callerHasAdminPrivileges);
+ if (!isConsentNeededToResolvePortIndex && (callerCanWriteEmbeddedSubscriptions
+ || callerHasAdminPrivileges)) {
// With WRITE_EMBEDDED_SUBSCRIPTIONS, we can skip profile-specific permission checks
// and move straight to the profile download.
downloadSubscriptionPrivileged(cardId, portIndex, token, subscription,
switchAfterDownload, forceDeactivateSim, callingPackage, resolvedBundle,
- callbackIntent, callerCanDownloadAdminManagedSubscription,
+ callbackIntent, callerHasAdminPrivileges,
getCurrentEmbeddedSubscriptionIds(cardId));
return;
}
@@ -867,8 +867,11 @@
cardId,
existingSubscriptions);
return;
+ } else if (markAsOwnedByAdmin) {
+ refreshSubscriptionsOwnership(true, callingPackage, cardId,
+ existingSubscriptions);
}
- break;
+ break;
case EuiccService.RESULT_MUST_DEACTIVATE_SIM:
resultCode = RESOLVABLE_ERROR;
addResolutionIntentWithPort(extrasIntent,
@@ -1733,22 +1736,27 @@
SubscriptionManagerService.getInstance().updateEmbeddedSubscriptions(
List.of(mTelephonyManager.getCardIdForDefaultEuicc()),
() -> {
- if (Flags.esimManagementEnabled() && isCallerAdmin) {
- // Mark the newly downloaded subscriptions as being owned by an admin so
- // that actions for that subscription can be restricted,
- // and the admin is limited to effecting only these subscriptions.
- Set<Integer> subscriptionsAfter = getCurrentEmbeddedSubscriptionIds(cardId);
- subscriptionsAfter.removeAll(subscriptionsBefore);
- for (int subId: subscriptionsAfter) {
- SubscriptionManagerService
- .getInstance().setGroupOwner(subId, callingPackage);
- }
- }
+ refreshSubscriptionsOwnership(isCallerAdmin, callingPackage, cardId,
+ subscriptionsBefore);
sendResult(callbackIntent, resultCode, extrasIntent);
});
}
+ private void refreshSubscriptionsOwnership(boolean isCallerAdmin, String callingPackage,
+ int cardId, Set<Integer> subscriptionsBefore) {
+ if (Flags.esimManagementEnabled() && isCallerAdmin) {
+ // Mark the newly downloaded subscriptions as being owned by an admin so
+ // that actions for that subscription can be restricted,
+ // and the admin is limited to effecting only these subscriptions.
+ Set<Integer> subscriptionsAfter = getCurrentEmbeddedSubscriptionIds(cardId);
+ subscriptionsAfter.removeAll(subscriptionsBefore);
+ for (int subId : subscriptionsAfter) {
+ SubscriptionManagerService.getInstance().setGroupOwner(subId, callingPackage);
+ }
+ }
+ }
+
/** Dispatch the given callback intent with the given result code and data. */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public void sendResult(PendingIntent callbackIntent, int resultCode, Intent extrasIntent) {
@@ -2186,20 +2194,31 @@
}
private boolean callerCanManageDevicePolicyManagedSubscriptions(String callingPackage) {
- // isProfileOwner/isDeviceOwner needs to callers user, so create device policy manager
- // with the correct context associated with the caller.
+ DevicePolicyManager devicePolicyManager = getDevicePolicyManager();
+ boolean isAdmin =
+ devicePolicyManager != null && (devicePolicyManager.isProfileOwnerApp(
+ callingPackage)
+ || devicePolicyManager.isDeviceOwnerApp(callingPackage));
+ return isAdmin || mContext.checkCallingOrSelfPermission(
+ Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS)
+ == PackageManager.PERMISSION_GRANTED;
+ }
+
+ private boolean shouldAllowSwitchAfterDownload(String callingPackage) {
+ DevicePolicyManager devicePolicyManager = getDevicePolicyManager();
+ return devicePolicyManager != null && (devicePolicyManager.isDeviceOwnerApp(callingPackage)
+ || (devicePolicyManager.isProfileOwnerApp(callingPackage)
+ && devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile()));
+ }
+
+ private DevicePolicyManager getDevicePolicyManager() {
+ // create device policy manager with the correct context associated with the caller.
DevicePolicyManager devicePolicyManager =
retrieveDevicePolicyManagerFromUserContext(Binder.getCallingUserHandle());
if (devicePolicyManager == null) {
Log.w(TAG, "Unable to get device policy manager");
- return false;
}
- boolean isAdmin =
- devicePolicyManager.isProfileOwnerApp(callingPackage)
- || devicePolicyManager.isDeviceOwnerApp(callingPackage);
- return isAdmin || mContext.checkCallingOrSelfPermission(
- Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS)
- == PackageManager.PERMISSION_GRANTED;
+ return devicePolicyManager;
}
@Override
diff --git a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index 9de3ee9..c003405 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -200,6 +200,12 @@
10 = dialing number
*/
+ /**
+ * An FAC code is of the following format:
+ * #FAC#MSISDN*
+ */
+ static Pattern sFac = Pattern.compile("^\\#\\d+\\#[^*]+\\*$");
+
static final int MATCH_GROUP_POUND_STRING = 1;
static final int MATCH_GROUP_ACTION = 2;
@@ -274,7 +280,9 @@
// in India operator(Mumbai MTNL)
ret = new GsmMmiCode(phone, app);
ret.mPoundString = dialString;
- } else if (ret.isFacToDial()) {
+ } else if (ret.isFacToDial(dialString)) {
+ // Note: we had to pass in the dial string above because the full dial string is not
+ // in the MmiCode class (or even needed there).
// This is a FAC (feature access code) to dial as a normal call.
ret = null;
}
@@ -963,12 +971,28 @@
}
/**
+ * Determines if a full dial string matches the general format of a FAC code.
+ * Ie. #FAC#MSIDN*
+ * @param dialString The full dialed number.
+ * @return {@code true} if the dialed number has the general format of a FAC code.
+ */
+ private static boolean isFacFormatNumber(String dialString) {
+ Matcher m = sFac.matcher(dialString);
+ return m.matches();
+ }
+
+ /**
* Returns true if the Service Code is FAC to dial as a normal call.
*
* FAC stands for feature access code and it is special patterns of characters
* to invoke certain features.
*/
- private boolean isFacToDial() {
+ private boolean isFacToDial(String dialString) {
+ if (!isFacFormatNumber(dialString)) {
+ // If the full dial string doesn't conform to the required format for a FAC, we will
+ // bail early. It is likely a true USSD which shares the same code as the FAC.
+ return false;
+ }
CarrierConfigManager configManager = (CarrierConfigManager)
mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
diff --git a/src/java/com/android/internal/telephony/ims/ImsResolver.java b/src/java/com/android/internal/telephony/ims/ImsResolver.java
index 49b7e62..eb389b7 100644
--- a/src/java/com/android/internal/telephony/ims/ImsResolver.java
+++ b/src/java/com/android/internal/telephony/ims/ImsResolver.java
@@ -60,6 +60,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.telephony.PhoneConfigurationManager;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.IndentingPrintWriter;
import java.io.FileDescriptor;
@@ -139,11 +140,12 @@
* Create the ImsResolver Service singleton instance.
*/
public static void make(Context context, String defaultMmTelPackageName,
- String defaultRcsPackageName, int numSlots, ImsFeatureBinderRepository repo) {
+ String defaultRcsPackageName, int numSlots, ImsFeatureBinderRepository repo,
+ FeatureFlags featureFlags) {
if (sInstance == null) {
sHandlerThread.start();
sInstance = new ImsResolver(context, defaultMmTelPackageName, defaultRcsPackageName,
- numSlots, repo, sHandlerThread.getLooper());
+ numSlots, repo, sHandlerThread.getLooper(), featureFlags);
}
}
@@ -372,7 +374,7 @@
*/
ImsServiceController create(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
- ImsFeatureBinderRepository repo);
+ ImsFeatureBinderRepository repo, FeatureFlags featureFlags);
}
private ImsServiceControllerFactory mImsServiceControllerFactory =
@@ -386,8 +388,9 @@
@Override
public ImsServiceController create(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
- ImsFeatureBinderRepository repo) {
- return new ImsServiceController(context, componentName, callbacks, repo);
+ ImsFeatureBinderRepository repo, FeatureFlags featureFlags) {
+ return new ImsServiceController(context, componentName, callbacks, repo,
+ featureFlags);
}
};
@@ -410,7 +413,7 @@
@Override
public ImsServiceController create(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
- ImsFeatureBinderRepository repo) {
+ ImsFeatureBinderRepository repo, FeatureFlags featureFlags) {
return new ImsServiceControllerCompat(context, componentName, callbacks, repo);
}
};
@@ -445,6 +448,9 @@
// Synchronize all events on a handler to ensure that the cache includes the most recent
// version of the installed ImsServices.
private final Handler mHandler;
+
+ private final FeatureFlags mFeatureFlags;
+
private class ResolverHandler extends Handler {
ResolverHandler(Looper looper) {
@@ -581,7 +587,7 @@
public ImsResolver(Context context, String defaultMmTelPackageName,
String defaultRcsPackageName, int numSlots, ImsFeatureBinderRepository repo,
- Looper looper) {
+ Looper looper, FeatureFlags featureFlags) {
Log.i(TAG, "device MMTEL package: " + defaultMmTelPackageName + ", device RCS package:"
+ defaultRcsPackageName);
mContext = context;
@@ -591,6 +597,7 @@
mHandler = new ResolverHandler(looper);
mRunnableExecutor = new HandlerExecutor(mHandler);
+ mFeatureFlags = featureFlags;
mCarrierServices = new SparseArray<>(mNumSlots);
setDeviceConfiguration(defaultMmTelPackageName, ImsFeature.FEATURE_EMERGENCY_MMTEL);
setDeviceConfiguration(defaultMmTelPackageName, ImsFeature.FEATURE_MMTEL);
@@ -1233,7 +1240,8 @@
Log.w(TAG, "bindImsService: error=" + e.getMessage());
}
} else {
- controller = info.controllerFactory.create(mContext, info.name, this, mRepo);
+ controller = info.controllerFactory.create(mContext, info.name, this, mRepo,
+ mFeatureFlags);
Log.i(TAG, "Binding ImsService: " + controller.getComponentName()
+ " with features: " + features);
controller.bind(features, slotIdToSubIdMap);
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceController.java b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
index 6af7a08..ea8399f 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceController.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
@@ -49,6 +49,7 @@
import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.util.TelephonyUtils;
import java.io.PrintWriter;
@@ -265,6 +266,7 @@
private final HandlerThread mHandlerThread = new HandlerThread("ImsServiceControllerHandler");
private final Handler mHandler;
private final LegacyPermissionManager mPermissionManager;
+ private final FeatureFlags mFeatureFlags;
private ImsFeatureBinderRepository mRepo;
private ImsServiceControllerCallbacks mCallbacks;
private ExponentialBackoff mBackoff;
@@ -353,7 +355,8 @@
};
public ImsServiceController(Context context, ComponentName componentName,
- ImsServiceControllerCallbacks callbacks, ImsFeatureBinderRepository repo) {
+ ImsServiceControllerCallbacks callbacks, ImsFeatureBinderRepository repo,
+ FeatureFlags featureFlags) {
mContext = context;
mComponentName = componentName;
mCallbacks = callbacks;
@@ -369,6 +372,7 @@
Context.LEGACY_PERMISSION_SERVICE);
mRepo = repo;
mImsEnablementTracker = new ImsEnablementTracker(mHandlerThread.getLooper(), componentName);
+ mFeatureFlags = featureFlags;
mPackageManager = mContext.getPackageManager();
if (mPackageManager != null) {
mChangedPackages = mPackageManager.getChangedPackages(mLastSequenceNumber);
@@ -383,7 +387,7 @@
// testing, use a handler supplied by the testing system.
public ImsServiceController(Context context, ComponentName componentName,
ImsServiceControllerCallbacks callbacks, Handler handler, RebindRetry rebindRetry,
- ImsFeatureBinderRepository repo) {
+ ImsFeatureBinderRepository repo, FeatureFlags featureFlags) {
mContext = context;
mComponentName = componentName;
mCallbacks = callbacks;
@@ -396,6 +400,7 @@
mRestartImsServiceRunnable);
mPermissionManager = null;
mRepo = repo;
+ mFeatureFlags = featureFlags;
mImsEnablementTracker = new ImsEnablementTracker(handler.getLooper(), componentName);
}
@@ -493,6 +498,12 @@
synchronized (mLock) {
HashSet<Integer> slotIDs = newImsFeatures.stream().map(e -> e.slotId).collect(
Collectors.toCollection(HashSet::new));
+
+ // Set the number of slot for IMS enable for each slot
+ if (mFeatureFlags.setNumberOfSimForImsEnable()) {
+ mImsEnablementTracker.setNumOfSlots(slotIDs.size());
+ }
+
// detect which subIds have changed on a per-slot basis
SparseIntArray changedSubIds = new SparseIntArray(slotIDs.size());
for (Integer slotID : slotIDs) {
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java b/src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java
index 778bd0e..440d784 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceControllerCompat.java
@@ -38,6 +38,7 @@
import com.android.ims.internal.IImsMMTelFeature;
import com.android.ims.internal.IImsServiceController;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlagsImpl;
/**
* Manages the Binding lifecycle of one ImsService as well as the relevant ImsFeatures that the
@@ -76,7 +77,7 @@
public ImsServiceControllerCompat(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
ImsFeatureBinderRepository repo) {
- super(context, componentName, callbacks, repo);
+ super(context, componentName, callbacks, repo, new FeatureFlagsImpl());
mMmTelFeatureFactory = MmTelFeatureCompatAdapter::new;
}
@@ -84,7 +85,8 @@
public ImsServiceControllerCompat(Context context, ComponentName componentName,
ImsServiceControllerCallbacks callbacks, Handler handler, RebindRetry rebindRetry,
ImsFeatureBinderRepository repo, MmTelFeatureCompatFactory factory) {
- super(context, componentName, callbacks, handler, rebindRetry, repo);
+ super(context, componentName, callbacks, handler, rebindRetry, repo,
+ new FeatureFlagsImpl());
mMmTelFeatureFactory = factory;
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index a6bb1d6..10cbe77 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -21,6 +21,7 @@
import static android.telephony.ims.ImsManager.EXTRA_WFC_REGISTRATION_FAILURE_TITLE;
import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED;
import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_REGISTERED;
+import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_REGISTERING;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_NONE;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_CLEAR_RAT_BLOCKS;
import static android.telephony.ims.RegistrationManager.SUGGESTED_ACTION_TRIGGER_PLMN_BLOCK;
@@ -75,6 +76,7 @@
import android.os.UserHandle;
import android.preference.PreferenceManager;
import android.sysprop.TelephonyProperties;
+import android.telecom.VideoProfile;
import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
import android.telephony.NetworkRegistrationInfo;
@@ -263,6 +265,14 @@
}
}
+ /**
+ * Container to transfer IMS registration radio tech.
+ * This will be used as result value of AsyncResult to the handler that called
+ * {@link #registerForImsRegistrationChanges(Handler, int, Object)}
+ */
+ public record ImsRegistrationRadioTechInfo(int phoneId, int imsRegistrationTech,
+ int imsRegistrationState) {}
+
// Instance Variables
Phone mDefaultPhone;
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
@@ -802,7 +812,11 @@
try {
if (getRingingCall().getState() != ImsPhoneCall.State.IDLE) {
if (DBG) logd("MmiCode 2: accept ringing call");
- mCT.acceptCall(ImsCallProfile.CALL_TYPE_VOICE);
+ if (mFeatureFlags.answerAudioOnlyWhenAnsweringViaMmiCode()) {
+ mCT.acceptCall(VideoProfile.STATE_AUDIO_ONLY);
+ } else {
+ mCT.acceptCall(ImsCallProfile.CALL_TYPE_VOICE);
+ }
} else if (getBackgroundCall().getState() == ImsPhoneCall.State.HOLDING) {
// If there's an active ongoing call as well, hold it and the background one
// should automatically unhold. Otherwise just unhold the background call.
@@ -2504,7 +2518,15 @@
updateImsRegistrationInfo(REGISTRATION_STATE_REGISTERED,
attributes.getRegistrationTechnology(), SUGGESTED_ACTION_NONE,
imsTransportType);
- AsyncResult ar = new AsyncResult(null, null, null);
+
+ AsyncResult ar;
+ if (mFeatureFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ ar = new AsyncResult(null, new ImsRegistrationRadioTechInfo(mPhoneId,
+ attributes.getRegistrationTechnology(), REGISTRATION_STATE_REGISTERED),
+ null);
+ } else {
+ ar = new AsyncResult(null, null, null);
+ }
mImsRegistrationUpdateRegistrants.notifyRegistrants(ar);
}
@@ -2521,7 +2543,15 @@
mMetrics.writeOnImsConnectionState(mPhoneId, ImsConnectionState.State.PROGRESSING,
null);
mImsStats.onImsRegistering(imsRadioTech);
- AsyncResult ar = new AsyncResult(null, null, null);
+
+ AsyncResult ar;
+ if (mFeatureFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ ar = new AsyncResult(null, new ImsRegistrationRadioTechInfo(mPhoneId,
+ imsRadioTech, REGISTRATION_STATE_REGISTERING),
+ null);
+ } else {
+ ar = new AsyncResult(null, null, null);
+ }
mImsRegistrationUpdateRegistrants.notifyRegistrants(ar);
}
@@ -2564,7 +2594,15 @@
setCurrentSubscriberUris(null);
clearPhoneNumberForSourceIms();
}
- AsyncResult ar = new AsyncResult(null, null, null);
+
+ AsyncResult ar;
+ if (mFeatureFlags.changeMethodOfObtainingImsRegistrationRadioTech()) {
+ ar = new AsyncResult(null, new ImsRegistrationRadioTechInfo(mPhoneId,
+ REGISTRATION_TECH_NONE, REGISTRATION_STATE_NOT_REGISTERED),
+ null);
+ } else {
+ ar = new AsyncResult(null, null, null);
+ }
mImsRegistrationUpdateRegistrants.notifyRegistrants(ar);
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index dcb3b20..e73eafd 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -3553,8 +3553,10 @@
if (DBG) log("onCallStartFailed reasonCode=" + reasonInfo.getCode());
int eccCategory = EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+ List<String> emergencyUrns = new ArrayList<>();
if (imsCall != null && imsCall.getCallProfile() != null) {
eccCategory = imsCall.getCallProfile().getEmergencyServiceCategories();
+ emergencyUrns = imsCall.getCallProfile().getEmergencyUrns();
}
if (mHoldSwitchingState == HoldSwapState.HOLDING_TO_ANSWER_INCOMING) {
@@ -3581,13 +3583,14 @@
// Since onCallInitiating and onCallProgressing reset mPendingMO,
// we can't depend on mPendingMO.
if (conn != null) {
- logi("onCallStartFailed eccCategory=" + eccCategory);
+ logi("onCallStartFailed eccCategory=" + eccCategory + ", emergencyUrns="
+ + emergencyUrns);
int reason = reasonInfo.getCode();
int extraCode = reasonInfo.getExtraCode();
if ((reason == ImsReasonInfo.CODE_LOCAL_CALL_CS_RETRY_REQUIRED
&& extraCode == ImsReasonInfo.EXTRA_CODE_CALL_RETRY_EMERGENCY)
|| (reason == ImsReasonInfo.CODE_SIP_ALTERNATE_EMERGENCY_CALL)) {
- conn.setNonDetectableEmergencyCallInfo(eccCategory);
+ conn.setNonDetectableEmergencyCallInfo(eccCategory, emergencyUrns);
}
conn.setImsReasonInfo(reasonInfo);
sendCallStartFailedDisconnect(imsCall, reasonInfo);
@@ -3765,11 +3768,13 @@
&& DomainSelectionResolver.getInstance().isDomainSelectionSupported()) {
if (conn != null) {
int eccCategory = EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_UNSPECIFIED;
+ List<String> emergencyUrns = new ArrayList<>();
if (imsCall != null && imsCall.getCallProfile() != null) {
eccCategory = imsCall.getCallProfile().getEmergencyServiceCategories();
+ emergencyUrns = imsCall.getCallProfile().getEmergencyUrns();
logi("onCallTerminated eccCategory=" + eccCategory);
}
- conn.setNonDetectableEmergencyCallInfo(eccCategory);
+ conn.setNonDetectableEmergencyCallInfo(eccCategory, emergencyUrns);
}
processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);
return;
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
old mode 100755
new mode 100644
index a71355d..316f62a
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneConnection.java
@@ -157,6 +157,11 @@
*/
private boolean mIsHeldByRemote = false;
+ /**
+ * Used to indicate if both the user and carrier config have enabled the business composer.
+ */
+ private boolean mIsBusinessComposerFeatureEnabled = false;
+
//***** Event Constants
private static final int EVENT_DTMF_DONE = 1;
private static final int EVENT_PAUSE_DONE = 2;
@@ -230,6 +235,10 @@
mCreateTime = System.currentTimeMillis();
mUusInfo = null;
+ if (com.android.server.telecom.flags.Flags.businessCallComposer()) {
+ setIsBusinessComposerFeatureEnabled(phone);
+ }
+
// Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
// in the ImsPhoneConnection. This isn't going to inform any listeners (since the original
// connection is not likely to be associated with a TelephonyConnection yet).
@@ -277,13 +286,13 @@
mIsEmergency = isEmergency;
if (isEmergency) {
- setEmergencyCallInfo(mOwner);
+ setEmergencyCallInfo(mOwner, dialArgs);
if (getEmergencyNumberInfo() == null) {
// There was no emergency number info found for this call, however it is
// still marked as an emergency number. This may happen if it was a redialed
// non-detectable emergency call from IMS.
- setNonDetectableEmergencyCallInfo(dialArgs.eccCategory);
+ setNonDetectableEmergencyCallInfo(dialArgs.eccCategory, new ArrayList<String>());
}
}
@@ -1389,10 +1398,18 @@
* ImsCallProfile.EXTRA_ASSERTED_DISPLAY_NAME). This helper notifies Telecom of the business
* composer values which will then be injected into the android.telecom.Call object.
*/
- private void maybeInjectBusinessComposerExtras(Bundle extras) {
+ @VisibleForTesting
+ public void maybeInjectBusinessComposerExtras(Bundle extras) {
if (extras == null) {
return;
}
+ // Telephony should check that the business composer features is on BEFORE
+ // propagating the business call extras. This prevents the user from getting
+ // business call info when they turned the feature off.
+ if (!mIsBusinessComposerFeatureEnabled) {
+ Rlog.i(LOG_TAG, "mIBCE: business composer feature is NOT enabled");
+ return;
+ }
try {
if (extras.containsKey(ImsCallProfile.EXTRA_IS_BUSINESS_CALL)
&& !extras.containsKey(android.telecom.Call.EXTRA_IS_BUSINESS_CALL)) {
@@ -1413,6 +1430,60 @@
}
}
+ @VisibleForTesting
+ public boolean getIsBusinessComposerFeatureEnabled() {
+ return mIsBusinessComposerFeatureEnabled;
+ }
+
+ @VisibleForTesting
+ public void setIsBusinessComposerFeatureEnabled(Phone phone) {
+ mIsBusinessComposerFeatureEnabled = isBusinessComposerEnabledByConfig(phone)
+ && isBusinessOnlyCallComposerEnabledByUser(phone);
+ Rlog.i(LOG_TAG, String.format(
+ "setIsBusinessComposerFeatureEnabled: mIsBusinessComposerFeatureEnabled=[%b], "
+ + "phone=[%s]", mIsBusinessComposerFeatureEnabled, phone));
+ }
+
+ /**
+ * Returns whether the carrier supports and has enabled the business composer
+ */
+ @VisibleForTesting
+ public boolean isBusinessComposerEnabledByConfig(Phone phone) {
+ PersistableBundle b = null;
+ CarrierConfigManager configMgr = phone.getContext().getSystemService(
+ CarrierConfigManager.class);
+
+ if (configMgr != null) {
+ // If an invalid subId is used, this bundle will contain default values.
+ b = configMgr.getConfigForSubId(phone.getSubId());
+ }
+ if (b != null) {
+ return b.getBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL);
+ } else {
+ // Return static default defined in CarrierConfigManager.
+ return CarrierConfigManager.getDefaultConfig()
+ .getBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL);
+ }
+ }
+
+ /**
+ * Returns whether the user has enabled the business composer
+ */
+ @VisibleForTesting
+ public boolean isBusinessOnlyCallComposerEnabledByUser(Phone phone) {
+ if (phone == null || phone.getContext() == null) {
+ return false;
+ }
+ TelephonyManager tm = (TelephonyManager)
+ phone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
+ if (tm == null) {
+ Rlog.e(LOG_TAG, "isBusinessOnlyCallComposerEnabledByUser: TelephonyManager is null");
+ return false;
+ }
+ return tm.getCallComposerStatus() == TelephonyManager.CALL_COMPOSER_STATUS_BUSINESS_ONLY
+ || tm.getCallComposerStatus() == TelephonyManager.CALL_COMPOSER_STATUS_ON;
+ }
+
private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
if (extras == null || newExtras == null) {
return extras == newExtras;
diff --git a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
index e1f6309..175f5e4 100644
--- a/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/DataCallSessionStats.java
@@ -41,6 +41,7 @@
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.data.DataNetwork;
import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.telephony.Rlog;
@@ -64,10 +65,12 @@
public static final int SIZE_LIMIT_HANDOVER_FAILURES = 15;
private final DefaultNetworkMonitor mDefaultNetworkMonitor;
+ private final SatelliteController mSatelliteController;
public DataCallSessionStats(Phone phone) {
mPhone = phone;
mDefaultNetworkMonitor = PhoneFactory.getMetricsCollector().getDefaultNetworkMonitor();
+ mSatelliteController = SatelliteController.getInstance();
}
private boolean isSystemDefaultNetworkMobile() {
@@ -76,8 +79,9 @@
}
/** Creates a new ongoing atom when data call is set up. */
- public synchronized void onSetupDataCall(@ApnType int apnTypeBitMask) {
- mDataCallSession = getDefaultProto(apnTypeBitMask);
+ public synchronized void onSetupDataCall(@ApnType int apnTypeBitMask,
+ boolean isSatellite) {
+ mDataCallSession = getDefaultProto(apnTypeBitMask, isSatellite);
mStartTime = getTimeMillis();
PhoneFactory.getMetricsCollector().registerOngoingDataCallStat(this);
}
@@ -303,11 +307,15 @@
call.handoverFailureRat.length);
copy.isNonDds = call.isNonDds;
copy.isIwlanCrossSim = call.isIwlanCrossSim;
+ copy.isNtn = call.isNtn;
+ copy.isSatelliteTransport = call.isSatelliteTransport;
+ copy.isProvisioningProfile = call.isProvisioningProfile;
return copy;
}
/** Creates a proto for a normal {@code DataCallSession} with default values. */
- private DataCallSession getDefaultProto(@ApnType int apnTypeBitmask) {
+ private DataCallSession getDefaultProto(@ApnType int apnTypeBitmask,
+ boolean isSatellite) {
DataCallSession proto = new DataCallSession();
proto.dimension = RANDOM.nextInt();
proto.isMultiSim = SimSlotState.isMultiSim();
@@ -329,6 +337,10 @@
proto.handoverFailureRat = new int[0];
proto.isNonDds = false;
proto.isIwlanCrossSim = false;
+ proto.isNtn = mSatelliteController != null
+ ? mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone) : false;
+ proto.isSatelliteTransport = isSatellite;
+ proto.isProvisioningProfile = getIsProvisioningProfile();
return proto;
}
@@ -345,6 +357,17 @@
return subInfo != null && subInfo.isOpportunistic();
}
+ private boolean getIsProvisioningProfile() {
+ SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance()
+ .getSubscriptionInfoInternal(mPhone.getSubId());
+ try {
+ return subInfo.getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING;
+ } catch (Exception ex) {
+ loge("getIsProvisioningProfile: " + ex.getMessage());
+ return false;
+ }
+ }
+
private boolean getIsOos() {
ServiceStateTracker serviceStateTracker = mPhone.getServiceStateTracker();
ServiceState serviceState =
diff --git a/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java b/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
index c7ef625..079ff03 100644
--- a/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
+++ b/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
@@ -16,9 +16,12 @@
package com.android.internal.telephony.metrics;
+import static com.android.internal.telephony.flags.Flags.dataRatMetricEnabled;
+
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
+import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseDataConnectionState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
@@ -27,6 +30,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyStatsLog;
import java.util.HashMap;
import java.util.List;
@@ -47,7 +51,10 @@
private int mSubId;
private HashMap<Integer, PreciseDataConnectionState> mLastPreciseDataConnectionState =
new HashMap<>();
- private PreciseDataConnectionStateListenerImpl mDataConnectionStateListener;
+ private TelephonyListenerImpl mTelephonyListener;
+ private int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ private int mChannelCountEnum = TelephonyStatsLog
+ .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_UNSPECIFIED;
private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
new SubscriptionManager.OnSubscriptionsChangedListener() {
@@ -132,15 +139,15 @@
TelephonyManager telephonyManager =
mPhone.getContext().getSystemService(TelephonyManager.class);
if (telephonyManager != null) {
- mDataConnectionStateListener = new PreciseDataConnectionStateListenerImpl(mExecutor);
- mDataConnectionStateListener.register(telephonyManager.createForSubscriptionId(subId));
+ mTelephonyListener = new TelephonyListenerImpl(mExecutor);
+ mTelephonyListener.register(telephonyManager.createForSubscriptionId(subId));
}
}
private void unregisterTelephonyListener() {
- if (mDataConnectionStateListener != null) {
- mDataConnectionStateListener.unregister();
- mDataConnectionStateListener = null;
+ if (mTelephonyListener != null) {
+ mTelephonyListener.unregister();
+ mTelephonyListener = null;
}
}
@@ -156,12 +163,46 @@
mPhone.getVoiceCallSessionStats().onPreciseDataConnectionStateChanged(connectionState);
}
- private class PreciseDataConnectionStateListenerImpl extends TelephonyCallback
- implements TelephonyCallback.PreciseDataConnectionStateListener {
+ static int getActiveDataSubId() {
+ if (sDataConnectionStateTracker.size() == 0) {
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+ return sDataConnectionStateTracker.valueAt(0).mActiveDataSubId;
+ }
+
+ /**
+ * Log RAT if the active data subId changes to another subId with a different RAT.
+ *
+ * @param subId the current active data subId
+ */
+ private void logRATChanges(int subId) {
+ if (mSubId == subId && mActiveDataSubId != subId) {
+ int newDataRat = mPhone.getServiceStateTracker()
+ .getServiceStateStats().getCurrentDataRat();
+ for (int i = 0; i < sDataConnectionStateTracker.size(); i++) {
+ DataConnectionStateTracker dataConnectionStateTracker =
+ sDataConnectionStateTracker.valueAt(0);
+ if (dataConnectionStateTracker.mSubId == mActiveDataSubId) {
+ int previousDataRat = dataConnectionStateTracker.mPhone
+ .getServiceStateTracker().getServiceStateStats()
+ .getCurrentDataRat();
+ if (newDataRat != previousDataRat) {
+ TelephonyStatsLog.write(TelephonyStatsLog.DATA_RAT_STATE_CHANGED,
+ newDataRat);
+ }
+ }
+ }
+ }
+ }
+
+ private class TelephonyListenerImpl extends TelephonyCallback
+ implements TelephonyCallback.PreciseDataConnectionStateListener,
+ TelephonyCallback.ActiveDataSubscriptionIdListener,
+ TelephonyCallback.PhysicalChannelConfigListener {
private final Executor mExecutor;
private TelephonyManager mTelephonyManager = null;
- PreciseDataConnectionStateListenerImpl(Executor executor) {
+ TelephonyListenerImpl(Executor executor) {
mExecutor = executor;
}
@@ -185,5 +226,58 @@
PreciseDataConnectionState connectionState) {
notifyDataConnectionStateChanged(connectionState);
}
+
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ if (dataRatMetricEnabled()) {
+ logRATChanges(subId);
+ }
+ mActiveDataSubId = subId;
+ }
+
+ @Override
+ public void onPhysicalChannelConfigChanged(List<PhysicalChannelConfig> configs) {
+ logChannelChange(configs);
+ }
+
+ /** Log channel number if it changes for active data subscription*/
+ private void logChannelChange(List<PhysicalChannelConfig> configs) {
+ int connectedChannelCount = configs.size();
+ int channelCountEnum = TelephonyStatsLog
+ .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_UNSPECIFIED;
+ switch(connectedChannelCount) {
+ case 0:
+ channelCountEnum = TelephonyStatsLog
+ .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_ONE;
+ break;
+ case 1:
+ channelCountEnum = TelephonyStatsLog
+ .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_ONE;
+ break;
+ case 2:
+ channelCountEnum = TelephonyStatsLog
+ .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_TWO;
+ break;
+ case 3:
+ channelCountEnum = TelephonyStatsLog
+ .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_THREE;
+ break;
+ case 4:
+ channelCountEnum = TelephonyStatsLog
+ .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_FOUR;
+ break;
+ // Greater than 4
+ default:
+ channelCountEnum = TelephonyStatsLog
+ .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_FIVE;
+ }
+ if (mChannelCountEnum != channelCountEnum) {
+ if (mSubId != mActiveDataSubId) {
+ TelephonyStatsLog.write(TelephonyStatsLog.CONNECTED_CHANNEL_CHANGED,
+ channelCountEnum);
+ }
+ mChannelCountEnum = channelCountEnum;
+ }
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/metrics/DataNetworkValidationStats.java b/src/java/com/android/internal/telephony/metrics/DataNetworkValidationStats.java
new file mode 100644
index 0000000..fdac834
--- /dev/null
+++ b/src/java/com/android/internal/telephony/metrics/DataNetworkValidationStats.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.metrics;
+
+import android.annotation.ElapsedRealtimeLong;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.SystemClock;
+import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.NetworkType;
+import android.telephony.PreciseDataConnectionState;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.TelephonyStatsLog;
+import com.android.internal.telephony.nano.PersistAtomsProto.DataNetworkValidation;
+
+/**
+ * DataNetworkValidationStats logs the atoms for response after a validation request from the
+ * DataNetwork in framework.
+ */
+public class DataNetworkValidationStats {
+
+ private static final String TAG = DataNetworkValidationStats.class.getSimpleName();
+
+ @NonNull
+ private final Phone mPhone;
+
+ @NonNull
+ private final PersistAtomsStorage mAtomsStorage =
+ PhoneFactory.getMetricsCollector().getAtomsStorage();
+
+ @Nullable
+ private DataNetworkValidation mDataNetworkValidation;
+
+ @ElapsedRealtimeLong
+ private long mRequestedTimeInMillis;
+
+ /** constructor */
+ public DataNetworkValidationStats(@NonNull Phone phone) {
+ mPhone = phone;
+ }
+
+
+ /**
+ * Create a new ongoing atom when NetworkValidation requested.
+ *
+ * Create a data network validation proto for a new atom record and write the start time to
+ * calculate the elapsed time required.
+ *
+ * @param apnTypeBitMask APN type bitmask of DataNetwork.
+ */
+ public void onRequestNetworkValidation(@ApnType int apnTypeBitMask) {
+ if (mDataNetworkValidation == null) {
+ mDataNetworkValidation = getDefaultProto(apnTypeBitMask);
+ mRequestedTimeInMillis = getTimeMillis();
+ }
+ }
+
+ /** Mark the Handover Attempt field as true if validation was requested */
+ public void onHandoverAttempted() {
+ if (mDataNetworkValidation != null) {
+ mDataNetworkValidation.handoverAttempted = true;
+ }
+ }
+
+ /**
+ * Called when data network is disconnected.
+ *
+ * Since network validation is based on the data network, validation must also end when the data
+ * network is disconnected. At this time, validation has not been completed, save an atom as
+ * unspecified. and clear.
+ *
+ * @param networkType Current Network Type of the Data Network.
+ */
+ public void onDataNetworkDisconnected(@NetworkType int networkType) {
+ // Nothing to do, if never requested validation
+ if (mDataNetworkValidation == null) {
+ return;
+ }
+
+ // Set data for and atom.
+ calcElapsedTime();
+ mDataNetworkValidation.networkType = networkType;
+ mDataNetworkValidation.signalStrength = mPhone.getSignalStrength().getLevel();
+ mDataNetworkValidation.validationResult = TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_UNSPECIFIED;
+
+ // Store.
+ mAtomsStorage.addDataNetworkValidation(mDataNetworkValidation);
+
+ // clear all values.
+ clear();
+ }
+
+ /**
+ * Store an atom by updated state.
+ *
+ * Called when the validation status is updated, and saves the atom when a failure or success
+ * result is received.
+ *
+ * @param status Data Network Validation Status.
+ * @param networkType Current Network Type of the Data Network.
+ */
+ public void onUpdateNetworkValidationState(
+ @PreciseDataConnectionState.NetworkValidationStatus int status,
+ @NetworkType int networkType) {
+ // Nothing to do, if never requested validation
+ if (mDataNetworkValidation == null) {
+ return;
+ }
+
+ switch (status) {
+ // Immediately after requesting validation, these messages may occur. In this case,
+ // ignore it and wait for the next update.
+ case PreciseDataConnectionState.NETWORK_VALIDATION_NOT_REQUESTED: // fall-through
+ case PreciseDataConnectionState.NETWORK_VALIDATION_IN_PROGRESS:
+ return;
+ // If status is unsupported, NetworkValidation should not be requested initially. logs
+ // this for abnormal tracking.
+ case PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED:
+ mDataNetworkValidation.validationResult = TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_NOT_SUPPORTED;
+ break;
+ // Success or failure corresponds to the result, store an atom.
+ case PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS:
+ case PreciseDataConnectionState.NETWORK_VALIDATION_FAILURE:
+ mDataNetworkValidation.validationResult = status;
+ break;
+ }
+
+ // Set data for and atom.
+ calcElapsedTime();
+ mDataNetworkValidation.networkType = networkType;
+ mDataNetworkValidation.signalStrength = mPhone.getSignalStrength().getLevel();
+
+ // Store.
+ mAtomsStorage.addDataNetworkValidation(mDataNetworkValidation);
+
+ // clear all values.
+ clear();
+ }
+
+ /**
+ * Calculate the current time required based on when network validation is requested.
+ */
+ private void calcElapsedTime() {
+ if (mDataNetworkValidation != null && mRequestedTimeInMillis != 0) {
+ mDataNetworkValidation.elapsedTimeInMillis = getTimeMillis() - mRequestedTimeInMillis;
+ }
+ }
+
+ /**
+ * Returns current time in millis from boot.
+ */
+ @VisibleForTesting
+ @ElapsedRealtimeLong
+ protected long getTimeMillis() {
+ return SystemClock.elapsedRealtime();
+ }
+
+ /**
+ * Clear all values.
+ */
+ private void clear() {
+ mDataNetworkValidation = null;
+ mRequestedTimeInMillis = 0;
+ }
+
+
+ /** Creates a DataNetworkValidation proto with default values. */
+ @NonNull
+ private DataNetworkValidation getDefaultProto(@ApnType int apnTypeBitmask) {
+ DataNetworkValidation proto = new DataNetworkValidation();
+ proto.networkType =
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__NETWORK_TYPE__NETWORK_TYPE_UNKNOWN;
+ proto.apnTypeBitmask = apnTypeBitmask;
+ proto.signalStrength =
+ TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__SIGNAL_STRENGTH__SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ proto.validationResult =
+ TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_UNSPECIFIED;
+ proto.elapsedTimeInMillis = 0;
+ proto.handoverAttempted = false;
+ proto.networkValidationCount = 1;
+ return proto;
+ }
+}
+
diff --git a/src/java/com/android/internal/telephony/metrics/DeviceStateHelper.java b/src/java/com/android/internal/telephony/metrics/DeviceStateHelper.java
index 29729c8..9ab52fb 100644
--- a/src/java/com/android/internal/telephony/metrics/DeviceStateHelper.java
+++ b/src/java/com/android/internal/telephony/metrics/DeviceStateHelper.java
@@ -41,7 +41,7 @@
.registerCallback(
new HandlerExecutor(new Handler(mHandlerThread.getLooper())),
state -> {
- updateFoldState(state);
+ updateFoldState(state.getIdentifier());
});
}
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index a315f1e..a83cd06 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -17,9 +17,12 @@
package com.android.internal.telephony.metrics;
import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ID_TABLE_VERSION;
+import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS;
+import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_SESSION;
import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_DATA_SERVICE_SWITCH;
import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE;
import static com.android.internal.telephony.TelephonyStatsLog.DATA_CALL_SESSION;
+import static com.android.internal.telephony.TelephonyStatsLog.DATA_NETWORK_VALIDATION;
import static com.android.internal.telephony.TelephonyStatsLog.DEVICE_TELEPHONY_PROPERTIES;
import static com.android.internal.telephony.TelephonyStatsLog.EMERGENCY_NUMBERS_INFO;
import static com.android.internal.telephony.TelephonyStatsLog.GBA_EVENT;
@@ -36,7 +39,10 @@
import static com.android.internal.telephony.TelephonyStatsLog.PRESENCE_NOTIFY_EVENT;
import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS;
import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS;
+import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_ACCESS_CONTROLLER;
+import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_CONFIG_UPDATER;
import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_CONTROLLER;
+import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_ENTITLEMENT;
import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_INCOMING_DATAGRAM;
import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_OUTGOING_DATAGRAM;
import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_PROVISION;
@@ -69,9 +75,12 @@
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
+import com.android.internal.telephony.nano.PersistAtomsProto.DataNetworkValidation;
import com.android.internal.telephony.nano.PersistAtomsProto.EmergencyNumbersInfo;
import com.android.internal.telephony.nano.PersistAtomsProto.GbaEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerEvent;
@@ -87,7 +96,10 @@
import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteAccessController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision;
@@ -138,14 +150,6 @@
private static final long MIN_COOLDOWN_MILLIS =
DBG ? 10L * MILLIS_PER_SECOND : 23L * MILLIS_PER_HOUR;
- /**
- * Sets atom pull cool down to 4 minutes for userdebug build.
- *
- * <p>Applies to certain atoms: CellularServiceState.
- */
- private static final long CELL_SERVICE_MIN_COOLDOWN_MILLIS =
- DBG ? 10L * MILLIS_PER_SECOND :
- IS_DEBUGGABLE ? 4L * MILLIS_PER_MINUTE : 23L * MILLIS_PER_HOUR;
/**
* Buckets with less than these many calls will be dropped.
@@ -166,6 +170,13 @@
private static final long CELL_SERVICE_DURATION_BUCKET_MILLIS =
DBG || IS_DEBUGGABLE ? 2L * MILLIS_PER_SECOND : 5L * MILLIS_PER_MINUTE;
+ /**
+ * Sets atom pull cool down to 4 minutes for userdebug build, 5 hours for user build.
+ *
+ * <p>Applies to certain atoms: CellularServiceState, DataCallSession,
+ * ImsRegistrationTermination.
+ */
+ private final long mPowerCorrelatedMinCooldownMillis;
private final PersistAtomsStorage mStorage;
private final DeviceStateHelper mDeviceStateHelper;
private final StatsManager mStatsManager;
@@ -177,14 +188,15 @@
public MetricsCollector(Context context, @NonNull FeatureFlags featureFlags) {
this(context, new PersistAtomsStorage(context),
- new DeviceStateHelper(context), new VonrHelper(featureFlags), featureFlags);
+ new DeviceStateHelper(context), new VonrHelper(featureFlags),
+ new DefaultNetworkMonitor(context, featureFlags), featureFlags);
}
/** Allows dependency injection. Used during unit tests. */
@VisibleForTesting
- public MetricsCollector(
- Context context, PersistAtomsStorage storage, DeviceStateHelper deviceStateHelper,
- VonrHelper vonrHelper, @NonNull FeatureFlags featureFlags) {
+ public MetricsCollector(Context context, PersistAtomsStorage storage,
+ DeviceStateHelper deviceStateHelper, VonrHelper vonrHelper,
+ DefaultNetworkMonitor defaultNetworkMonitor, @NonNull FeatureFlags featureFlags) {
mStorage = storage;
mDeviceStateHelper = deviceStateHelper;
mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER);
@@ -227,6 +239,12 @@
registerAtom(SATELLITE_OUTGOING_DATAGRAM);
registerAtom(SATELLITE_PROVISION);
registerAtom(SATELLITE_SOS_MESSAGE_RECOMMENDER);
+ registerAtom(DATA_NETWORK_VALIDATION);
+ registerAtom(CARRIER_ROAMING_SATELLITE_SESSION);
+ registerAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS);
+ registerAtom(SATELLITE_ENTITLEMENT);
+ registerAtom(SATELLITE_CONFIG_UPDATER);
+ registerAtom(SATELLITE_ACCESS_CONTROLLER);
Rlog.d(TAG, "registered");
} else {
Rlog.e(TAG, "could not get StatsManager, atoms not registered");
@@ -234,6 +252,9 @@
mAirplaneModeStats = new AirplaneModeStats(context);
mDefaultNetworkMonitor = new DefaultNetworkMonitor(context, featureFlags);
+ mPowerCorrelatedMinCooldownMillis = DBG ? 10L * MILLIS_PER_SECOND :
+ IS_DEBUGGABLE ? 4L * MILLIS_PER_MINUTE : (long) context.getResources().getInteger(
+ com.android.internal.R.integer.config_metrics_pull_cooldown_millis);
}
/**
@@ -318,6 +339,18 @@
return pullSatelliteProvision(data);
case SATELLITE_SOS_MESSAGE_RECOMMENDER:
return pullSatelliteSosMessageRecommender(data);
+ case DATA_NETWORK_VALIDATION:
+ return pullDataNetworkValidation(data);
+ case CARRIER_ROAMING_SATELLITE_SESSION:
+ return pullCarrierRoamingSatelliteSession(data);
+ case CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS:
+ return pullCarrierRoamingSatelliteControllerStats(data);
+ case SATELLITE_ENTITLEMENT:
+ return pullSatelliteEntitlement(data);
+ case SATELLITE_CONFIG_UPDATER:
+ return pullSatelliteConfigUpdater(data);
+ case SATELLITE_ACCESS_CONTROLLER:
+ return pullSatelliteAccessController(data);
default:
Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag));
return StatsManager.PULL_SKIP;
@@ -516,7 +549,8 @@
private int pullDataCallSession(List<StatsEvent> data) {
// Include ongoing data call segments
concludeDataCallSessionStats();
- DataCallSession[] dataCallSessions = mStorage.getDataCallSessions(MIN_COOLDOWN_MILLIS);
+ DataCallSession[] dataCallSessions = mStorage.getDataCallSessions(
+ mPowerCorrelatedMinCooldownMillis);
if (dataCallSessions != null) {
Arrays.stream(dataCallSessions)
.forEach(dataCall -> data.add(buildStatsEvent(dataCall)));
@@ -544,8 +578,8 @@
private int pullCellularServiceState(List<StatsEvent> data) {
// Include the latest durations
concludeServiceStateStats();
- CellularServiceState[] persistAtoms =
- mStorage.getCellularServiceStates(CELL_SERVICE_MIN_COOLDOWN_MILLIS);
+ CellularServiceState[] persistAtoms = mStorage.getCellularServiceStates(
+ mPowerCorrelatedMinCooldownMillis);
if (persistAtoms != null) {
// list is already shuffled when instances were inserted
Arrays.stream(persistAtoms)
@@ -573,8 +607,8 @@
}
private int pullImsRegistrationTermination(List<StatsEvent> data) {
- ImsRegistrationTermination[] persistAtoms =
- mStorage.getImsRegistrationTerminations(MIN_COOLDOWN_MILLIS);
+ ImsRegistrationTermination[] persistAtoms = mStorage.getImsRegistrationTerminations(
+ mPowerCorrelatedMinCooldownMillis);
if (persistAtoms != null) {
// list is already shuffled when instances were inserted
Arrays.stream(persistAtoms)
@@ -937,6 +971,85 @@
}
}
+ private int pullDataNetworkValidation(@NonNull List<StatsEvent> data) {
+ DataNetworkValidation[] dataNetworkValidations =
+ mStorage.getDataNetworkValidation(mPowerCorrelatedMinCooldownMillis);
+ if (dataNetworkValidations != null) {
+ Arrays.stream(dataNetworkValidations)
+ .forEach(d -> data.add(buildStatsEvent(d)));
+ return StatsManager.PULL_SUCCESS;
+ } else {
+ Rlog.w(TAG, "DATA_NETWORK_VALIDATION pull too frequent, skipping");
+ return StatsManager.PULL_SKIP;
+ }
+ }
+
+ private int pullCarrierRoamingSatelliteSession(List<StatsEvent> data) {
+ CarrierRoamingSatelliteSession[] carrierRoamingSatelliteSessionAtoms =
+ mStorage.getCarrierRoamingSatelliteSessionStats(MIN_COOLDOWN_MILLIS);
+ if (carrierRoamingSatelliteSessionAtoms != null) {
+ Arrays.stream(carrierRoamingSatelliteSessionAtoms)
+ .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
+ return StatsManager.PULL_SUCCESS;
+ } else {
+ Rlog.w(TAG, "CARRIER_ROAMING_SATELLITE_SESSION pull too frequent, skipping");
+ return StatsManager.PULL_SKIP;
+ }
+ }
+
+ private int pullCarrierRoamingSatelliteControllerStats(List<StatsEvent> data) {
+ CarrierRoamingSatelliteControllerStats[] carrierRoamingSatelliteControllerStatsAtoms =
+ mStorage.getCarrierRoamingSatelliteControllerStats(MIN_COOLDOWN_MILLIS);
+ if (carrierRoamingSatelliteControllerStatsAtoms != null) {
+ Arrays.stream(carrierRoamingSatelliteControllerStatsAtoms)
+ .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
+ return StatsManager.PULL_SUCCESS;
+ } else {
+ Rlog.w(TAG, "CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS "
+ + "pull too frequent, skipping");
+ return StatsManager.PULL_SKIP;
+ }
+ }
+
+ private int pullSatelliteEntitlement(List<StatsEvent> data) {
+ SatelliteEntitlement[] satelliteEntitlementAtoms =
+ mStorage.getSatelliteEntitlementStats(MIN_COOLDOWN_MILLIS);
+ if (satelliteEntitlementAtoms != null) {
+ Arrays.stream(satelliteEntitlementAtoms)
+ .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
+ return StatsManager.PULL_SUCCESS;
+ } else {
+ Rlog.w(TAG, "SATELLITE_ENTITLEMENT pull too frequent, skipping");
+ return StatsManager.PULL_SKIP;
+ }
+ }
+
+ private int pullSatelliteConfigUpdater(List<StatsEvent> data) {
+ SatelliteConfigUpdater[] satelliteConfigUpdaterAtoms =
+ mStorage.getSatelliteConfigUpdaterStats(MIN_COOLDOWN_MILLIS);
+ if (satelliteConfigUpdaterAtoms != null) {
+ Arrays.stream(satelliteConfigUpdaterAtoms)
+ .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
+ return StatsManager.PULL_SUCCESS;
+ } else {
+ Rlog.w(TAG, "SATELLITE_CONFIG_UPDATER pull too frequent, skipping");
+ return StatsManager.PULL_SKIP;
+ }
+ }
+
+ private int pullSatelliteAccessController(List<StatsEvent> data) {
+ SatelliteAccessController[] satelliteAccessControllerAtoms =
+ mStorage.getSatelliteAccessControllerStats(MIN_COOLDOWN_MILLIS);
+ if (satelliteAccessControllerAtoms != null) {
+ Arrays.stream(satelliteAccessControllerAtoms)
+ .forEach(persistAtom -> data.add(buildStatsEvent(persistAtom)));
+ return StatsManager.PULL_SUCCESS;
+ } else {
+ Rlog.w(TAG, "SATELLITE_ACCESS_CONTROLLER pull too frequent, skipping");
+ return StatsManager.PULL_SKIP;
+ }
+ }
+
/** Registers a pulled atom ID {@code atomId}. */
private void registerAtom(int atomId) {
mStatsManager.setPullAtomCallback(atomId, /* metadata= */ null,
@@ -972,7 +1085,8 @@
state.foldState,
state.overrideVoiceService,
state.isDataEnabled,
- state.isIwlanCrossSim);
+ state.isIwlanCrossSim,
+ state.isNtn);
}
private static StatsEvent buildStatsEvent(VoiceCallRatUsage usage) {
@@ -1030,7 +1144,10 @@
session.isIwlanCrossSimAtStart,
session.isIwlanCrossSimAtEnd,
session.isIwlanCrossSimAtConnected,
- session.vonrEnabled);
+ session.vonrEnabled,
+ session.isNtn,
+ session.supportsBusinessCallComposer,
+ session.callComposerStatus);
}
@@ -1052,7 +1169,9 @@
sms.carrierId,
sms.messageId,
sms.count,
- sms.isManagedProfile);
+ sms.isManagedProfile,
+ sms.isNtn,
+ sms.isEmergency);
}
private static StatsEvent buildStatsEvent(OutgoingSms sms) {
@@ -1075,7 +1194,9 @@
sms.count,
sms.sendErrorCode,
sms.networkErrorCode,
- sms.isManagedProfile);
+ sms.isManagedProfile,
+ sms.isEmergency,
+ sms.isNtn);
}
private static StatsEvent buildStatsEvent(DataCallSession dataCallSession) {
@@ -1104,7 +1225,10 @@
dataCallSession.handoverFailureCauses,
dataCallSession.handoverFailureRat,
dataCallSession.isNonDds,
- dataCallSession.isIwlanCrossSim);
+ dataCallSession.isIwlanCrossSim,
+ dataCallSession.isNtn,
+ dataCallSession.isSatelliteTransport,
+ dataCallSession.isProvisioningProfile);
}
private static StatsEvent buildStatsEvent(ImsRegistrationStats stats) {
@@ -1339,7 +1463,18 @@
satelliteController.countOfDeprovisionFail,
satelliteController.totalServiceUptimeSec,
satelliteController.totalBatteryConsumptionPercent,
- satelliteController.totalBatteryChargedTimeSec);
+ satelliteController.totalBatteryChargedTimeSec,
+ satelliteController.countOfDemoModeSatelliteServiceEnablementsSuccess,
+ satelliteController.countOfDemoModeSatelliteServiceEnablementsFail,
+ satelliteController.countOfDemoModeOutgoingDatagramSuccess,
+ satelliteController.countOfDemoModeOutgoingDatagramFail,
+ satelliteController.countOfDemoModeIncomingDatagramSuccess,
+ satelliteController.countOfDemoModeIncomingDatagramFail,
+ satelliteController.countOfDatagramTypeKeepAliveSuccess,
+ satelliteController.countOfDatagramTypeKeepAliveFail,
+ satelliteController.countOfAllowedSatelliteAccess,
+ satelliteController.countOfDisallowedSatelliteAccess,
+ satelliteController.countOfSatelliteAccessCheckFail);
}
private static StatsEvent buildStatsEvent(SatelliteSession satelliteSession) {
@@ -1347,7 +1482,17 @@
SATELLITE_SESSION,
satelliteSession.satelliteServiceInitializationResult,
satelliteSession.satelliteTechnology,
- satelliteSession.count);
+ satelliteSession.count,
+ satelliteSession.satelliteServiceTerminationResult,
+ satelliteSession.initializationProcessingTimeMillis,
+ satelliteSession.terminationProcessingTimeMillis,
+ satelliteSession.sessionDurationSeconds,
+ satelliteSession.countOfOutgoingDatagramSuccess,
+ satelliteSession.countOfOutgoingDatagramFailed,
+ satelliteSession.countOfIncomingDatagramSuccess,
+ satelliteSession.countOfIncomingDatagramFailed,
+ satelliteSession.isDemoMode,
+ satelliteSession.maxNtnSignalStrengthLevel);
}
private static StatsEvent buildStatsEvent(SatelliteIncomingDatagram stats) {
@@ -1355,7 +1500,8 @@
SATELLITE_INCOMING_DATAGRAM,
stats.resultCode,
stats.datagramSizeBytes,
- stats.datagramTransferTimeMillis);
+ stats.datagramTransferTimeMillis,
+ stats.isDemoMode);
}
private static StatsEvent buildStatsEvent(SatelliteOutgoingDatagram stats) {
@@ -1364,7 +1510,8 @@
stats.datagramType,
stats.resultCode,
stats.datagramSizeBytes,
- stats.datagramTransferTimeMillis);
+ stats.datagramTransferTimeMillis,
+ stats.isDemoMode);
}
private static StatsEvent buildStatsEvent(SatelliteProvision stats) {
@@ -1389,6 +1536,83 @@
stats.isSatelliteAllowedInCurrentLocation);
}
+ private static StatsEvent buildStatsEvent(DataNetworkValidation stats) {
+ return TelephonyStatsLog.buildStatsEvent(
+ DATA_NETWORK_VALIDATION,
+ stats.networkType,
+ stats.apnTypeBitmask,
+ stats.signalStrength,
+ stats.validationResult,
+ stats.elapsedTimeInMillis,
+ stats.handoverAttempted,
+ stats.networkValidationCount);
+ }
+
+ private static StatsEvent buildStatsEvent(CarrierRoamingSatelliteSession stats) {
+ return TelephonyStatsLog.buildStatsEvent(
+ CARRIER_ROAMING_SATELLITE_SESSION,
+ stats.carrierId,
+ stats.isNtnRoamingInHomeCountry,
+ stats.totalSatelliteModeTimeSec,
+ stats.numberOfSatelliteConnections,
+ stats.avgDurationOfSatelliteConnectionSec,
+ stats.satelliteConnectionGapMinSec,
+ stats.satelliteConnectionGapAvgSec,
+ stats.satelliteConnectionGapMaxSec,
+ stats.rsrpAvg,
+ stats.rsrpMedian,
+ stats.rssnrAvg,
+ stats.rssnrMedian,
+ stats.countOfIncomingSms,
+ stats.countOfOutgoingSms,
+ stats.countOfIncomingMms,
+ stats.countOfOutgoingMms);
+ }
+
+ private static StatsEvent buildStatsEvent(CarrierRoamingSatelliteControllerStats stats) {
+ return TelephonyStatsLog.buildStatsEvent(
+ CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS,
+ stats.configDataSource,
+ stats.countOfEntitlementStatusQueryRequest,
+ stats.countOfSatelliteConfigUpdateRequest,
+ stats.countOfSatelliteNotificationDisplayed,
+ stats.satelliteSessionGapMinSec,
+ stats.satelliteSessionGapAvgSec,
+ stats.satelliteSessionGapMaxSec);
+ }
+
+ private static StatsEvent buildStatsEvent(SatelliteEntitlement stats) {
+ return TelephonyStatsLog.buildStatsEvent(
+ SATELLITE_ENTITLEMENT,
+ stats.carrierId,
+ stats.result,
+ stats.entitlementStatus,
+ stats.isRetry,
+ stats.count);
+ }
+
+ private static StatsEvent buildStatsEvent(SatelliteConfigUpdater stats) {
+ return TelephonyStatsLog.buildStatsEvent(SATELLITE_CONFIG_UPDATER,
+ stats.configVersion,
+ stats.oemConfigResult,
+ stats.carrierConfigResult,
+ stats.count);
+ }
+
+ private static StatsEvent buildStatsEvent(SatelliteAccessController stats) {
+ return TelephonyStatsLog.buildStatsEvent(
+ SATELLITE_ACCESS_CONTROLLER,
+ stats.accessControlType,
+ stats.locationQueryTimeMillis,
+ stats.onDeviceLookupTimeMillis,
+ stats.totalCheckingTimeMillis,
+ stats.isAllowed,
+ stats.isEmergency,
+ stats.resultCode,
+ stats.countryCodes,
+ stats.configDataSource);
+ }
+
/** Returns all phones in {@link PhoneFactory}, or an empty array if phones not made yet. */
static Phone[] getPhonesIfAny() {
try {
diff --git a/src/java/com/android/internal/telephony/metrics/NetworkRequestsStats.java b/src/java/com/android/internal/telephony/metrics/NetworkRequestsStats.java
index 26c28f0..6f4a1a0 100644
--- a/src/java/com/android/internal/telephony/metrics/NetworkRequestsStats.java
+++ b/src/java/com/android/internal/telephony/metrics/NetworkRequestsStats.java
@@ -59,6 +59,47 @@
networkRequestsTemplate.capability = NetworkRequestsV2.NetworkCapability.ENTERPRISE;
storage.addNetworkRequestsV2(networkRequestsTemplate);
}
+
+ if (networkRequest.hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)
+ && !networkRequest.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)) {
+
+ if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+ networkRequestsTemplate.capability =
+ NetworkRequestsV2.NetworkCapability.SATELLITE_INTERNET_RESTRICTED;
+ storage.addNetworkRequestsV2(networkRequestsTemplate);
+ }
+
+ if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ networkRequestsTemplate.capability =
+ NetworkRequestsV2.NetworkCapability.SATELLITE_MMS_RESTRICTED;
+ storage.addNetworkRequestsV2(networkRequestsTemplate);
+ }
+
+ if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
+ networkRequestsTemplate.capability =
+ NetworkRequestsV2.NetworkCapability.SATELLITE_IMS_RESTRICTED;
+ storage.addNetworkRequestsV2(networkRequestsTemplate);
+ }
+
+ if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)) {
+ networkRequestsTemplate.capability =
+ NetworkRequestsV2.NetworkCapability.SATELLITE_XCAP_RESTRICTED;
+ storage.addNetworkRequestsV2(networkRequestsTemplate);
+ }
+
+ if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) {
+ networkRequestsTemplate.capability =
+ NetworkRequestsV2.NetworkCapability.SATELLITE_EIMS_RESTRICTED;
+ storage.addNetworkRequestsV2(networkRequestsTemplate);
+ }
+
+ if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
+ networkRequestsTemplate.capability =
+ NetworkRequestsV2.NetworkCapability.SATELLITE_SUPL_RESTRICTED;
+ storage.addNetworkRequestsV2(networkRequestsTemplate);
+ }
+ }
}
/** Returns the carrier ID of the given subscription id. */
diff --git a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index f3fe8fa..12dab7a 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -30,9 +30,12 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.nano.PersistAtomsProto.CarrierIdMismatch;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
+import com.android.internal.telephony.nano.PersistAtomsProto.DataNetworkValidation;
import com.android.internal.telephony.nano.PersistAtomsProto.GbaEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerListenerEvent;
@@ -48,7 +51,10 @@
import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteAccessController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision;
@@ -172,6 +178,10 @@
/** Maximum number of Satellite relevant stats to store between pulls. */
private final int mMaxNumSatelliteStats;
private final int mMaxNumSatelliteControllerStats = 1;
+ private final int mMaxNumCarrierRoamingSatelliteSessionStats = 1;
+
+ /** Maximum number of data network validation to store during pulls. */
+ private final int mMaxNumDataNetworkValidation;
/** Stores persist atoms and persist states of the puller. */
@VisibleForTesting protected PersistAtoms mAtoms;
@@ -223,6 +233,7 @@
mMaxNumGbaEventStats = 5;
mMaxOutgoingShortCodeSms = 5;
mMaxNumSatelliteStats = 5;
+ mMaxNumDataNetworkValidation = 5;
} else {
mMaxNumVoiceCallSessions = 50;
mMaxNumSms = 25;
@@ -247,6 +258,7 @@
mMaxNumGbaEventStats = 10;
mMaxOutgoingShortCodeSms = 10;
mMaxNumSatelliteStats = 15;
+ mMaxNumDataNetworkValidation = 15;
}
mAtoms = loadAtomsFromFile();
@@ -739,6 +751,25 @@
+= stats.totalBatteryConsumptionPercent;
atom.totalBatteryChargedTimeSec
+= stats.totalBatteryChargedTimeSec;
+ atom.countOfDemoModeSatelliteServiceEnablementsSuccess
+ += stats.countOfDemoModeSatelliteServiceEnablementsSuccess;
+ atom.countOfDemoModeSatelliteServiceEnablementsFail
+ += stats.countOfDemoModeSatelliteServiceEnablementsFail;
+ atom.countOfDemoModeOutgoingDatagramSuccess
+ += stats.countOfDemoModeOutgoingDatagramSuccess;
+ atom.countOfDemoModeOutgoingDatagramFail
+ += stats.countOfDemoModeOutgoingDatagramFail;
+ atom.countOfDemoModeIncomingDatagramSuccess
+ += stats.countOfDemoModeIncomingDatagramSuccess;
+ atom.countOfDemoModeIncomingDatagramFail
+ += stats.countOfDemoModeIncomingDatagramFail;
+ atom.countOfDatagramTypeKeepAliveSuccess
+ += stats.countOfDatagramTypeKeepAliveSuccess;
+ atom.countOfDatagramTypeKeepAliveFail
+ += stats.countOfDatagramTypeKeepAliveFail;
+ atom.countOfAllowedSatelliteAccess += stats.countOfAllowedSatelliteAccess;
+ atom.countOfDisallowedSatelliteAccess += stats.countOfDisallowedSatelliteAccess;
+ atom.countOfSatelliteAccessCheckFail += stats.countOfSatelliteAccessCheckFail;
mAtoms.satelliteController = atomArray;
saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
@@ -791,6 +822,90 @@
saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
}
+ /** Adds a data network validation to the storage. */
+ public synchronized void addDataNetworkValidation(DataNetworkValidation dataNetworkValidation) {
+ DataNetworkValidation existingStats = find(dataNetworkValidation);
+ if (existingStats != null) {
+ int count = existingStats.networkValidationCount
+ + dataNetworkValidation.networkValidationCount;
+ long elapsedTime = ((dataNetworkValidation.elapsedTimeInMillis
+ * dataNetworkValidation.networkValidationCount) + (
+ existingStats.elapsedTimeInMillis * existingStats.networkValidationCount))
+ / count;
+ existingStats.networkValidationCount = count;
+ existingStats.elapsedTimeInMillis = elapsedTime;
+ } else {
+ mAtoms.dataNetworkValidation = insertAtRandomPlace(
+ mAtoms.dataNetworkValidation, dataNetworkValidation, mMaxNumDataCallSessions);
+ }
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
+ }
+
+ /** Adds a new {@link CarrierRoamingSatelliteSession} to the storage. */
+ public synchronized void addCarrierRoamingSatelliteSessionStats(
+ CarrierRoamingSatelliteSession stats) {
+ mAtoms.carrierRoamingSatelliteSession = insertAtRandomPlace(
+ mAtoms.carrierRoamingSatelliteSession, stats,
+ mMaxNumCarrierRoamingSatelliteSessionStats);
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
+ }
+
+ /** Adds a new {@link CarrierRoamingSatelliteControllerStats} to the storage. */
+ public synchronized void addCarrierRoamingSatelliteControllerStats(
+ CarrierRoamingSatelliteControllerStats stats) {
+ // CarrierRoamingSatelliteController is a single data point
+ CarrierRoamingSatelliteControllerStats[] atomArray =
+ mAtoms.carrierRoamingSatelliteControllerStats;
+ if (atomArray == null || atomArray.length == 0) {
+ atomArray = new CarrierRoamingSatelliteControllerStats[] {new
+ CarrierRoamingSatelliteControllerStats()};
+ }
+
+ CarrierRoamingSatelliteControllerStats atom = atomArray[0];
+ atom.configDataSource = stats.configDataSource;
+ atom.countOfEntitlementStatusQueryRequest += stats.countOfEntitlementStatusQueryRequest;
+ atom.countOfSatelliteConfigUpdateRequest += stats.countOfSatelliteConfigUpdateRequest;
+ atom.countOfSatelliteNotificationDisplayed += stats.countOfSatelliteNotificationDisplayed;
+ atom.satelliteSessionGapMinSec = stats.satelliteSessionGapMinSec;
+ atom.satelliteSessionGapAvgSec = stats.satelliteSessionGapAvgSec;
+ atom.satelliteSessionGapMaxSec = stats.satelliteSessionGapMaxSec;
+
+ mAtoms.carrierRoamingSatelliteControllerStats = atomArray;
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
+ }
+
+ /** Adds a new {@link SatelliteEntitlement} to the storage. */
+ public synchronized void addSatelliteEntitlementStats(SatelliteEntitlement stats) {
+ SatelliteEntitlement existingStats = find(stats);
+ if (existingStats != null) {
+ existingStats.count += 1;
+ } else {
+ mAtoms.satelliteEntitlement = insertAtRandomPlace(mAtoms.satelliteEntitlement,
+ stats, mMaxNumSatelliteStats);
+ }
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
+ }
+
+ /** Adds a new {@link SatelliteConfigUpdater} to the storage. */
+ public synchronized void addSatelliteConfigUpdaterStats(SatelliteConfigUpdater stats) {
+ SatelliteConfigUpdater existingStats = find(stats);
+ if (existingStats != null) {
+ existingStats.count += 1;
+ } else {
+ mAtoms.satelliteConfigUpdater = insertAtRandomPlace(mAtoms.satelliteConfigUpdater,
+ stats, mMaxNumSatelliteStats);
+ }
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
+ }
+
+ /** Adds a new {@link SatelliteAccessController} to the storage. */
+ public synchronized void addSatelliteAccessControllerStats(SatelliteAccessController stats) {
+ mAtoms.satelliteAccessController =
+ insertAtRandomPlace(mAtoms.satelliteAccessController, stats,
+ mMaxNumSatelliteStats);
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_UPDATE_MILLIS);
+ }
+
/**
* Returns and clears the voice call sessions if last pulled longer than {@code
* minIntervalMillis} ago, otherwise returns {@code null}.
@@ -1439,7 +1554,7 @@
long minIntervalMillis) {
if (getWallTimeMillis() - mAtoms.satelliteSosMessageRecommenderPullTimestampMillis
> minIntervalMillis) {
- mAtoms.satelliteProvisionPullTimestampMillis = getWallTimeMillis();
+ mAtoms.satelliteSosMessageRecommenderPullTimestampMillis = getWallTimeMillis();
SatelliteSosMessageRecommender[] statsArray = mAtoms.satelliteSosMessageRecommender;
mAtoms.satelliteSosMessageRecommender = new SatelliteSosMessageRecommender[0];
saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
@@ -1449,6 +1564,121 @@
}
}
+ /**
+ * Returns and clears the data network validation if last pulled longer than {@code
+ * minIntervalMillis} ago, otherwise returns {@code null}.
+ */
+ @Nullable
+ public synchronized DataNetworkValidation[] getDataNetworkValidation(long minIntervalMillis) {
+ long wallTime = getWallTimeMillis();
+ if (wallTime - mAtoms.dataNetworkValidationPullTimestampMillis > minIntervalMillis) {
+ mAtoms.dataNetworkValidationPullTimestampMillis = wallTime;
+ DataNetworkValidation[] previousDataNetworkValidation = mAtoms.dataNetworkValidation;
+ mAtoms.dataNetworkValidation = new DataNetworkValidation[0];
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
+ return previousDataNetworkValidation;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns and clears the {@link CarrierRoamingSatelliteSession} stats if last pulled
+ * longer than {@code minIntervalMillis} ago, otherwise returns {@code null}.
+ */
+ @Nullable
+ public synchronized CarrierRoamingSatelliteSession[] getCarrierRoamingSatelliteSessionStats(
+ long minIntervalMillis) {
+ if (getWallTimeMillis() - mAtoms.carrierRoamingSatelliteSessionPullTimestampMillis
+ > minIntervalMillis) {
+ mAtoms.carrierRoamingSatelliteSessionPullTimestampMillis = getWallTimeMillis();
+ CarrierRoamingSatelliteSession[] statsArray = mAtoms.carrierRoamingSatelliteSession;
+ mAtoms.carrierRoamingSatelliteSession = new CarrierRoamingSatelliteSession[0];
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
+ return statsArray;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns and clears the {@link CarrierRoamingSatelliteControllerStats} stats if last pulled
+ * longer than {@code minIntervalMillis} ago, otherwise returns {@code null}.
+ */
+ @Nullable
+ public synchronized CarrierRoamingSatelliteControllerStats[]
+ getCarrierRoamingSatelliteControllerStats(long minIntervalMillis) {
+ if (getWallTimeMillis() - mAtoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis
+ > minIntervalMillis) {
+ mAtoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis = getWallTimeMillis();
+ CarrierRoamingSatelliteControllerStats[] statsArray =
+ mAtoms.carrierRoamingSatelliteControllerStats;
+ mAtoms.carrierRoamingSatelliteControllerStats =
+ new CarrierRoamingSatelliteControllerStats[0];
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
+ return statsArray;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns and clears the {@link SatelliteEntitlement} stats if last pulled longer than {@code
+ * minIntervalMillis} ago, otherwise returns {@code null}.
+ */
+ @Nullable
+ public synchronized SatelliteEntitlement[] getSatelliteEntitlementStats(
+ long minIntervalMillis) {
+ if (getWallTimeMillis() - mAtoms.satelliteEntitlementPullTimestampMillis
+ > minIntervalMillis) {
+ mAtoms.satelliteEntitlementPullTimestampMillis = getWallTimeMillis();
+ SatelliteEntitlement[] statsArray = mAtoms.satelliteEntitlement;
+ mAtoms.satelliteEntitlement = new SatelliteEntitlement[0];
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
+ return statsArray;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns and clears the {@link SatelliteConfigUpdater} stats if last pulled longer than {@code
+ * minIntervalMillis} ago, otherwise returns {@code null}.
+ */
+ @Nullable
+ public synchronized SatelliteConfigUpdater[] getSatelliteConfigUpdaterStats(
+ long minIntervalMillis) {
+ if (getWallTimeMillis() - mAtoms.satelliteConfigUpdaterPullTimestampMillis
+ > minIntervalMillis) {
+ mAtoms.satelliteConfigUpdaterPullTimestampMillis = getWallTimeMillis();
+ SatelliteConfigUpdater[] statsArray = mAtoms.satelliteConfigUpdater;
+ mAtoms.satelliteConfigUpdater = new SatelliteConfigUpdater[0];
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
+ return statsArray;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns and clears the {@link SatelliteAccessController} stats if last pulled longer
+ * than {@code minIntervalMillis} ago, otherwise returns {@code null}.
+ */
+ @Nullable
+ public synchronized SatelliteAccessController[] getSatelliteAccessControllerStats(
+ long minIntervalMillis) {
+ if (getWallTimeMillis() - mAtoms.satelliteAccessControllerPullTimestampMillis
+ > minIntervalMillis) {
+ mAtoms.satelliteAccessControllerPullTimestampMillis = getWallTimeMillis();
+ SatelliteAccessController[] statsArray = mAtoms.satelliteAccessController;
+ mAtoms.satelliteAccessController = new SatelliteAccessController[0];
+ saveAtomsToFile(SAVE_TO_FILE_DELAY_FOR_GET_MILLIS);
+ return statsArray;
+ } else {
+ return null;
+ }
+ }
+
/** Saves {@link PersistAtoms} to a file in private storage immediately. */
public synchronized void flushAtoms() {
saveAtomsToFile(0);
@@ -1599,6 +1829,25 @@
atoms.satelliteSosMessageRecommender = sanitizeAtoms(
atoms.satelliteSosMessageRecommender, SatelliteSosMessageRecommender.class,
mMaxNumSatelliteStats);
+ atoms.dataNetworkValidation =
+ sanitizeAtoms(
+ atoms.dataNetworkValidation,
+ DataNetworkValidation.class,
+ mMaxNumDataNetworkValidation
+ );
+ atoms.carrierRoamingSatelliteSession = sanitizeAtoms(
+ atoms.carrierRoamingSatelliteSession, CarrierRoamingSatelliteSession.class,
+ mMaxNumSatelliteStats);
+ atoms.carrierRoamingSatelliteControllerStats = sanitizeAtoms(
+ atoms.carrierRoamingSatelliteControllerStats,
+ CarrierRoamingSatelliteControllerStats.class, mMaxNumSatelliteControllerStats);
+ atoms.satelliteEntitlement = sanitizeAtoms(atoms.satelliteEntitlement,
+ SatelliteEntitlement.class, mMaxNumSatelliteStats);
+ atoms.satelliteConfigUpdater = sanitizeAtoms(atoms.satelliteConfigUpdater,
+ SatelliteConfigUpdater.class, mMaxNumSatelliteStats);
+ atoms.satelliteAccessController = sanitizeAtoms(
+ atoms.satelliteAccessController, SatelliteAccessController.class,
+ mMaxNumSatelliteStats);
// out of caution, sanitize also the timestamps
atoms.voiceCallRatUsagePullTimestampMillis =
@@ -1661,6 +1910,18 @@
sanitizeTimestamp(atoms.satelliteProvisionPullTimestampMillis);
atoms.satelliteSosMessageRecommenderPullTimestampMillis =
sanitizeTimestamp(atoms.satelliteSosMessageRecommenderPullTimestampMillis);
+ atoms.dataNetworkValidationPullTimestampMillis =
+ sanitizeTimestamp(atoms.dataNetworkValidationPullTimestampMillis);
+ atoms.carrierRoamingSatelliteSessionPullTimestampMillis = sanitizeTimestamp(
+ atoms.carrierRoamingSatelliteSessionPullTimestampMillis);
+ atoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis = sanitizeTimestamp(
+ atoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis);
+ atoms.satelliteEntitlementPullTimestampMillis =
+ sanitizeTimestamp(atoms.satelliteEntitlementPullTimestampMillis);
+ atoms.satelliteConfigUpdaterPullTimestampMillis =
+ sanitizeTimestamp(atoms.satelliteConfigUpdaterPullTimestampMillis);
+ atoms.satelliteAccessControllerPullTimestampMillis =
+ sanitizeTimestamp(atoms.satelliteAccessControllerPullTimestampMillis);
return atoms;
} catch (NoSuchFileException e) {
Rlog.d(TAG, "PersistAtoms file not found");
@@ -1715,7 +1976,8 @@
&& state.foldState == key.foldState
&& state.overrideVoiceService == key.overrideVoiceService
&& state.isDataEnabled == key.isDataEnabled
- && state.isIwlanCrossSim == key.isIwlanCrossSim) {
+ && state.isIwlanCrossSim == key.isIwlanCrossSim
+ && state.isNtn == key.isNtn) {
return state;
}
}
@@ -2049,7 +2311,7 @@
}
/**
- * Returns SatelliteOutgoingDatagram atom that has same values or {@code null}
+ * Returns SatelliteSession atom that has same values or {@code null}
* if it does not exist.
*/
private @Nullable SatelliteSession find(
@@ -2057,7 +2319,19 @@
for (SatelliteSession stats : mAtoms.satelliteSession) {
if (stats.satelliteServiceInitializationResult
== key.satelliteServiceInitializationResult
- && stats.satelliteTechnology == key.satelliteTechnology) {
+ && stats.satelliteTechnology == key.satelliteTechnology
+ && stats.satelliteServiceTerminationResult
+ == key.satelliteServiceTerminationResult
+ && stats.initializationProcessingTimeMillis
+ == key.initializationProcessingTimeMillis
+ && stats.terminationProcessingTimeMillis == key.terminationProcessingTimeMillis
+ && stats.sessionDurationSeconds == key.sessionDurationSeconds
+ && stats.countOfOutgoingDatagramSuccess == key.countOfOutgoingDatagramSuccess
+ && stats.countOfOutgoingDatagramFailed == key.countOfOutgoingDatagramFailed
+ && stats.countOfIncomingDatagramSuccess == key.countOfIncomingDatagramSuccess
+ && stats.countOfIncomingDatagramFailed == key.countOfIncomingDatagramFailed
+ && stats.isDemoMode == key.isDemoMode
+ && stats.maxNtnSignalStrengthLevel == key.maxNtnSignalStrengthLevel) {
return stats;
}
}
@@ -2065,7 +2339,7 @@
}
/**
- * Returns SatelliteOutgoingDatagram atom that has same values or {@code null}
+ * Returns SatelliteSosMessageRecommender atom that has same values or {@code null}
* if it does not exist.
*/
private @Nullable SatelliteSosMessageRecommender find(
@@ -2084,6 +2358,53 @@
}
/**
+ * Returns SatelliteOutgoingDatagram atom that has same values or {@code null}
+ * if it does not exist.
+ */
+ private @Nullable DataNetworkValidation find(DataNetworkValidation key) {
+ for (DataNetworkValidation stats : mAtoms.dataNetworkValidation) {
+ if (stats.networkType == key.networkType
+ && stats.apnTypeBitmask == key.apnTypeBitmask
+ && stats.signalStrength == key.signalStrength
+ && stats.validationResult == key.validationResult
+ && stats.handoverAttempted == key.handoverAttempted) {
+ return stats;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns SatelliteEntitlement atom that has same values or {@code null} if it does not exist.
+ */
+ private @Nullable SatelliteEntitlement find(SatelliteEntitlement key) {
+ for (SatelliteEntitlement stats : mAtoms.satelliteEntitlement) {
+ if (stats.carrierId == key.carrierId
+ && stats.result == key.result
+ && stats.entitlementStatus == key.entitlementStatus
+ && stats.isRetry == key.isRetry) {
+ return stats;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns SatelliteConfigUpdater atom that has same values
+ * or {@code null} if it does not exist.
+ */
+ private @Nullable SatelliteConfigUpdater find(SatelliteConfigUpdater key) {
+ for (SatelliteConfigUpdater stats : mAtoms.satelliteConfigUpdater) {
+ if (stats.configVersion == key.configVersion
+ && stats.oemConfigResult == key.oemConfigResult
+ && stats.carrierConfigResult == key.carrierConfigResult) {
+ return stats;
+ }
+ }
+ return null;
+ }
+
+ /**
* Inserts a new element in a random position in an array with a maximum size.
*
* <p>If the array is full, merge with existing item if possible or replace one item randomly.
@@ -2339,6 +2660,12 @@
atoms.satelliteOutgoingDatagramPullTimestampMillis = currentTime;
atoms.satelliteProvisionPullTimestampMillis = currentTime;
atoms.satelliteSosMessageRecommenderPullTimestampMillis = currentTime;
+ atoms.dataNetworkValidationPullTimestampMillis = currentTime;
+ atoms.carrierRoamingSatelliteSessionPullTimestampMillis = currentTime;
+ atoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis = currentTime;
+ atoms.satelliteEntitlementPullTimestampMillis = currentTime;
+ atoms.satelliteConfigUpdaterPullTimestampMillis = currentTime;
+ atoms.satelliteAccessControllerPullTimestampMillis = currentTime;
Rlog.d(TAG, "created new PersistAtoms");
return atoms;
diff --git a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
index 55eee1a..c2b2753 100644
--- a/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
+++ b/src/java/com/android/internal/telephony/metrics/SatelliteStats.java
@@ -16,15 +16,28 @@
package com.android.internal.telephony.metrics;
+import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
+
+import android.telephony.satellite.NtnSignalStrength;
+import android.telephony.satellite.SatelliteManager;
+
import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteAccessController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteSession;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteSosMessageRecommender;
+import com.android.internal.telephony.satellite.SatelliteConstants;
import com.android.telephony.Rlog;
+import java.util.Arrays;
+
/** Tracks Satellite metrics for each phone */
public class SatelliteStats {
private static final String TAG = SatelliteStats.class.getSimpleName();
@@ -67,6 +80,17 @@
private final int mTotalServiceUptimeSec;
private final int mTotalBatteryConsumptionPercent;
private final int mTotalBatteryChargedTimeSec;
+ private final int mCountOfDemoModeSatelliteServiceEnablementsSuccess;
+ private final int mCountOfDemoModeSatelliteServiceEnablementsFail;
+ private final int mCountOfDemoModeOutgoingDatagramSuccess;
+ private final int mCountOfDemoModeOutgoingDatagramFail;
+ private final int mCountOfDemoModeIncomingDatagramSuccess;
+ private final int mCountOfDemoModeIncomingDatagramFail;
+ private final int mCountOfDatagramTypeKeepAliveSuccess;
+ private final int mCountOfDatagramTypeKeepAliveFail;
+ private final int mCountOfAllowedSatelliteAccess;
+ private final int mCountOfDisallowedSatelliteAccess;
+ private final int mCountOfSatelliteAccessCheckFail;
private SatelliteControllerParams(Builder builder) {
this.mCountOfSatelliteServiceEnablementsSuccess =
@@ -90,6 +114,28 @@
this.mTotalServiceUptimeSec = builder.mTotalServiceUptimeSec;
this.mTotalBatteryConsumptionPercent = builder.mTotalBatteryConsumptionPercent;
this.mTotalBatteryChargedTimeSec = builder.mTotalBatteryChargedTimeSec;
+ this.mCountOfDemoModeSatelliteServiceEnablementsSuccess =
+ builder.mCountOfDemoModeSatelliteServiceEnablementsSuccess;
+ this.mCountOfDemoModeSatelliteServiceEnablementsFail =
+ builder.mCountOfDemoModeSatelliteServiceEnablementsFail;
+ this.mCountOfDemoModeOutgoingDatagramSuccess =
+ builder.mCountOfDemoModeOutgoingDatagramSuccess;
+ this.mCountOfDemoModeOutgoingDatagramFail =
+ builder.mCountOfDemoModeOutgoingDatagramFail;
+ this.mCountOfDemoModeIncomingDatagramSuccess =
+ builder.mCountOfDemoModeIncomingDatagramSuccess;
+ this.mCountOfDemoModeIncomingDatagramFail =
+ builder.mCountOfDemoModeIncomingDatagramFail;
+ this.mCountOfDatagramTypeKeepAliveSuccess =
+ builder.mCountOfDatagramTypeKeepAliveSuccess;
+ this.mCountOfDatagramTypeKeepAliveFail =
+ builder.mCountOfDatagramTypeKeepAliveFail;
+ this.mCountOfAllowedSatelliteAccess =
+ builder.mCountOfAllowedSatelliteAccess;
+ this.mCountOfDisallowedSatelliteAccess =
+ builder.mCountOfDisallowedSatelliteAccess;
+ this.mCountOfSatelliteAccessCheckFail =
+ builder.mCountOfSatelliteAccessCheckFail;
}
public int getCountOfSatelliteServiceEnablementsSuccess() {
@@ -160,6 +206,50 @@
return mTotalBatteryChargedTimeSec;
}
+ public int getCountOfDemoModeSatelliteServiceEnablementsSuccess() {
+ return mCountOfDemoModeSatelliteServiceEnablementsSuccess;
+ }
+
+ public int getCountOfDemoModeSatelliteServiceEnablementsFail() {
+ return mCountOfDemoModeSatelliteServiceEnablementsFail;
+ }
+
+ public int getCountOfDemoModeOutgoingDatagramSuccess() {
+ return mCountOfDemoModeOutgoingDatagramSuccess;
+ }
+
+ public int getCountOfDemoModeOutgoingDatagramFail() {
+ return mCountOfDemoModeOutgoingDatagramFail;
+ }
+
+ public int getCountOfDemoModeIncomingDatagramSuccess() {
+ return mCountOfDemoModeIncomingDatagramSuccess;
+ }
+
+ public int getCountOfDemoModeIncomingDatagramFail() {
+ return mCountOfDemoModeIncomingDatagramFail;
+ }
+
+ public int getCountOfDatagramTypeKeepAliveSuccess() {
+ return mCountOfDatagramTypeKeepAliveSuccess;
+ }
+
+ public int getCountOfDatagramTypeKeepAliveFail() {
+ return mCountOfDatagramTypeKeepAliveFail;
+ }
+
+ public int getCountOfAllowedSatelliteAccess() {
+ return mCountOfAllowedSatelliteAccess;
+ }
+
+ public int getCountOfDisallowedSatelliteAccess() {
+ return mCountOfDisallowedSatelliteAccess;
+ }
+
+ public int getCountOfSatelliteAccessCheckFail() {
+ return mCountOfSatelliteAccessCheckFail;
+ }
+
/**
* A builder class to create {@link SatelliteControllerParams} data structure class
*/
@@ -181,6 +271,17 @@
private int mTotalServiceUptimeSec = 0;
private int mTotalBatteryConsumptionPercent = 0;
private int mTotalBatteryChargedTimeSec = 0;
+ private int mCountOfDemoModeSatelliteServiceEnablementsSuccess = 0;
+ private int mCountOfDemoModeSatelliteServiceEnablementsFail = 0;
+ private int mCountOfDemoModeOutgoingDatagramSuccess = 0;
+ private int mCountOfDemoModeOutgoingDatagramFail = 0;
+ private int mCountOfDemoModeIncomingDatagramSuccess = 0;
+ private int mCountOfDemoModeIncomingDatagramFail = 0;
+ private int mCountOfDatagramTypeKeepAliveSuccess = 0;
+ private int mCountOfDatagramTypeKeepAliveFail = 0;
+ private int mCountOfAllowedSatelliteAccess = 0;
+ private int mCountOfDisallowedSatelliteAccess = 0;
+ private int mCountOfSatelliteAccessCheckFail = 0;
/**
* Sets countOfSatelliteServiceEnablementsSuccess value of {@link SatelliteController}
@@ -345,6 +446,121 @@
}
/**
+ * Sets countOfDemoModeSatelliteServiceEnablementsSuccess value of
+ * {@link SatelliteController} atom then returns Builder class
+ */
+ public Builder setCountOfDemoModeSatelliteServiceEnablementsSuccess(
+ int countOfDemoModeSatelliteServiceEnablementsSuccess) {
+ this.mCountOfDemoModeSatelliteServiceEnablementsSuccess =
+ countOfDemoModeSatelliteServiceEnablementsSuccess;
+ return this;
+ }
+
+ /**
+ * Sets countOfDemoModeSatelliteServiceEnablementsFail value of
+ * {@link SatelliteController} atom then returns Builder class
+ */
+ public Builder setCountOfDemoModeSatelliteServiceEnablementsFail(
+ int countOfDemoModeSatelliteServiceEnablementsFail) {
+ this.mCountOfDemoModeSatelliteServiceEnablementsFail =
+ countOfDemoModeSatelliteServiceEnablementsFail;
+ return this;
+ }
+
+ /**
+ * Sets countOfDemoModeOutgoingDatagramSuccess value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfDemoModeOutgoingDatagramSuccess(
+ int countOfDemoModeOutgoingDatagramSuccess) {
+ this.mCountOfDemoModeOutgoingDatagramSuccess =
+ countOfDemoModeOutgoingDatagramSuccess;
+ return this;
+ }
+
+ /**
+ * Sets countOfDemoModeOutgoingDatagramFail value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfDemoModeOutgoingDatagramFail(
+ int countOfDemoModeOutgoingDatagramFail) {
+ this.mCountOfDemoModeOutgoingDatagramFail = countOfDemoModeOutgoingDatagramFail;
+ return this;
+ }
+
+ /**
+ * Sets countOfDemoModeIncomingDatagramSuccess value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfDemoModeIncomingDatagramSuccess(
+ int countOfDemoModeIncomingDatagramSuccess) {
+ this.mCountOfDemoModeIncomingDatagramSuccess =
+ countOfDemoModeIncomingDatagramSuccess;
+ return this;
+ }
+
+ /**
+ * Sets countOfDemoModeIncomingDatagramFail value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfDemoModeIncomingDatagramFail(
+ int countOfDemoModeIncomingDatagramFail) {
+ this.mCountOfDemoModeIncomingDatagramFail = countOfDemoModeIncomingDatagramFail;
+ return this;
+ }
+
+ /**
+ * Sets countOfDatagramTypeKeepAliveSuccess value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfDatagramTypeKeepAliveSuccess(
+ int countOfDatagramTypeKeepAliveSuccess) {
+ this.mCountOfDatagramTypeKeepAliveSuccess = countOfDatagramTypeKeepAliveSuccess;
+ return this;
+ }
+
+ /**
+ * Sets countOfDatagramTypeKeepAliveFail value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfDatagramTypeKeepAliveFail(
+ int countOfDatagramTypeKeepAliveFail) {
+ this.mCountOfDatagramTypeKeepAliveFail = countOfDatagramTypeKeepAliveFail;
+ return this;
+ }
+
+ /**
+ * Sets countOfAllowedSatelliteAccess value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfAllowedSatelliteAccess(
+ int countOfAllowedSatelliteAccess) {
+ this.mCountOfAllowedSatelliteAccess =
+ countOfAllowedSatelliteAccess;
+ return this;
+ }
+
+ /**
+ * Sets countOfDisallowedSatelliteAccess value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfDisallowedSatelliteAccess(
+ int countOfDisallowedSatelliteAccess) {
+ this.mCountOfDisallowedSatelliteAccess = countOfDisallowedSatelliteAccess;
+ return this;
+ }
+
+ /**
+ * Sets countOfSatelliteAccessCheckFail value of {@link SatelliteController} atom
+ * then returns Builder class
+ */
+ public Builder setCountOfSatelliteAccessCheckFail(
+ int countOfSatelliteAccessCheckFail) {
+ this.mCountOfSatelliteAccessCheckFail = countOfSatelliteAccessCheckFail;
+ return this;
+ }
+
+ /**
* Returns ControllerParams, which contains whole component of
* {@link SatelliteController} atom
*/
@@ -374,6 +590,25 @@
+ ", serviceUptimeSec=" + mTotalServiceUptimeSec
+ ", batteryConsumptionPercent=" + mTotalBatteryConsumptionPercent
+ ", batteryChargedTimeSec=" + mTotalBatteryChargedTimeSec
+ + ", countOfDemoModeSatelliteServiceEnablementsSuccess="
+ + mCountOfDemoModeSatelliteServiceEnablementsSuccess
+ + ", countOfDemoModeSatelliteServiceEnablementsFail="
+ + mCountOfDemoModeSatelliteServiceEnablementsFail
+ + ", countOfDemoModeOutgoingDatagramSuccess="
+ + mCountOfDemoModeOutgoingDatagramSuccess
+ + ", countOfDemoModeOutgoingDatagramFail="
+ + mCountOfDemoModeOutgoingDatagramFail
+ + ", countOfDemoModeIncomingDatagramSuccess="
+ + mCountOfDemoModeIncomingDatagramSuccess
+ + ", countOfDemoModeIncomingDatagramFail="
+ + mCountOfDemoModeIncomingDatagramFail
+ + ", countOfDatagramTypeKeepAliveSuccess="
+ + mCountOfDatagramTypeKeepAliveSuccess
+ + ", countOfDatagramTypeKeepAliveFail="
+ + mCountOfDatagramTypeKeepAliveFail
+ + ", countOfAllowedSatelliteAccess=" + mCountOfAllowedSatelliteAccess
+ + ", countOfDisallowedSatelliteAccess=" + mCountOfDisallowedSatelliteAccess
+ + ", countOfSatelliteAccessCheckFail=" + mCountOfSatelliteAccessCheckFail
+ ")";
}
}
@@ -385,11 +620,32 @@
public class SatelliteSessionParams {
private final int mSatelliteServiceInitializationResult;
private final int mSatelliteTechnology;
+ private final int mTerminationResult;
+ private final long mInitializationProcessingTimeMillis;
+ private final long mTerminationProcessingTimeMillis;
+ private final int mSessionDurationSec;
+ private final int mCountOfOutgoingDatagramSuccess;
+ private final int mCountOfOutgoingDatagramFailed;
+ private final int mCountOfIncomingDatagramSuccess;
+ private final int mCountOfIncomingDatagramFailed;
+ private final boolean mIsDemoMode;
+ private final @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel;
private SatelliteSessionParams(Builder builder) {
this.mSatelliteServiceInitializationResult =
builder.mSatelliteServiceInitializationResult;
this.mSatelliteTechnology = builder.mSatelliteTechnology;
+ this.mTerminationResult = builder.mTerminationResult;
+ this.mInitializationProcessingTimeMillis = builder.mInitializationProcessingTimeMillis;
+ this.mTerminationProcessingTimeMillis =
+ builder.mTerminationProcessingTimeMillis;
+ this.mSessionDurationSec = builder.mSessionDurationSec;
+ this.mCountOfOutgoingDatagramSuccess = builder.mCountOfOutgoingDatagramSuccess;
+ this.mCountOfOutgoingDatagramFailed = builder.mCountOfOutgoingDatagramFailed;
+ this.mCountOfIncomingDatagramSuccess = builder.mCountOfIncomingDatagramSuccess;
+ this.mCountOfIncomingDatagramFailed = builder.mCountOfIncomingDatagramFailed;
+ this.mIsDemoMode = builder.mIsDemoMode;
+ this.mMaxNtnSignalStrengthLevel = builder.mMaxNtnSignalStrengthLevel;
}
public int getSatelliteServiceInitializationResult() {
@@ -400,12 +656,63 @@
return mSatelliteTechnology;
}
+ public int getTerminationResult() {
+ return mTerminationResult;
+ }
+
+ public long getInitializationProcessingTime() {
+ return mInitializationProcessingTimeMillis;
+ }
+
+ public long getTerminationProcessingTime() {
+ return mTerminationProcessingTimeMillis;
+ }
+
+ public int getSessionDuration() {
+ return mSessionDurationSec;
+ }
+
+ public int getCountOfOutgoingDatagramSuccess() {
+ return mCountOfOutgoingDatagramSuccess;
+ }
+
+ public int getCountOfOutgoingDatagramFailed() {
+ return mCountOfOutgoingDatagramFailed;
+ }
+
+ public int getCountOfIncomingDatagramSuccess() {
+ return mCountOfIncomingDatagramSuccess;
+ }
+
+ public int getCountOfIncomingDatagramFailed() {
+ return mCountOfIncomingDatagramFailed;
+ }
+
+ public boolean getIsDemoMode() {
+ return mIsDemoMode;
+ }
+
+ public @NtnSignalStrength.NtnSignalStrengthLevel int getMaxNtnSignalStrengthLevel() {
+ return mMaxNtnSignalStrengthLevel;
+ }
+
/**
* A builder class to create {@link SatelliteSessionParams} data structure class
*/
public static class Builder {
private int mSatelliteServiceInitializationResult = -1;
private int mSatelliteTechnology = -1;
+ private int mTerminationResult = -1;
+ private long mInitializationProcessingTimeMillis = -1;
+ private long mTerminationProcessingTimeMillis = -1;
+ private int mSessionDurationSec = -1;
+ private int mCountOfOutgoingDatagramSuccess = -1;
+ private int mCountOfOutgoingDatagramFailed = -1;
+ private int mCountOfIncomingDatagramSuccess = -1;
+ private int mCountOfIncomingDatagramFailed = -1;
+ private boolean mIsDemoMode = false;
+ private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel =
+ NTN_SIGNAL_STRENGTH_NONE;
/**
* Sets satelliteServiceInitializationResult value of {@link SatelliteSession}
@@ -426,6 +733,68 @@
return this;
}
+ /** Sets the satellite de-initialization result. */
+ public Builder setTerminationResult(
+ @SatelliteManager.SatelliteResult int result) {
+ this.mTerminationResult = result;
+ return this;
+ }
+
+ /** Sets the satellite initialization processing time. */
+ public Builder setInitializationProcessingTime(long processingTime) {
+ this.mInitializationProcessingTimeMillis = processingTime;
+ return this;
+ }
+
+ /** Sets the satellite de-initialization processing time. */
+ public Builder setTerminationProcessingTime(long processingTime) {
+ this.mTerminationProcessingTimeMillis = processingTime;
+ return this;
+ }
+
+ /** Sets the total enabled time for the satellite session. */
+ public Builder setSessionDuration(int sessionDurationSec) {
+ this.mSessionDurationSec = sessionDurationSec;
+ return this;
+ }
+
+ /** Sets the total number of successful outgoing datagram transmission. */
+ public Builder setCountOfOutgoingDatagramSuccess(int countOfoutgoingDatagramSuccess) {
+ this.mCountOfOutgoingDatagramSuccess = countOfoutgoingDatagramSuccess;
+ return this;
+ }
+
+ /** Sets the total number of failed outgoing datagram transmission. */
+ public Builder setCountOfOutgoingDatagramFailed(int countOfoutgoingDatagramFailed) {
+ this.mCountOfOutgoingDatagramFailed = countOfoutgoingDatagramFailed;
+ return this;
+ }
+
+ /** Sets the total number of successful incoming datagram transmission. */
+ public Builder setCountOfIncomingDatagramSuccess(int countOfincomingDatagramSuccess) {
+ this.mCountOfIncomingDatagramSuccess = countOfincomingDatagramSuccess;
+ return this;
+ }
+
+ /** Sets the total number of failed incoming datagram transmission. */
+ public Builder setCountOfIncomingDatagramFailed(int countOfincomingDatagramFailed) {
+ this.mCountOfIncomingDatagramFailed = countOfincomingDatagramFailed;
+ return this;
+ }
+
+ /** Sets whether enabled satellite session is for demo mode or not. */
+ public Builder setIsDemoMode(boolean isDemoMode) {
+ this.mIsDemoMode = isDemoMode;
+ return this;
+ }
+
+ /** Sets the max ntn signal strength for the satellite session */
+ public Builder setMaxNtnSignalStrengthLevel(
+ @NtnSignalStrength.NtnSignalStrengthLevel int maxNtnSignalStrengthLevel) {
+ this.mMaxNtnSignalStrengthLevel = maxNtnSignalStrengthLevel;
+ return this;
+ }
+
/**
* Returns SessionParams, which contains whole component of
* {@link SatelliteSession} atom
@@ -441,7 +810,16 @@
return "SessionParams("
+ ", satelliteServiceInitializationResult="
+ mSatelliteServiceInitializationResult
- + ", satelliteTechnology=" + mSatelliteTechnology
+ + ", TerminationResult=" + mTerminationResult
+ + ", InitializationProcessingTimeMillis=" + mInitializationProcessingTimeMillis
+ + ", TerminationProcessingTimeMillis=" + mTerminationProcessingTimeMillis
+ + ", SessionDurationSec=" + mSessionDurationSec
+ + ", CountOfOutgoingDatagramSuccess=" + mCountOfOutgoingDatagramSuccess
+ + ", CountOfOutgoingDatagramFailed=" + mCountOfOutgoingDatagramFailed
+ + ", CountOfIncomingDatagramSuccess=" + mCountOfIncomingDatagramSuccess
+ + ", CountOfIncomingDatagramFailed=" + mCountOfIncomingDatagramFailed
+ + ", IsDemoMode=" + mIsDemoMode
+ + ", MaxNtnSignalStrengthLevel=" + mMaxNtnSignalStrengthLevel
+ ")";
}
}
@@ -454,11 +832,13 @@
private final int mResultCode;
private final int mDatagramSizeBytes;
private final long mDatagramTransferTimeMillis;
+ private final boolean mIsDemoMode;
private SatelliteIncomingDatagramParams(Builder builder) {
this.mResultCode = builder.mResultCode;
this.mDatagramSizeBytes = builder.mDatagramSizeBytes;
this.mDatagramTransferTimeMillis = builder.mDatagramTransferTimeMillis;
+ this.mIsDemoMode = builder.mIsDemoMode;
}
public int getResultCode() {
@@ -473,6 +853,10 @@
return mDatagramTransferTimeMillis;
}
+ public boolean getIsDemoMode() {
+ return mIsDemoMode;
+ }
+
/**
* A builder class to create {@link SatelliteIncomingDatagramParams} data structure class
*/
@@ -480,6 +864,7 @@
private int mResultCode = -1;
private int mDatagramSizeBytes = -1;
private long mDatagramTransferTimeMillis = -1;
+ private boolean mIsDemoMode = false;
/**
* Sets resultCode value of {@link SatelliteIncomingDatagram} atom
@@ -509,6 +894,15 @@
}
/**
+ * Sets whether transferred datagram is in demo mode or not
+ * then returns Builder class
+ */
+ public Builder setIsDemoMode(boolean isDemoMode) {
+ this.mIsDemoMode = isDemoMode;
+ return this;
+ }
+
+ /**
* Returns IncomingDatagramParams, which contains whole component of
* {@link SatelliteIncomingDatagram} atom
*/
@@ -523,7 +917,9 @@
return "IncomingDatagramParams("
+ ", resultCode=" + mResultCode
+ ", datagramSizeBytes=" + mDatagramSizeBytes
- + ", datagramTransferTimeMillis=" + mDatagramTransferTimeMillis + ")";
+ + ", datagramTransferTimeMillis=" + mDatagramTransferTimeMillis
+ + ", isDemoMode=" + mIsDemoMode
+ + ")";
}
}
@@ -536,12 +932,14 @@
private final int mResultCode;
private final int mDatagramSizeBytes;
private final long mDatagramTransferTimeMillis;
+ private final boolean mIsDemoMode;
private SatelliteOutgoingDatagramParams(Builder builder) {
this.mDatagramType = builder.mDatagramType;
this.mResultCode = builder.mResultCode;
this.mDatagramSizeBytes = builder.mDatagramSizeBytes;
this.mDatagramTransferTimeMillis = builder.mDatagramTransferTimeMillis;
+ this.mIsDemoMode = builder.mIsDemoMode;
}
public int getDatagramType() {
@@ -560,6 +958,10 @@
return mDatagramTransferTimeMillis;
}
+ public boolean getIsDemoMode() {
+ return mIsDemoMode;
+ }
+
/**
* A builder class to create {@link SatelliteOutgoingDatagramParams} data structure class
*/
@@ -568,6 +970,7 @@
private int mResultCode = -1;
private int mDatagramSizeBytes = -1;
private long mDatagramTransferTimeMillis = -1;
+ private boolean mIsDemoMode = false;
/**
* Sets datagramType value of {@link SatelliteOutgoingDatagram} atom
@@ -606,6 +1009,15 @@
}
/**
+ * Sets whether transferred datagram is in demo mode or not
+ * then returns Builder class
+ */
+ public Builder setIsDemoMode(boolean isDemoMode) {
+ this.mIsDemoMode = isDemoMode;
+ return this;
+ }
+
+ /**
* Returns OutgoingDatagramParams, which contains whole component of
* {@link SatelliteOutgoingDatagram} atom
*/
@@ -621,7 +1033,9 @@
+ "datagramType=" + mDatagramType
+ ", resultCode=" + mResultCode
+ ", datagramSizeBytes=" + mDatagramSizeBytes
- + ", datagramTransferTimeMillis=" + mDatagramTransferTimeMillis + ")";
+ + ", datagramTransferTimeMillis=" + mDatagramTransferTimeMillis
+ + ", isDemoMode=" + mIsDemoMode
+ + ")";
}
}
@@ -877,6 +1291,854 @@
}
}
+ /**
+ * A data class to contain whole component of {@link CarrierRoamingSatelliteSession} atom.
+ * Refer to {@link #onCarrierRoamingSatelliteSessionMetrics(
+ * CarrierRoamingSatelliteSessionParams)}.
+ */
+ public class CarrierRoamingSatelliteSessionParams {
+ private final int mCarrierId;
+ private final boolean mIsNtnRoamingInHomeCountry;
+ private final int mTotalSatelliteModeTimeSec;
+ private final int mNumberOfSatelliteConnections;
+ private final int mAvgDurationOfSatelliteConnectionSec;
+ private final int mSatelliteConnectionGapMinSec;
+ private final int mSatelliteConnectionGapAvgSec;
+ private final int mSatelliteConnectionGapMaxSec;
+ private final int mRsrpAvg;
+ private final int mRsrpMedian;
+ private final int mRssnrAvg;
+ private final int mRssnrMedian;
+ private final int mCountOfIncomingSms;
+ private final int mCountOfOutgoingSms;
+ private final int mCountOfIncomingMms;
+ private final int mCountOfOutgoingMms;
+
+ private CarrierRoamingSatelliteSessionParams(Builder builder) {
+ this.mCarrierId = builder.mCarrierId;
+ this.mIsNtnRoamingInHomeCountry = builder.mIsNtnRoamingInHomeCountry;
+ this.mTotalSatelliteModeTimeSec = builder.mTotalSatelliteModeTimeSec;
+ this.mNumberOfSatelliteConnections = builder.mNumberOfSatelliteConnections;
+ this.mAvgDurationOfSatelliteConnectionSec =
+ builder.mAvgDurationOfSatelliteConnectionSec;
+ this.mSatelliteConnectionGapMinSec = builder.mSatelliteConnectionGapMinSec;
+ this.mSatelliteConnectionGapAvgSec = builder.mSatelliteConnectionGapAvgSec;
+ this.mSatelliteConnectionGapMaxSec = builder.mSatelliteConnectionGapMaxSec;
+ this.mRsrpAvg = builder.mRsrpAvg;
+ this.mRsrpMedian = builder.mRsrpMedian;
+ this.mRssnrAvg = builder.mRssnrAvg;
+ this.mRssnrMedian = builder.mRssnrMedian;
+ this.mCountOfIncomingSms = builder.mCountOfIncomingSms;
+ this.mCountOfOutgoingSms = builder.mCountOfOutgoingSms;
+ this.mCountOfIncomingMms = builder.mCountOfIncomingMms;
+ this.mCountOfOutgoingMms = builder.mCountOfOutgoingMms;
+ }
+
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
+ public boolean getIsNtnRoamingInHomeCountry() {
+ return mIsNtnRoamingInHomeCountry;
+ }
+
+ public int getTotalSatelliteModeTimeSec() {
+ return mTotalSatelliteModeTimeSec;
+ }
+
+ public int getNumberOfSatelliteConnections() {
+ return mNumberOfSatelliteConnections;
+ }
+
+ public int getAvgDurationOfSatelliteConnectionSec() {
+ return mAvgDurationOfSatelliteConnectionSec;
+ }
+
+ public int getSatelliteConnectionGapMinSec() {
+ return mSatelliteConnectionGapMinSec;
+ }
+
+ public int getSatelliteConnectionGapAvgSec() {
+ return mSatelliteConnectionGapAvgSec;
+ }
+
+ public int getSatelliteConnectionGapMaxSec() {
+ return mSatelliteConnectionGapMaxSec;
+ }
+
+ public int getRsrpAvg() {
+ return mRsrpAvg;
+ }
+
+ public int getRsrpMedian() {
+ return mRsrpMedian;
+ }
+
+ public int getRssnrAvg() {
+ return mRssnrAvg;
+ }
+
+ public int getRssnrMedian() {
+ return mRssnrMedian;
+ }
+
+ public int getCountOfIncomingSms() {
+ return mCountOfIncomingSms;
+ }
+
+ public int getCountOfOutgoingSms() {
+ return mCountOfOutgoingSms;
+ }
+
+ public int getCountOfIncomingMms() {
+ return mCountOfIncomingMms;
+ }
+
+ public int getCountOfOutgoingMms() {
+ return mCountOfOutgoingMms;
+ }
+
+ /**
+ * A builder class to create {@link CarrierRoamingSatelliteSessionParams} data structure
+ * class
+ */
+ public static class Builder {
+ private int mCarrierId = -1;
+ private boolean mIsNtnRoamingInHomeCountry = false;
+ private int mTotalSatelliteModeTimeSec = 0;
+ private int mNumberOfSatelliteConnections = 0;
+ private int mAvgDurationOfSatelliteConnectionSec = 0;
+ private int mSatelliteConnectionGapMinSec = 0;
+ private int mSatelliteConnectionGapAvgSec = 0;
+ private int mSatelliteConnectionGapMaxSec = 0;
+ private int mRsrpAvg = 0;
+ private int mRsrpMedian = 0;
+ private int mRssnrAvg = 0;
+ private int mRssnrMedian = 0;
+ private int mCountOfIncomingSms = 0;
+ private int mCountOfOutgoingSms = 0;
+ private int mCountOfIncomingMms = 0;
+ private int mCountOfOutgoingMms = 0;
+
+ /**
+ * Sets carrierId value of {@link CarrierRoamingSatelliteSession} atom
+ * then returns Builder class
+ */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ return this;
+ }
+
+ /**
+ * Sets isNtnRoamingInHomeCountry value of {@link CarrierRoamingSatelliteSession} atom
+ * then returns Builder class
+ */
+ public Builder setIsNtnRoamingInHomeCountry(boolean isNtnRoamingInHomeCountry) {
+ this.mIsNtnRoamingInHomeCountry = isNtnRoamingInHomeCountry;
+ return this;
+ }
+
+ /**
+ * Sets totalSatelliteModeTimeSec value of {@link CarrierRoamingSatelliteSession} atom
+ * then returns Builder class
+ */
+ public Builder setTotalSatelliteModeTimeSec(int totalSatelliteModeTimeSec) {
+ this.mTotalSatelliteModeTimeSec = totalSatelliteModeTimeSec;
+ return this;
+ }
+
+
+ /**
+ * Sets numberOfSatelliteConnections value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setNumberOfSatelliteConnections(int numberOfSatelliteConnections) {
+ this.mNumberOfSatelliteConnections = numberOfSatelliteConnections;
+ return this;
+ }
+
+ /**
+ * Sets avgDurationOfSatelliteConnectionSec value of
+ * {@link CarrierRoamingSatelliteSession} atom then returns Builder class
+ */
+ public Builder setAvgDurationOfSatelliteConnectionSec(
+ int avgDurationOfSatelliteConnectionSec) {
+ this.mAvgDurationOfSatelliteConnectionSec = avgDurationOfSatelliteConnectionSec;
+ return this;
+ }
+
+ /**
+ * Sets satelliteConnectionGapMinSec value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setSatelliteConnectionGapMinSec(int satelliteConnectionGapMinSec) {
+ this.mSatelliteConnectionGapMinSec = satelliteConnectionGapMinSec;
+ return this;
+ }
+
+ /**
+ * Sets satelliteConnectionGapAvgSec value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setSatelliteConnectionGapAvgSec(int satelliteConnectionGapAvgSec) {
+ this.mSatelliteConnectionGapAvgSec = satelliteConnectionGapAvgSec;
+ return this;
+ }
+
+ /**
+ * Sets satelliteConnectionGapMaxSec value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setSatelliteConnectionGapMaxSec(int satelliteConnectionGapMaxSec) {
+ this.mSatelliteConnectionGapMaxSec = satelliteConnectionGapMaxSec;
+ return this;
+ }
+
+ /**
+ * Sets rsrpAvg value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setRsrpAvg(int rsrpAvg) {
+ this.mRsrpAvg = rsrpAvg;
+ return this;
+ }
+
+ /**
+ * Sets rsrpMedian value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setRsrpMedian(int rsrpMedian) {
+ this.mRsrpMedian = rsrpMedian;
+ return this;
+ }
+
+ /**
+ * Sets rssnrAvg value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setRssnrAvg(int rssnrAvg) {
+ this.mRssnrAvg = rssnrAvg;
+ return this;
+ }
+
+ /**
+ * Sets rssnrMedian value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setRssnrMedian(int rssnrMedian) {
+ this.mRssnrMedian = rssnrMedian;
+ return this;
+ }
+
+
+ /**
+ * Sets countOfIncomingSms value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setCountOfIncomingSms(int countOfIncomingSms) {
+ this.mCountOfIncomingSms = countOfIncomingSms;
+ return this;
+ }
+
+ /**
+ * Sets countOfOutgoingSms value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setCountOfOutgoingSms(int countOfOutgoingSms) {
+ this.mCountOfOutgoingSms = countOfOutgoingSms;
+ return this;
+ }
+
+ /**
+ * Sets countOfIncomingMms value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setCountOfIncomingMms(int countOfIncomingMms) {
+ this.mCountOfIncomingMms = countOfIncomingMms;
+ return this;
+ }
+
+ /**
+ * Sets countOfOutgoingMms value of {@link CarrierRoamingSatelliteSession}
+ * atom then returns Builder class
+ */
+ public Builder setCountOfOutgoingMms(int countOfOutgoingMms) {
+ this.mCountOfOutgoingMms = countOfOutgoingMms;
+ return this;
+ }
+
+ /**
+ * Returns CarrierRoamingSatelliteSessionParams, which contains whole component of
+ * {@link CarrierRoamingSatelliteSession} atom
+ */
+ public CarrierRoamingSatelliteSessionParams build() {
+ return new SatelliteStats()
+ .new CarrierRoamingSatelliteSessionParams(Builder.this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "CarrierRoamingSatelliteSessionParams("
+ + "carrierId=" + mCarrierId
+ + ", isNtnRoamingInHomeCountry=" + mIsNtnRoamingInHomeCountry
+ + ", totalSatelliteModeTimeSec=" + mTotalSatelliteModeTimeSec
+ + ", numberOfSatelliteConnections=" + mNumberOfSatelliteConnections
+ + ", avgDurationOfSatelliteConnectionSec="
+ + mAvgDurationOfSatelliteConnectionSec
+ + ", satelliteConnectionGapMinSec=" + mSatelliteConnectionGapMinSec
+ + ", satelliteConnectionGapAvgSec=" + mSatelliteConnectionGapAvgSec
+ + ", satelliteConnectionGapMaxSec=" + mSatelliteConnectionGapMaxSec
+ + ", rsrpAvg=" + mRsrpAvg
+ + ", rsrpMedian=" + mRsrpMedian
+ + ", rssnrAvg=" + mRssnrAvg
+ + ", rssnrMedian=" + mRssnrMedian
+ + ", countOfIncomingSms=" + mCountOfIncomingSms
+ + ", countOfOutgoingSms=" + mCountOfOutgoingSms
+ + ", countOfIncomingMms=" + mCountOfIncomingMms
+ + ", countOfOutgoingMms=" + mCountOfOutgoingMms
+ + ")";
+ }
+ }
+
+ /**
+ * A data class to contain whole component of {@link CarrierRoamingSatelliteControllerStats}
+ * atom. Refer to {@link #onCarrierRoamingSatelliteControllerStatsMetrics(
+ * CarrierRoamingSatelliteControllerStatsParams)}.
+ */
+ public class CarrierRoamingSatelliteControllerStatsParams {
+ private final int mConfigDataSource;
+ private final int mCountOfEntitlementStatusQueryRequest;
+ private final int mCountOfSatelliteConfigUpdateRequest;
+ private final int mCountOfSatelliteNotificationDisplayed;
+ private final int mSatelliteSessionGapMinSec;
+ private final int mSatelliteSessionGapAvgSec;
+ private final int mSatelliteSessionGapMaxSec;
+
+ private CarrierRoamingSatelliteControllerStatsParams(Builder builder) {
+ this.mConfigDataSource = builder.mConfigDataSource;
+ this.mCountOfEntitlementStatusQueryRequest =
+ builder.mCountOfEntitlementStatusQueryRequest;
+ this.mCountOfSatelliteConfigUpdateRequest =
+ builder.mCountOfSatelliteConfigUpdateRequest;
+ this.mCountOfSatelliteNotificationDisplayed =
+ builder.mCountOfSatelliteNotificationDisplayed;
+ this.mSatelliteSessionGapMinSec = builder.mSatelliteSessionGapMinSec;
+ this.mSatelliteSessionGapAvgSec = builder.mSatelliteSessionGapAvgSec;
+ this.mSatelliteSessionGapMaxSec = builder.mSatelliteSessionGapMaxSec;
+ }
+
+ public int getConfigDataSource() {
+ return mConfigDataSource;
+ }
+
+
+ public int getCountOfEntitlementStatusQueryRequest() {
+ return mCountOfEntitlementStatusQueryRequest;
+ }
+
+ public int getCountOfSatelliteConfigUpdateRequest() {
+ return mCountOfSatelliteConfigUpdateRequest;
+ }
+
+ public int getCountOfSatelliteNotificationDisplayed() {
+ return mCountOfSatelliteNotificationDisplayed;
+ }
+
+ public int getSatelliteSessionGapMinSec() {
+ return mSatelliteSessionGapMinSec;
+ }
+
+ public int getSatelliteSessionGapAvgSec() {
+ return mSatelliteSessionGapAvgSec;
+ }
+
+ public int getSatelliteSessionGapMaxSec() {
+ return mSatelliteSessionGapMaxSec;
+ }
+
+ /**
+ * A builder class to create {@link CarrierRoamingSatelliteControllerStatsParams}
+ * data structure class
+ */
+ public static class Builder {
+ private int mConfigDataSource = SatelliteConstants.CONFIG_DATA_SOURCE_UNKNOWN;
+ private int mCountOfEntitlementStatusQueryRequest = 0;
+ private int mCountOfSatelliteConfigUpdateRequest = 0;
+ private int mCountOfSatelliteNotificationDisplayed = 0;
+ private int mSatelliteSessionGapMinSec = 0;
+ private int mSatelliteSessionGapAvgSec = 0;
+ private int mSatelliteSessionGapMaxSec = 0;
+
+ /**
+ * Sets configDataSource value of {@link CarrierRoamingSatelliteControllerStats} atom
+ * then returns Builder class
+ */
+ public Builder setConfigDataSource(int configDataSource) {
+ this.mConfigDataSource = configDataSource;
+ return this;
+ }
+
+ /**
+ * Sets countOfEntitlementStatusQueryRequest value of
+ * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
+ */
+ public Builder setCountOfEntitlementStatusQueryRequest(
+ int countOfEntitlementStatusQueryRequest) {
+ this.mCountOfEntitlementStatusQueryRequest = countOfEntitlementStatusQueryRequest;
+ return this;
+ }
+
+ /**
+ * Sets countOfSatelliteConfigUpdateRequest value of
+ * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
+ */
+ public Builder setCountOfSatelliteConfigUpdateRequest(
+ int countOfSatelliteConfigUpdateRequest) {
+ this.mCountOfSatelliteConfigUpdateRequest = countOfSatelliteConfigUpdateRequest;
+ return this;
+ }
+
+ /**
+ * Sets countOfSatelliteNotificationDisplayed value of
+ * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
+ */
+ public Builder setCountOfSatelliteNotificationDisplayed(
+ int countOfSatelliteNotificationDisplayed) {
+ this.mCountOfSatelliteNotificationDisplayed = countOfSatelliteNotificationDisplayed;
+ return this;
+ }
+
+ /**
+ * Sets satelliteSessionGapMinSec value of
+ * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
+ */
+ public Builder setSatelliteSessionGapMinSec(int satelliteSessionGapMinSec) {
+ this.mSatelliteSessionGapMinSec = satelliteSessionGapMinSec;
+ return this;
+ }
+
+ /**
+ * Sets satelliteSessionGapAvgSec value of
+ * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
+ */
+ public Builder setSatelliteSessionGapAvgSec(int satelliteSessionGapAvgSec) {
+ this.mSatelliteSessionGapAvgSec = satelliteSessionGapAvgSec;
+ return this;
+ }
+
+ /**
+ * Sets satelliteSessionGapMaxSec value of
+ * {@link CarrierRoamingSatelliteControllerStats} atom then returns Builder class
+ */
+ public Builder setSatelliteSessionGapMaxSec(int satelliteSessionGapMaxSec) {
+ this.mSatelliteSessionGapMaxSec = satelliteSessionGapMaxSec;
+ return this;
+ }
+
+ /**
+ * Returns CarrierRoamingSatelliteControllerStatsParams, which contains whole component
+ * of {@link CarrierRoamingSatelliteControllerStats} atom
+ */
+ public CarrierRoamingSatelliteControllerStatsParams build() {
+ return new SatelliteStats()
+ .new CarrierRoamingSatelliteControllerStatsParams(Builder.this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "CarrierRoamingSatelliteControllerStatsParams("
+ + "configDataSource=" + mConfigDataSource
+ + ", countOfEntitlementStatusQueryRequest="
+ + mCountOfEntitlementStatusQueryRequest
+ + ", countOfSatelliteConfigUpdateRequest="
+ + mCountOfSatelliteConfigUpdateRequest
+ + ", countOfSatelliteNotificationDisplayed="
+ + mCountOfSatelliteNotificationDisplayed
+ + ", satelliteSessionGapMinSec=" + mSatelliteSessionGapMinSec
+ + ", satelliteSessionGapAvgSec=" + mSatelliteSessionGapAvgSec
+ + ", satelliteSessionGapMaxSec=" + mSatelliteSessionGapMaxSec
+ + ")";
+ }
+ }
+
+ /**
+ * A data class to contain whole component of {@link SatelliteEntitlement} atom.
+ * Refer to {@link #onSatelliteEntitlementMetrics(SatelliteEntitlementParams)}.
+ */
+ public class SatelliteEntitlementParams {
+ private final int mCarrierId;
+ private final int mResult;
+ private final int mEntitlementStatus;
+ private final boolean mIsRetry;
+ private final int mCount;
+
+ private SatelliteEntitlementParams(Builder builder) {
+ this.mCarrierId = builder.mCarrierId;
+ this.mResult = builder.mResult;
+ this.mEntitlementStatus = builder.mEntitlementStatus;
+ this.mIsRetry = builder.mIsRetry;
+ this.mCount = builder.mCount;
+ }
+
+ public int getCarrierId() {
+ return mCarrierId;
+ }
+
+ public int getResult() {
+ return mResult;
+ }
+
+ public int getEntitlementStatus() {
+ return mEntitlementStatus;
+ }
+
+ public boolean getIsRetry() {
+ return mIsRetry;
+ }
+
+ public int getCount() {
+ return mCount;
+ }
+
+ /**
+ * A builder class to create {@link SatelliteEntitlementParams} data structure class
+ */
+ public static class Builder {
+ private int mCarrierId = -1;
+ private int mResult = -1;
+ private int mEntitlementStatus = -1;
+ private boolean mIsRetry = false;
+ private int mCount = -1;
+
+ /**
+ * Sets carrierId value of {@link SatelliteEntitlement} atom
+ * then returns Builder class
+ */
+ public Builder setCarrierId(int carrierId) {
+ this.mCarrierId = carrierId;
+ return this;
+ }
+
+ /**
+ * Sets result value of {@link SatelliteEntitlement} atom
+ * then returns Builder class
+ */
+ public Builder setResult(int result) {
+ this.mResult = result;
+ return this;
+ }
+
+ /**
+ * Sets entitlementStatus value of {@link SatelliteEntitlement} atom
+ * then returns Builder class
+ */
+ public Builder setEntitlementStatus(int entitlementStatus) {
+ this.mEntitlementStatus = entitlementStatus;
+ return this;
+ }
+
+ /**
+ * Sets isRetry value of {@link SatelliteEntitlement} atom
+ * then returns Builder class
+ */
+ public Builder setIsRetry(boolean isRetry) {
+ this.mIsRetry = isRetry;
+ return this;
+ }
+
+ /**
+ * Sets count value of {@link SatelliteEntitlement} atom
+ * then returns Builder class
+ */
+ public Builder setCount(int count) {
+ this.mCount = count;
+ return this;
+ }
+
+ /**
+ * Returns SatelliteEntitlementParams, which contains whole component of
+ * {@link SatelliteEntitlement} atom
+ */
+ public SatelliteEntitlementParams build() {
+ return new SatelliteStats()
+ .new SatelliteEntitlementParams(Builder.this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SatelliteEntitlementParams("
+ + "carrierId=" + mCarrierId
+ + ", result=" + mResult
+ + ", entitlementStatus=" + mEntitlementStatus
+ + ", isRetry=" + mIsRetry
+ + ", count=" + mCount + ")";
+ }
+ }
+
+ /**
+ * A data class to contain whole component of {@link SatelliteConfigUpdater} atom.
+ * Refer to {@link #onSatelliteConfigUpdaterMetrics(SatelliteConfigUpdaterParams)}.
+ */
+ public class SatelliteConfigUpdaterParams {
+ private final int mConfigVersion;
+ private final int mOemConfigResult;
+ private final int mCarrierConfigResult;
+ private final int mCount;
+
+ private SatelliteConfigUpdaterParams(Builder builder) {
+ this.mConfigVersion = builder.mConfigVersion;
+ this.mOemConfigResult = builder.mOemConfigResult;
+ this.mCarrierConfigResult = builder.mCarrierConfigResult;
+ this.mCount = builder.mCount;
+ }
+
+ public int getConfigVersion() {
+ return mConfigVersion;
+ }
+
+ public int getOemConfigResult() {
+ return mOemConfigResult;
+ }
+
+ public int getCarrierConfigResult() {
+ return mCarrierConfigResult;
+ }
+
+ public int getCount() {
+ return mCount;
+ }
+
+ /**
+ * A builder class to create {@link SatelliteConfigUpdaterParams} data structure class
+ */
+ public static class Builder {
+ private int mConfigVersion = -1;
+ private int mOemConfigResult = -1;
+ private int mCarrierConfigResult = -1;
+ private int mCount = -1;
+
+ /**
+ * Sets configVersion value of {@link SatelliteConfigUpdater} atom
+ * then returns Builder class
+ */
+ public Builder setConfigVersion(int configVersion) {
+ this.mConfigVersion = configVersion;
+ return this;
+ }
+
+ /**
+ * Sets oemConfigResult value of {@link SatelliteConfigUpdater} atom
+ * then returns Builder class
+ */
+ public Builder setOemConfigResult(int oemConfigResult) {
+ this.mOemConfigResult = oemConfigResult;
+ return this;
+ }
+
+ /**
+ * Sets carrierConfigResult value of {@link SatelliteConfigUpdater} atom
+ * then returns Builder class
+ */
+ public Builder setCarrierConfigResult(int carrierConfigResult) {
+ this.mCarrierConfigResult = carrierConfigResult;
+ return this;
+ }
+
+ /**
+ * Sets count value of {@link SatelliteConfigUpdater} atom
+ * then returns Builder class
+ */
+ public Builder setCount(int count) {
+ this.mCount = count;
+ return this;
+ }
+
+ /**
+ * Returns SatelliteConfigUpdaterParams, which contains whole component of
+ * {@link SatelliteConfigUpdater} atom
+ */
+ public SatelliteConfigUpdaterParams build() {
+ return new SatelliteStats()
+ .new SatelliteConfigUpdaterParams(Builder.this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "SatelliteConfigUpdaterParams("
+ + "configVersion=" + mConfigVersion
+ + ", oemConfigResult=" + mOemConfigResult
+ + ", carrierConfigResult=" + mCarrierConfigResult
+ + ", count=" + mCount + ")";
+ }
+ }
+
+ /**
+ * A data class to contain whole component of {@link SatelliteAccessControllerParams} atom.
+ * Refer to {@link #onSatelliteAccessControllerMetrics(SatelliteAccessControllerParams)}.
+ */
+ public class SatelliteAccessControllerParams {
+ private final @SatelliteConstants.AccessControlType int mAccessControlType;
+ private final long mLocationQueryTimeMillis;
+ private final long mOnDeviceLookupTimeMillis;
+ private final long mTotalCheckingTimeMillis;
+ private final boolean mIsAllowed;
+ private final boolean mIsEmergency;
+ private final @SatelliteManager.SatelliteResult int mResultCode;
+ private final String[] mCountryCodes;
+ private final @SatelliteConstants.ConfigDataSource int mConfigDataSource;
+
+ private SatelliteAccessControllerParams(Builder builder) {
+ this.mAccessControlType = builder.mAccessControlType;
+ this.mLocationQueryTimeMillis = builder.mLocationQueryTimeMillis;
+ this.mOnDeviceLookupTimeMillis = builder.mOnDeviceLookupTimeMillis;
+ this.mTotalCheckingTimeMillis = builder.mTotalCheckingTimeMillis;
+ this.mIsAllowed = builder.mIsAllowed;
+ this.mIsEmergency = builder.mIsEmergency;
+ this.mResultCode = builder.mResultCode;
+ this.mCountryCodes = builder.mCountryCodes;
+ this.mConfigDataSource = builder.mConfigDataSource;
+ }
+
+ public @SatelliteConstants.AccessControlType int getAccessControlType() {
+ return mAccessControlType;
+ }
+
+ public long getLocationQueryTime() {
+ return mLocationQueryTimeMillis;
+ }
+
+ public long getOnDeviceLookupTime() {
+ return mOnDeviceLookupTimeMillis;
+ }
+
+ public long getTotalCheckingTime() {
+ return mTotalCheckingTimeMillis;
+ }
+
+ public boolean getIsAllowed() {
+ return mIsAllowed;
+ }
+
+ public boolean getIsEmergency() {
+ return mIsEmergency;
+ }
+
+ public @SatelliteManager.SatelliteResult int getResultCode() {
+ return mResultCode;
+ }
+
+ public String[] getCountryCodes() {
+ return mCountryCodes;
+ }
+
+ public @SatelliteConstants.ConfigDataSource int getConfigDataSource() {
+ return mConfigDataSource;
+ }
+
+ /**
+ * A builder class to create {@link SatelliteAccessControllerParams} data structure class
+ */
+ public static class Builder {
+ private @SatelliteConstants.AccessControlType int mAccessControlType;
+ private long mLocationQueryTimeMillis;
+ private long mOnDeviceLookupTimeMillis;
+ private long mTotalCheckingTimeMillis;
+ private boolean mIsAllowed;
+ private boolean mIsEmergency;
+ private @SatelliteManager.SatelliteResult int mResultCode;
+ private String[] mCountryCodes;
+ private @SatelliteConstants.ConfigDataSource int mConfigDataSource;
+
+ /**
+ * Sets AccessControlType value of {@link #SatelliteAccessController}
+ * atom then returns Builder class
+ */
+ public Builder setAccessControlType(
+ @SatelliteConstants.AccessControlType int accessControlType) {
+ this.mAccessControlType = accessControlType;
+ return this;
+ }
+
+ /** Sets the location query time for current satellite enablement. */
+ public Builder setLocationQueryTime(long locationQueryTimeMillis) {
+ this.mLocationQueryTimeMillis = locationQueryTimeMillis;
+ return this;
+ }
+
+ /** Sets the on device lookup time for current satellite enablement. */
+ public Builder setOnDeviceLookupTime(long onDeviceLookupTimeMillis) {
+ this.mOnDeviceLookupTimeMillis = onDeviceLookupTimeMillis;
+ return this;
+ }
+
+ /** Sets the total checking time for current satellite enablement. */
+ public Builder setTotalCheckingTime(long totalCheckingTimeMillis) {
+ this.mTotalCheckingTimeMillis = totalCheckingTimeMillis;
+ return this;
+ }
+
+ /** Sets whether the satellite communication is allowed from current location. */
+ public Builder setIsAllowed(boolean isAllowed) {
+ this.mIsAllowed = isAllowed;
+ return this;
+ }
+
+ /** Sets whether the current satellite enablement is for emergency or not. */
+ public Builder setIsEmergency(boolean isEmergency) {
+ this.mIsEmergency = isEmergency;
+ return this;
+ }
+
+ /** Sets the result code for checking whether satellite service is allowed from current
+ location. */
+ public Builder setResult(int result) {
+ this.mResultCode = result;
+ return this;
+ }
+
+ /** Sets the country code for current location while attempting satellite enablement. */
+ public Builder setCountryCodes(String[] countryCodes) {
+ this.mCountryCodes = Arrays.stream(countryCodes).toArray(String[]::new);
+ return this;
+ }
+
+ /** Sets the config data source for checking whether satellite service is allowed from
+ current location. */
+ public Builder setConfigDatasource(int configDatasource) {
+ this.mConfigDataSource = configDatasource;
+ return this;
+ }
+
+ /**
+ * Returns AccessControllerParams, which contains whole component of
+ * {@link #SatelliteAccessController} atom
+ */
+ public SatelliteAccessControllerParams build() {
+ return new SatelliteStats()
+ .new SatelliteAccessControllerParams(this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "AccessControllerParams("
+ + ", AccessControlType=" + mAccessControlType
+ + ", LocationQueryTime=" + mLocationQueryTimeMillis
+ + ", OnDeviceLookupTime=" + mOnDeviceLookupTimeMillis
+ + ", TotalCheckingTime=" + mTotalCheckingTimeMillis
+ + ", IsAllowed=" + mIsAllowed
+ + ", IsEmergency=" + mIsEmergency
+ + ", ResultCode=" + mResultCode
+ + ", CountryCodes=" + Arrays.toString(mCountryCodes)
+ + ", ConfigDataSource=" + mConfigDataSource
+ + ")";
+ }
+ }
+
/** Create a new atom or update an existing atom for SatelliteController metrics */
public synchronized void onSatelliteControllerMetrics(SatelliteControllerParams param) {
SatelliteController proto = new SatelliteController();
@@ -901,7 +2163,18 @@
proto.totalServiceUptimeSec = param.getTotalServiceUptimeSec();
proto.totalBatteryConsumptionPercent = param.getTotalBatteryConsumptionPercent();
proto.totalBatteryChargedTimeSec = param.getTotalBatteryChargedTimeSec();
-
+ proto.countOfDemoModeSatelliteServiceEnablementsSuccess =
+ param.getCountOfDemoModeSatelliteServiceEnablementsSuccess();
+ proto.countOfDemoModeSatelliteServiceEnablementsFail =
+ param.getCountOfDemoModeSatelliteServiceEnablementsFail();
+ proto.countOfDemoModeOutgoingDatagramSuccess =
+ param.getCountOfDemoModeOutgoingDatagramSuccess();
+ proto.countOfDemoModeOutgoingDatagramFail = param.getCountOfDemoModeOutgoingDatagramFail();
+ proto.countOfDemoModeIncomingDatagramSuccess =
+ param.getCountOfDemoModeIncomingDatagramSuccess();
+ proto.countOfDemoModeIncomingDatagramFail = param.getCountOfDemoModeIncomingDatagramFail();
+ proto.countOfDatagramTypeKeepAliveSuccess = param.getCountOfDatagramTypeKeepAliveSuccess();
+ proto.countOfDatagramTypeKeepAliveFail = param.getCountOfDatagramTypeKeepAliveFail();
mAtomsStorage.addSatelliteControllerStats(proto);
}
@@ -912,6 +2185,16 @@
param.getSatelliteServiceInitializationResult();
proto.satelliteTechnology = param.getSatelliteTechnology();
proto.count = 1;
+ proto.satelliteServiceTerminationResult = param.getTerminationResult();
+ proto.initializationProcessingTimeMillis = param.getInitializationProcessingTime();
+ proto.terminationProcessingTimeMillis = param.getTerminationProcessingTime();
+ proto.sessionDurationSeconds = param.getSessionDuration();
+ proto.countOfOutgoingDatagramSuccess = param.getCountOfIncomingDatagramSuccess();
+ proto.countOfOutgoingDatagramFailed = param.getCountOfOutgoingDatagramFailed();
+ proto.countOfIncomingDatagramSuccess = param.getCountOfIncomingDatagramSuccess();
+ proto.countOfIncomingDatagramFailed = param.getCountOfOutgoingDatagramFailed();
+ proto.isDemoMode = param.getIsDemoMode();
+ proto.maxNtnSignalStrengthLevel = param.getMaxNtnSignalStrengthLevel();
mAtomsStorage.addSatelliteSessionStats(proto);
}
@@ -922,6 +2205,7 @@
proto.resultCode = param.getResultCode();
proto.datagramSizeBytes = param.getDatagramSizeBytes();
proto.datagramTransferTimeMillis = param.getDatagramTransferTimeMillis();
+ proto.isDemoMode = param.getIsDemoMode();
mAtomsStorage.addSatelliteIncomingDatagramStats(proto);
}
@@ -933,6 +2217,7 @@
proto.resultCode = param.getResultCode();
proto.datagramSizeBytes = param.getDatagramSizeBytes();
proto.datagramTransferTimeMillis = param.getDatagramTransferTimeMillis();
+ proto.isDemoMode = param.getIsDemoMode();
mAtomsStorage.addSatelliteOutgoingDatagramStats(proto);
}
@@ -960,4 +2245,78 @@
proto.count = 1;
mAtomsStorage.addSatelliteSosMessageRecommenderStats(proto);
}
+
+ /** Create a new atom for CarrierRoamingSatelliteSession metrics */
+ public synchronized void onCarrierRoamingSatelliteSessionMetrics(
+ CarrierRoamingSatelliteSessionParams param) {
+ CarrierRoamingSatelliteSession proto = new CarrierRoamingSatelliteSession();
+ proto.carrierId = param.getCarrierId();
+ proto.isNtnRoamingInHomeCountry = param.getIsNtnRoamingInHomeCountry();
+ proto.totalSatelliteModeTimeSec = param.getTotalSatelliteModeTimeSec();
+ proto.numberOfSatelliteConnections = param.getNumberOfSatelliteConnections();
+ proto.avgDurationOfSatelliteConnectionSec = param.getAvgDurationOfSatelliteConnectionSec();
+ proto.satelliteConnectionGapMinSec = param.mSatelliteConnectionGapMinSec;
+ proto.satelliteConnectionGapAvgSec = param.mSatelliteConnectionGapAvgSec;
+ proto.satelliteConnectionGapMaxSec = param.mSatelliteConnectionGapMaxSec;
+ proto.rsrpAvg = param.mRsrpAvg;
+ proto.rsrpMedian = param.mRsrpMedian;
+ proto.rssnrAvg = param.mRssnrAvg;
+ proto.rssnrMedian = param.mRssnrMedian;
+ proto.countOfIncomingSms = param.mCountOfIncomingSms;
+ proto.countOfOutgoingSms = param.mCountOfOutgoingSms;
+ proto.countOfIncomingMms = param.mCountOfIncomingMms;
+ proto.countOfOutgoingMms = param.mCountOfOutgoingMms;
+ mAtomsStorage.addCarrierRoamingSatelliteSessionStats(proto);
+ }
+
+ /** Create a new atom for CarrierRoamingSatelliteSession metrics */
+ public synchronized void onCarrierRoamingSatelliteControllerStatsMetrics(
+ CarrierRoamingSatelliteControllerStatsParams param) {
+ CarrierRoamingSatelliteControllerStats proto = new CarrierRoamingSatelliteControllerStats();
+ proto.configDataSource = param.mConfigDataSource;
+ proto.countOfEntitlementStatusQueryRequest = param.mCountOfEntitlementStatusQueryRequest;
+ proto.countOfSatelliteConfigUpdateRequest = param.mCountOfSatelliteConfigUpdateRequest;
+ proto.countOfSatelliteNotificationDisplayed = param.mCountOfSatelliteNotificationDisplayed;
+ proto.satelliteSessionGapMinSec = param.mSatelliteSessionGapMinSec;
+ proto.satelliteSessionGapAvgSec = param.mSatelliteSessionGapAvgSec;
+ proto.satelliteSessionGapMaxSec = param.mSatelliteSessionGapMaxSec;
+ mAtomsStorage.addCarrierRoamingSatelliteControllerStats(proto);
+ }
+
+ /** Create a new atom for SatelliteEntitlement metrics */
+ public synchronized void onSatelliteEntitlementMetrics(SatelliteEntitlementParams param) {
+ SatelliteEntitlement proto = new SatelliteEntitlement();
+ proto.carrierId = param.getCarrierId();
+ proto.result = param.getResult();
+ proto.entitlementStatus = param.getEntitlementStatus();
+ proto.isRetry = param.getIsRetry();
+ proto.count = param.getCount();
+ mAtomsStorage.addSatelliteEntitlementStats(proto);
+ }
+
+ /** Create a new atom for SatelliteConfigUpdater metrics */
+ public synchronized void onSatelliteConfigUpdaterMetrics(SatelliteConfigUpdaterParams param) {
+ SatelliteConfigUpdater proto = new SatelliteConfigUpdater();
+ proto.configVersion = param.getConfigVersion();
+ proto.oemConfigResult = param.getOemConfigResult();
+ proto.carrierConfigResult = param.getCarrierConfigResult();
+ proto.count = param.getCount();
+ mAtomsStorage.addSatelliteConfigUpdaterStats(proto);
+ }
+
+ /** Create a new atom or update an existing atom for SatelliteAccessController metrics */
+ public synchronized void onSatelliteAccessControllerMetrics(
+ SatelliteAccessControllerParams param) {
+ SatelliteAccessController proto = new SatelliteAccessController();
+ proto.accessControlType = param.getAccessControlType();
+ proto.locationQueryTimeMillis = param.getLocationQueryTime();
+ proto.onDeviceLookupTimeMillis = param.getOnDeviceLookupTime();
+ proto.totalCheckingTimeMillis = param.getTotalCheckingTime();
+ proto.isAllowed = param.getIsAllowed();
+ proto.isEmergency = param.getIsEmergency();
+ proto.resultCode = param.getResultCode();
+ proto.countryCodes = param.getCountryCodes();
+ proto.configDataSource = param.getConfigDataSource();
+ mAtomsStorage.addSatelliteAccessControllerStats(proto);
+ }
}
diff --git a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
index d400c22..3f24968 100644
--- a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
+++ b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
@@ -21,6 +21,7 @@
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN;
+import static com.android.internal.telephony.flags.Flags.dataRatMetricEnabled;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -31,6 +32,7 @@
import android.telephony.NetworkRegistrationInfo;
import android.telephony.ServiceState;
import android.telephony.ServiceState.RoamingType;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.stub.ImsRegistrationImplBase;
@@ -38,12 +40,14 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.TelephonyStatsLog;
import com.android.internal.telephony.data.DataNetwork;
import com.android.internal.telephony.data.DataNetworkController;
import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.telephony.Rlog;
import java.util.Set;
@@ -61,6 +65,8 @@
private final PersistAtomsStorage mStorage;
private final DeviceStateHelper mDeviceStateHelper;
private boolean mExistAnyConnectedInternetPdn;
+ private int mCurrentDataRat =
+ TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_UNSPECIFIED;
public ServiceStateStats(Phone phone) {
super(Runnable::run);
@@ -118,6 +124,7 @@
// Finish the duration of last service state and mark modem off
addServiceState(mLastState.getAndSet(new TimestampedServiceState(null, now)), now);
} else {
+ SatelliteController satelliteController = SatelliteController.getInstance();
CellularServiceState newState = new CellularServiceState();
newState.voiceRat = getVoiceRat(mPhone, serviceState);
newState.dataRat = getRat(serviceState, NetworkRegistrationInfo.DOMAIN_PS);
@@ -135,11 +142,17 @@
newState.overrideVoiceService = mOverrideVoiceService.get();
newState.isDataEnabled = mPhone.getDataSettingsManager().isDataEnabled();
newState.isIwlanCrossSim = isCrossSimCallingRegistered(mPhone);
+ newState.isNtn = satelliteController != null
+ && satelliteController.isInSatelliteModeForCarrierRoaming(mPhone);
TimestampedServiceState prevState =
mLastState.getAndSet(new TimestampedServiceState(newState, now));
addServiceStateAndSwitch(
prevState, now, getDataServiceSwitch(prevState.mServiceState, newState));
}
+
+ if (dataRatMetricEnabled()) {
+ writeDataRatAtom(serviceState);
+ }
}
/** Updates the fold state of the device for the current service state. */
@@ -306,6 +319,7 @@
copy.overrideVoiceService = state.overrideVoiceService;
copy.isDataEnabled = state.isDataEnabled;
copy.isIwlanCrossSim = state.isIwlanCrossSim;
+ copy.isNtn = state.isNtn;
return copy;
}
@@ -456,6 +470,68 @@
|| isNetworkRoaming(ss, NetworkRegistrationInfo.DOMAIN_PS);
}
+ /** Collect data Rat metric. */
+ private void writeDataRatAtom(@NonNull ServiceState serviceState) {
+ if (DataConnectionStateTracker.getActiveDataSubId() != mPhone.getSubId()) {
+ return;
+ }
+ NetworkRegistrationInfo wwanRegInfo = serviceState.getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ if (wwanRegInfo == null) {
+ return;
+ }
+ int dataRat = wwanRegInfo.getAccessNetworkTechnology();
+ int nrFrequency = serviceState.getNrFrequencyRange();
+ int nrState = serviceState.getNrState();
+ int translatedDataRat =
+ TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_UNSPECIFIED;
+ if (!SubscriptionManager.isValidSubscriptionId(mPhone.getSubId())) {
+ translatedDataRat = TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__NO_SIM;
+ } else if (dataRat == TelephonyManager.NETWORK_TYPE_EHRPD
+ || dataRat == TelephonyManager.NETWORK_TYPE_HSPAP
+ || dataRat == TelephonyManager.NETWORK_TYPE_UMTS
+ || dataRat == TelephonyManager.NETWORK_TYPE_HSDPA
+ || dataRat == TelephonyManager.NETWORK_TYPE_HSUPA
+ || dataRat == TelephonyManager.NETWORK_TYPE_HSPA
+ || dataRat == TelephonyManager.NETWORK_TYPE_EVDO_0
+ || dataRat == TelephonyManager.NETWORK_TYPE_EVDO_A
+ || dataRat == TelephonyManager.NETWORK_TYPE_EVDO_B) {
+ translatedDataRat = TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_3G;
+ } else if (dataRat == TelephonyManager.NETWORK_TYPE_1xRTT
+ || dataRat == TelephonyManager.NETWORK_TYPE_GPRS
+ || dataRat == TelephonyManager.NETWORK_TYPE_EDGE
+ || dataRat == TelephonyManager.NETWORK_TYPE_CDMA
+ || dataRat == TelephonyManager.NETWORK_TYPE_GSM) {
+ translatedDataRat = TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_2G;
+ } else if (dataRat == TelephonyManager.NETWORK_TYPE_NR) {
+ translatedDataRat = nrFrequency != ServiceState.FREQUENCY_RANGE_MMWAVE
+ ? TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_SA_FR1 :
+ TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_SA_FR2;
+ } else if (dataRat == TelephonyManager.NETWORK_TYPE_LTE) {
+ if (nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED) {
+ translatedDataRat = nrFrequency != ServiceState.FREQUENCY_RANGE_MMWAVE
+ ? TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_NSA_FR1 :
+ TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_NSA_FR2;
+ } else if (nrState == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED) {
+ translatedDataRat =
+ TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_5G_NSA_LTE;
+ } else {
+ translatedDataRat =
+ TelephonyStatsLog.DATA_RAT_STATE_CHANGED__DATA_RAT__DATA_RAT_4G_LTE;
+ }
+ }
+
+ if (translatedDataRat != mCurrentDataRat) {
+ TelephonyStatsLog.write(TelephonyStatsLog.DATA_RAT_STATE_CHANGED, translatedDataRat);
+ mCurrentDataRat = translatedDataRat;
+ }
+ }
+
+ int getCurrentDataRat() {
+ return mCurrentDataRat;
+ }
+
@VisibleForTesting
protected long getTimeMillis() {
return SystemClock.elapsedRealtime();
diff --git a/src/java/com/android/internal/telephony/metrics/SmsStats.java b/src/java/com/android/internal/telephony/metrics/SmsStats.java
index 949b72e..b62114c 100644
--- a/src/java/com/android/internal/telephony/metrics/SmsStats.java
+++ b/src/java/com/android/internal/telephony/metrics/SmsStats.java
@@ -57,9 +57,11 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.ServiceStateTracker;
+import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
+import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats;
import com.android.telephony.Rlog;
import java.util.Objects;
@@ -87,8 +89,9 @@
}
/** Create a new atom when multi-part incoming SMS is dropped due to missing parts. */
- public void onDroppedIncomingMultipartSms(boolean is3gpp2, int receivedCount, int totalCount) {
- IncomingSms proto = getIncomingDefaultProto(is3gpp2, SOURCE_NOT_INJECTED);
+ public void onDroppedIncomingMultipartSms(boolean is3gpp2, int receivedCount, int totalCount,
+ boolean isEmergency) {
+ IncomingSms proto = getIncomingDefaultProto(is3gpp2, SOURCE_NOT_INJECTED, isEmergency);
// Keep SMS tech as unknown because it's possible that it changed overtime and is not
// necessarily the current one. Similarly mark the RAT as unknown.
proto.smsTech = INCOMING_SMS__SMS_TECH__SMS_TECH_UNKNOWN;
@@ -102,21 +105,21 @@
/** Create a new atom when an SMS for the voicemail indicator is received. */
public void onIncomingSmsVoicemail(boolean is3gpp2,
@InboundSmsHandler.SmsSource int smsSource) {
- IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource);
+ IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource, false);
proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_VOICEMAIL_INDICATION;
mAtomsStorage.addIncomingSms(proto);
}
/** Create a new atom when an SMS of type zero is received. */
public void onIncomingSmsTypeZero(@InboundSmsHandler.SmsSource int smsSource) {
- IncomingSms proto = getIncomingDefaultProto(false /* is3gpp2 */, smsSource);
+ IncomingSms proto = getIncomingDefaultProto(false /* is3gpp2 */, smsSource, false);
proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_ZERO;
mAtomsStorage.addIncomingSms(proto);
}
/** Create a new atom when an SMS-PP for the SIM card is received. */
public void onIncomingSmsPP(@InboundSmsHandler.SmsSource int smsSource, boolean success) {
- IncomingSms proto = getIncomingDefaultProto(false /* is3gpp2 */, smsSource);
+ IncomingSms proto = getIncomingDefaultProto(false /* is3gpp2 */, smsSource, false);
proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_SMS_PP;
proto.error = getIncomingSmsError(success);
mAtomsStorage.addIncomingSms(proto);
@@ -125,8 +128,8 @@
/** Create a new atom when an SMS is received successfully. */
public void onIncomingSmsSuccess(boolean is3gpp2,
@InboundSmsHandler.SmsSource int smsSource, int messageCount,
- boolean blocked, long messageId) {
- IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource);
+ boolean blocked, long messageId, boolean isEmergency) {
+ IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource, isEmergency);
proto.totalParts = messageCount;
proto.receivedParts = messageCount;
proto.blocked = blocked;
@@ -136,16 +139,16 @@
/** Create a new atom when an incoming SMS has an error. */
public void onIncomingSmsError(boolean is3gpp2,
- @InboundSmsHandler.SmsSource int smsSource, int result) {
- IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource);
+ @InboundSmsHandler.SmsSource int smsSource, int result, boolean isEmergency) {
+ IncomingSms proto = getIncomingDefaultProto(is3gpp2, smsSource, isEmergency);
proto.error = getIncomingSmsError(result);
mAtomsStorage.addIncomingSms(proto);
}
/** Create a new atom when an incoming WAP_PUSH SMS is received. */
public void onIncomingSmsWapPush(@InboundSmsHandler.SmsSource int smsSource,
- int messageCount, int result, long messageId) {
- IncomingSms proto = getIncomingDefaultProto(false, smsSource);
+ int messageCount, int result, long messageId, boolean isEmergency) {
+ IncomingSms proto = getIncomingDefaultProto(false, smsSource, isEmergency);
proto.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_WAP_PUSH;
proto.totalParts = messageCount;
proto.receivedParts = messageCount;
@@ -157,18 +160,18 @@
/** Create a new atom when an outgoing SMS is sent. */
public void onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs,
@SmsManager.Result int sendErrorCode, long messageId, boolean isFromDefaultApp,
- long intervalMillis) {
+ long intervalMillis, boolean isEmergency) {
onOutgoingSms(isOverIms, is3gpp2, fallbackToCs, sendErrorCode, NO_ERROR_CODE,
- messageId, isFromDefaultApp, intervalMillis);
+ messageId, isFromDefaultApp, intervalMillis, isEmergency);
}
/** Create a new atom when an outgoing SMS is sent. */
public void onOutgoingSms(boolean isOverIms, boolean is3gpp2, boolean fallbackToCs,
@SmsManager.Result int sendErrorCode, int networkErrorCode, long messageId,
- boolean isFromDefaultApp, long intervalMillis) {
+ boolean isFromDefaultApp, long intervalMillis, boolean isEmergency) {
OutgoingSms proto =
getOutgoingDefaultProto(is3gpp2, isOverIms, messageId, isFromDefaultApp,
- intervalMillis);
+ intervalMillis, isEmergency);
// The field errorCode is used for up-to-Android-13 devices. From Android 14, sendErrorCode
// and networkErrorCode will be used. The field errorCode will be deprecated when most
@@ -201,6 +204,9 @@
proto.networkErrorCode = networkErrorCode;
mAtomsStorage.addOutgoingSms(proto);
+ CarrierRoamingSatelliteSessionStats sessionStats =
+ CarrierRoamingSatelliteSessionStats.getInstance(mPhone.getSubId());
+ sessionStats.onOutgoingSms(mPhone.getSubId());
}
/** Create a new atom when user attempted to send an outgoing short code sms. */
@@ -214,7 +220,7 @@
/** Creates a proto for a normal single-part {@code IncomingSms} with default values. */
private IncomingSms getIncomingDefaultProto(boolean is3gpp2,
- @InboundSmsHandler.SmsSource int smsSource) {
+ @InboundSmsHandler.SmsSource int smsSource, boolean isEmergency) {
IncomingSms proto = new IncomingSms();
proto.smsFormat = getSmsFormat(is3gpp2);
proto.smsTech = getSmsTech(smsSource, is3gpp2);
@@ -234,12 +240,14 @@
proto.messageId = RANDOM.nextLong();
proto.count = 1;
proto.isManagedProfile = mPhone.isManagedProfile();
+ proto.isNtn = isNonTerrestrialNetwork();
+ proto.isEmergency = isEmergency;
return proto;
}
/** Create a proto for a normal {@code OutgoingSms} with default values. */
private OutgoingSms getOutgoingDefaultProto(boolean is3gpp2, boolean isOverIms,
- long messageId, boolean isFromDefaultApp, long intervalMillis) {
+ long messageId, boolean isFromDefaultApp, long intervalMillis, boolean isEmergency) {
OutgoingSms proto = new OutgoingSms();
proto.smsFormat = getSmsFormat(is3gpp2);
proto.smsTech = getSmsTech(isOverIms, is3gpp2);
@@ -260,6 +268,8 @@
proto.intervalMillis = intervalMillis;
proto.count = 1;
proto.isManagedProfile = mPhone.isManagedProfile();
+ proto.isEmergency = isEmergency;
+ proto.isNtn = isNonTerrestrialNetwork();
return proto;
}
@@ -397,6 +407,20 @@
return phone.getCarrierId();
}
+ private boolean isNonTerrestrialNetwork() {
+ if (!Flags.carrierEnabledSatelliteFlag()) {
+ return false;
+ }
+
+ ServiceState ss = getServiceState();
+ if (ss != null) {
+ return ss.isUsingNonTerrestrialNetwork();
+ } else {
+ Rlog.e(TAG, "isNonTerrestrialNetwork(), ServiceState is null");
+ return false;
+ }
+ }
+
private void loge(String format, Object... args) {
Rlog.e(TAG, "[" + mPhone.getPhoneId() + "]" + String.format(format, args));
}
diff --git a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
index 9cf53c9..911424e 100644
--- a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
@@ -41,16 +41,19 @@
import android.content.Context;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
+import android.os.PersistableBundle;
import android.os.SystemClock;
import android.telecom.VideoProfile;
import android.telecom.VideoProfile.VideoState;
import android.telephony.Annotation.NetworkType;
import android.telephony.AnomalyReporter;
+import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PreciseDataConnectionState;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
+import android.telephony.TelephonyManager.CallComposerStatus;
import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
@@ -75,6 +78,7 @@
import com.android.internal.telephony.imsphone.ImsPhoneConnection;
import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession;
import com.android.internal.telephony.nano.TelephonyProto.TelephonyCallSession.Event.AudioCodec;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.telephony.uicc.UiccController;
import com.android.telephony.Rlog;
@@ -167,15 +171,16 @@
private final UiccController mUiccController = UiccController.getInstance();
private final DeviceStateHelper mDeviceStateHelper =
PhoneFactory.getMetricsCollector().getDeviceStateHelper();
-
private final VonrHelper mVonrHelper =
PhoneFactory.getMetricsCollector().getVonrHelper();
+ private final SatelliteController mSatelliteController;
public VoiceCallSessionStats(int phoneId, Phone phone, @NonNull FeatureFlags featureFlags) {
mPhoneId = phoneId;
mPhone = phone;
mFlags = featureFlags;
DataConnectionStateTracker.getInstance(phoneId).start(phone);
+ mSatelliteController = SatelliteController.getInstance();
}
/* CS calls */
@@ -570,6 +575,13 @@
proto.vonrEnabled = mVonrHelper.getVonrEnabled(mPhone.getSubId());
}
+ proto.supportsBusinessCallComposer = isBusinessCallSupported();
+ // 0 is defined as UNKNOWN in Enum
+ proto.callComposerStatus = getCallComposerStatusForPhone() + 1;
+
+ proto.isNtn = mSatelliteController != null
+ ? mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone) : false;
+
mAtomsStorage.addVoiceCallSession(proto);
// merge RAT usages to PersistPullers when the call session ends (i.e. no more active calls)
@@ -790,11 +802,8 @@
}
}
}
- if (bearer == VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS) {
- return TelephonyManager.NETWORK_TYPE_UNKNOWN;
- } else {
- return ServiceStateStats.getRat(state, NetworkRegistrationInfo.DOMAIN_CS);
- }
+
+ return ServiceStateStats.getRat(state, NetworkRegistrationInfo.DOMAIN_CS);
}
/** Resets the list of codecs used for the connection with only the codec currently in use. */
@@ -943,6 +952,36 @@
return false;
}
+ private @CallComposerStatus int getCallComposerStatusForPhone() {
+ TelephonyManager telephonyManager = mPhone.getContext()
+ .getSystemService(TelephonyManager.class);
+ if (telephonyManager == null) {
+ return TelephonyManager.CALL_COMPOSER_STATUS_OFF;
+ }
+ telephonyManager = telephonyManager.createForSubscriptionId(mPhone.getSubId());
+ return telephonyManager.getCallComposerStatus();
+ }
+
+ private boolean isBusinessCallSupported() {
+ CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
+ mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ if (carrierConfigManager == null) {
+ return false;
+ }
+ int subId = mPhone.getSubId();
+ PersistableBundle b = null;
+ try {
+ b = carrierConfigManager.getConfigForSubId(subId,
+ CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL);
+ } catch (RuntimeException e) {
+ loge("CarrierConfigLoader is not available.");
+ }
+ if (b == null || b.isEmpty()) {
+ return false;
+ }
+ return b.getBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL);
+ }
+
@VisibleForTesting
protected long getTimeMillis() {
return SystemClock.elapsedRealtime();
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramController.java b/src/java/com/android/internal/telephony/satellite/DatagramController.java
index 877eaf1..ff2ee9f 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramController.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramController.java
@@ -16,16 +16,26 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_IDLE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
+import android.content.res.Resources;
import android.os.Build;
import android.os.Looper;
import android.os.SystemProperties;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.satellite.ISatelliteDatagramCallback;
import android.telephony.satellite.SatelliteDatagram;
@@ -34,7 +44,10 @@
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
@@ -46,6 +59,7 @@
@NonNull private static DatagramController sInstance;
@NonNull private final Context mContext;
+ @NonNull private final FeatureFlags mFeatureFlags;
@NonNull private final PointingAppController mPointingAppController;
@NonNull private final DatagramDispatcher mDatagramDispatcher;
@NonNull private final DatagramReceiver mDatagramReceiver;
@@ -59,6 +73,10 @@
public static final int TIMEOUT_TYPE_DATAGRAM_WAIT_FOR_CONNECTED_STATE = 2;
/** This type is used by CTS to override the time to wait for response of the send request */
public static final int TIMEOUT_TYPE_WAIT_FOR_DATAGRAM_SENDING_RESPONSE = 3;
+ /** This type is used by CTS to override the time to datagram delay in demo mode */
+ public static final int TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE = 4;
+ /** This type is used by CTS to override wait for device alignment in demo datagram boolean */
+ public static final int BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM = 1;
private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
private static final boolean DEBUG = !"user".equals(Build.TYPE);
@@ -67,8 +85,10 @@
@GuardedBy("mLock")
private int mSendSubId;
@GuardedBy("mLock")
+ private @SatelliteManager.DatagramType int mDatagramType = DATAGRAM_TYPE_UNKNOWN;
+ @GuardedBy("mLock")
private @SatelliteManager.SatelliteDatagramTransferState int mSendDatagramTransferState =
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@GuardedBy("mLock")
private int mSendPendingCount = 0;
@GuardedBy("mLock")
@@ -78,20 +98,24 @@
private int mReceiveSubId;
@GuardedBy("mLock")
private @SatelliteManager.SatelliteDatagramTransferState int mReceiveDatagramTransferState =
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
@GuardedBy("mLock")
private int mReceivePendingCount = 0;
@GuardedBy("mLock")
private int mReceiveErrorCode = SatelliteManager.SATELLITE_RESULT_SUCCESS;
-
- private SatelliteDatagram mDemoModeDatagram;
+ @GuardedBy("mLock")
+ private final List<SatelliteDatagram> mDemoModeDatagramList;
private boolean mIsDemoMode = false;
private long mAlignTimeoutDuration = SATELLITE_ALIGN_TIMEOUT;
private long mDatagramWaitTimeForConnectedState;
private long mModemImageSwitchingDuration;
+ private boolean mWaitForDeviceAlignmentInDemoDatagram;
+ private long mDatagramWaitTimeForConnectedStateForLastMessage;
@GuardedBy("mLock")
@SatelliteManager.SatelliteModemState
private int mSatelltieModemState = SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN;
+ @Nullable
+ private PersistentLogger mPersistentLogger = null;
/**
* @return The singleton instance of DatagramController.
@@ -107,14 +131,17 @@
* Create the DatagramController singleton instance.
* @param context The Context to use to create the DatagramController.
* @param looper The looper for the handler.
+ * @param featureFlags The telephony feature flags.
* @param pointingAppController PointingAppController is used to update
* PointingApp about datagram transfer state changes.
* @return The singleton instance of DatagramController.
*/
public static DatagramController make(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
@NonNull PointingAppController pointingAppController) {
if (sInstance == null) {
- sInstance = new DatagramController(context, looper, pointingAppController);
+ sInstance = new DatagramController(
+ context, looper, featureFlags, pointingAppController);
}
return sInstance;
}
@@ -124,25 +151,40 @@
*
* @param context The Context for the DatagramController.
* @param looper The looper for the handler
+ * @param featureFlags The telephony feature flags.
* @param pointingAppController PointingAppController is used to update PointingApp
* about datagram transfer state changes.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected DatagramController(@NonNull Context context, @NonNull Looper looper,
+ public DatagramController(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
@NonNull PointingAppController pointingAppController) {
mContext = context;
+ mFeatureFlags = featureFlags;
mPointingAppController = pointingAppController;
// Create the DatagramDispatcher singleton,
// which is used to send satellite datagrams.
- mDatagramDispatcher = DatagramDispatcher.make(mContext, looper, this);
+ mDatagramDispatcher = DatagramDispatcher.make(
+ mContext, looper, mFeatureFlags, this);
// Create the DatagramReceiver singleton,
// which is used to receive satellite datagrams.
- mDatagramReceiver = DatagramReceiver.make(mContext, looper, this);
+ mDatagramReceiver = DatagramReceiver.make(
+ mContext, looper, mFeatureFlags, this);
mDatagramWaitTimeForConnectedState = getDatagramWaitForConnectedStateTimeoutMillis();
mModemImageSwitchingDuration = getSatelliteModemImageSwitchingDurationMillis();
+ mWaitForDeviceAlignmentInDemoDatagram =
+ getWaitForDeviceAlignmentInDemoDatagramFromResources();
+ mDatagramWaitTimeForConnectedStateForLastMessage =
+ getDatagramWaitForConnectedStateForLastMessageTimeoutMillis();
+ mDemoModeDatagramList = new ArrayList<>();
+
+ if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+ mPersistentLogger = new PersistentLogger(
+ DropBoxManagerLoggerBackend.getInstance(context));
+ }
}
/**
@@ -183,6 +225,7 @@
* @param callback The callback to get {@link SatelliteManager.SatelliteResult} of the request.
*/
public void pollPendingSatelliteDatagrams(int subId, @NonNull Consumer<Integer> callback) {
+ plogd("pollPendingSatelliteDatagrams");
mDatagramReceiver.pollPendingSatelliteDatagrams(subId, callback);
}
@@ -208,7 +251,6 @@
public void sendSatelliteDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
@NonNull SatelliteDatagram datagram, boolean needFullScreenPointingUI,
@NonNull Consumer<Integer> callback) {
- setDemoModeDatagram(datagramType, datagram);
mDatagramDispatcher.sendSatelliteDatagram(subId, datagramType, datagram,
needFullScreenPointingUI, callback);
}
@@ -221,23 +263,43 @@
* @param sendPendingCount number of datagrams that are currently being sent
* @param errorCode If datagram transfer failed, the reason for failure.
*/
- public void updateSendStatus(int subId,
+ public void updateSendStatus(int subId, @SatelliteManager.DatagramType int datagramType,
@SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
int sendPendingCount, int errorCode) {
synchronized (mLock) {
- logd("updateSendStatus"
+ plogd("updateSendStatus"
+ " subId: " + subId
+ + " datagramType: " + datagramType
+ " datagramTransferState: " + datagramTransferState
+ " sendPendingCount: " + sendPendingCount + " errorCode: " + errorCode);
+ if (shouldSuppressDatagramTransferStateUpdate(datagramType)) {
+ plogd("Ignore the request to update send status");
+ return;
+ }
mSendSubId = subId;
+ mDatagramType = datagramType;
mSendDatagramTransferState = datagramTransferState;
mSendPendingCount = sendPendingCount;
mSendErrorCode = errorCode;
-
notifyDatagramTransferStateChangedToSessionController();
- mPointingAppController.updateSendDatagramTransferState(mSendSubId,
+ mPointingAppController.updateSendDatagramTransferState(mSendSubId, mDatagramType,
mSendDatagramTransferState, mSendPendingCount, mSendErrorCode);
+ retryPollPendingDatagramsInDemoMode();
+ }
+ }
+
+ private boolean shouldSuppressDatagramTransferStateUpdate(
+ @SatelliteManager.DatagramType int datagramType) {
+ synchronized (mLock) {
+ if (!SatelliteController.getInstance().isSatelliteAttachRequired()) {
+ return false;
+ }
+ if (datagramType == DATAGRAM_TYPE_KEEP_ALIVE
+ && mSatelltieModemState == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
+ return true;
+ }
+ return false;
}
}
@@ -253,7 +315,7 @@
@SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
int receivePendingCount, int errorCode) {
synchronized (mLock) {
- logd("updateReceiveStatus"
+ plogd("updateReceiveStatus"
+ " subId: " + subId
+ " datagramTransferState: " + datagramTransferState
+ " receivePendingCount: " + receivePendingCount + " errorCode: " + errorCode);
@@ -266,6 +328,7 @@
notifyDatagramTransferStateChangedToSessionController();
mPointingAppController.updateReceiveDatagramTransferState(mReceiveSubId,
mReceiveDatagramTransferState, mReceivePendingCount, mReceiveErrorCode);
+ retryPollPendingDatagramsInDemoMode();
}
if (isPollingInIdleState()) {
@@ -295,9 +358,16 @@
mDatagramReceiver.onSatelliteModemStateChanged(state);
}
- void setDeviceAlignedWithSatellite(boolean isAligned) {
+ /**
+ * Set whether the device is aligned with the satellite.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
mDatagramDispatcher.setDeviceAlignedWithSatellite(isAligned);
mDatagramReceiver.setDeviceAlignedWithSatellite(isAligned);
+ if (isAligned) {
+ retryPollPendingDatagramsInDemoMode();
+ }
}
@VisibleForTesting
@@ -313,10 +383,17 @@
* before transferring datagrams via satellite.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public boolean needsWaitingForSatelliteConnected() {
+ public boolean needsWaitingForSatelliteConnected(
+ @SatelliteManager.DatagramType int datagramType) {
synchronized (mLock) {
- if (SatelliteController.getInstance().isSatelliteAttachRequired()
- && mSatelltieModemState != SATELLITE_MODEM_STATE_CONNECTED
+ if (!SatelliteController.getInstance().isSatelliteAttachRequired()) {
+ return false;
+ }
+ if (datagramType == DATAGRAM_TYPE_KEEP_ALIVE
+ && mSatelltieModemState == SATELLITE_MODEM_STATE_NOT_CONNECTED) {
+ return false;
+ }
+ if (mSatelltieModemState != SATELLITE_MODEM_STATE_CONNECTED
&& mSatelltieModemState != SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING) {
return true;
}
@@ -327,14 +404,14 @@
public boolean isSendingInIdleState() {
synchronized (mLock) {
return (mSendDatagramTransferState
- == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
}
}
public boolean isPollingInIdleState() {
synchronized (mLock) {
return (mReceiveDatagramTransferState
- == SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
}
}
@@ -349,26 +426,42 @@
mDatagramReceiver.setDemoMode(isDemoMode);
if (!isDemoMode) {
- mDemoModeDatagram = null;
+ synchronized (mLock) {
+ mDemoModeDatagramList.clear();
+ }
+ setDeviceAlignedWithSatellite(false);
}
+ plogd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
}
/** Get the last sent datagram for demo mode */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public SatelliteDatagram getDemoModeDatagram() {
- return mDemoModeDatagram;
+ public SatelliteDatagram popDemoModeDatagram() {
+ if (!mIsDemoMode) {
+ return null;
+ }
+
+ synchronized (mLock) {
+ plogd("popDemoModeDatagram");
+ return mDemoModeDatagramList.size() > 0 ? mDemoModeDatagramList.remove(0) : null;
+ }
}
/**
* Set last sent datagram for demo mode
- * @param datagramType datagram type, only DATAGRAM_TYPE_SOS_MESSAGE will be saved
+ * @param datagramType datagram type, DATAGRAM_TYPE_SOS_MESSAGE,
+ * DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP,
+ * DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED will be saved
* @param datagram datagram The last datagram saved when sendSatelliteDatagramForDemo is called
*/
- @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- protected void setDemoModeDatagram(@SatelliteManager.DatagramType int datagramType,
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void pushDemoModeDatagram(@SatelliteManager.DatagramType int datagramType,
SatelliteDatagram datagram) {
- if (mIsDemoMode && datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
- mDemoModeDatagram = datagram;
+ if (mIsDemoMode && SatelliteServiceUtils.isSosMessage(datagramType)) {
+ synchronized (mLock) {
+ mDemoModeDatagramList.add(datagram);
+ plogd("pushDemoModeDatagram size=" + mDemoModeDatagramList.size());
+ }
}
}
@@ -377,13 +470,17 @@
}
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- public long getDatagramWaitTimeForConnectedState() {
+ public long getDatagramWaitTimeForConnectedState(boolean isLastSosMessage) {
synchronized (mLock) {
+ long timeout = isLastSosMessage ? mDatagramWaitTimeForConnectedStateForLastMessage :
+ mDatagramWaitTimeForConnectedState;
+ logd("getDatagramWaitTimeForConnectedState: isLastSosMessage=" + isLastSosMessage
+ + ", timeout=" + timeout + ", modemState=" + mSatelltieModemState);
if (mSatelltieModemState == SATELLITE_MODEM_STATE_OFF
|| mSatelltieModemState == SATELLITE_MODEM_STATE_IDLE) {
- return (mDatagramWaitTimeForConnectedState + mModemImageSwitchingDuration);
+ return (timeout + mModemImageSwitchingDuration);
}
- return mDatagramWaitTimeForConnectedState;
+ return timeout;
}
}
@@ -396,11 +493,11 @@
boolean setDatagramControllerTimeoutDuration(
boolean reset, int timeoutType, long timeoutMillis) {
if (!isMockModemAllowed()) {
- loge("Updating timeout duration is not allowed");
+ ploge("Updating timeout duration is not allowed");
return false;
}
- logd("setDatagramControllerTimeoutDuration: timeoutMillis=" + timeoutMillis
+ plogd("setDatagramControllerTimeoutDuration: timeoutMillis=" + timeoutMillis
+ ", reset=" + reset + ", timeoutType=" + timeoutType);
if (timeoutType == TIMEOUT_TYPE_ALIGN) {
if (reset) {
@@ -419,8 +516,40 @@
}
} else if (timeoutType == TIMEOUT_TYPE_WAIT_FOR_DATAGRAM_SENDING_RESPONSE) {
mDatagramDispatcher.setWaitTimeForDatagramSendingResponse(reset, timeoutMillis);
+ } else if (timeoutType == TIMEOUT_TYPE_DATAGRAM_DELAY_IN_DEMO_MODE) {
+ mDatagramDispatcher.setTimeoutDatagramDelayInDemoMode(reset, timeoutMillis);
} else {
- loge("Invalid timeout type " + timeoutType);
+ ploge("Invalid timeout type " + timeoutType);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This API can be used by only CTS to override the boolean configs used by the
+ * DatagramController module.
+ *
+ * @param enable Whether to enable or disable boolean config.
+ * @return {@code true} if the boolean config is set successfully, {@code false} otherwise.
+ */
+ boolean setDatagramControllerBooleanConfig(
+ boolean reset, int booleanType, boolean enable) {
+ if (!isMockModemAllowed()) {
+ loge("Updating boolean config is not allowed");
+ return false;
+ }
+
+ logd("setDatagramControllerTimeoutDuration: booleanType=" + booleanType
+ + ", reset=" + reset + ", enable=" + enable);
+ if (booleanType == BOOLEAN_TYPE_WAIT_FOR_DEVICE_ALIGNMENT_IN_DEMO_DATAGRAM) {
+ if (reset) {
+ mWaitForDeviceAlignmentInDemoDatagram =
+ getWaitForDeviceAlignmentInDemoDatagramFromResources();
+ } else {
+ mWaitForDeviceAlignmentInDemoDatagram = enable;
+ }
+ } else {
+ loge("Invalid boolean type " + booleanType);
return false;
}
return true;
@@ -433,7 +562,7 @@
private void notifyDatagramTransferStateChangedToSessionController() {
SatelliteSessionController sessionController = SatelliteSessionController.getInstance();
if (sessionController == null) {
- loge("notifyDatagramTransferStateChangeToSessionController: SatelliteSessionController"
+ ploge("notifyDatagramTransferStateChangeToSessionController: SatelliteSessionController"
+ " is not initialized yet");
} else {
sessionController.onDatagramTransferStateChanged(
@@ -451,6 +580,11 @@
R.integer.config_satellite_modem_image_switching_duration_millis);
}
+ private long getDatagramWaitForConnectedStateForLastMessageTimeoutMillis() {
+ return mContext.getResources().getInteger(
+ R.integer.config_datagram_wait_for_connected_state_for_last_message_timeout_millis);
+ }
+
/**
* This API can be used by only CTS to override the cached value for the device overlay config
* value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
@@ -463,6 +597,55 @@
mDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(shouldSendToModemInDemoMode);
}
+ private void retryPollPendingDatagramsInDemoMode() {
+ synchronized (mLock) {
+ if (mIsDemoMode && isSendingInIdleState() && isPollingInIdleState()
+ && !mDemoModeDatagramList.isEmpty()) {
+ Consumer<Integer> internalCallback = new Consumer<Integer>() {
+ @Override
+ public void accept(Integer result) {
+ if (result != SATELLITE_RESULT_SUCCESS) {
+ plogd("retryPollPendingDatagramsInDemoMode result: " + result);
+ }
+ }
+ };
+ pollPendingSatelliteDatagrams(DEFAULT_SUBSCRIPTION_ID, internalCallback);
+ }
+ }
+ }
+
+ /**
+ * Get whether to wait for device alignment with satellite before sending datagrams.
+ *
+ * @param isAligned if the device is aligned with satellite or not
+ * @return {@code true} if device is not aligned to satellite,
+ * and it is required to wait for alignment else {@code false}
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public boolean waitForAligningToSatellite(boolean isAligned) {
+ if (isAligned) {
+ return false;
+ }
+
+ return getWaitForDeviceAlignmentInDemoDatagram();
+ }
+
+ private boolean getWaitForDeviceAlignmentInDemoDatagram() {
+ return mWaitForDeviceAlignmentInDemoDatagram;
+ }
+
+ private boolean getWaitForDeviceAlignmentInDemoDatagramFromResources() {
+ boolean waitForDeviceAlignmentInDemoDatagram = false;
+ try {
+ waitForDeviceAlignmentInDemoDatagram = mContext.getResources().getBoolean(
+ R.bool.config_wait_for_device_alignment_in_demo_datagram);
+ } catch (Resources.NotFoundException ex) {
+ loge("getWaitForDeviceAlignmentInDemoDatagram: ex=" + ex);
+ }
+
+ return waitForDeviceAlignmentInDemoDatagram;
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
@@ -470,4 +653,31 @@
private static void loge(@NonNull String log) {
Rlog.e(TAG, log);
}
+
+ private boolean isSatellitePersistentLoggingEnabled(
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (featureFlags.satellitePersistentLogging()) {
+ return true;
+ }
+ try {
+ return context.getResources().getBoolean(
+ R.bool.config_dropboxmanager_persistent_logging_enabled);
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ private void plogd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
+ private void ploge(@NonNull String log) {
+ Rlog.e(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.error(TAG, log);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
index 5cac1dd..2c9463f 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramDispatcher.java
@@ -16,8 +16,10 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.DatagramController.ROUNDING_UNIT;
@@ -30,6 +32,8 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.satellite.SatelliteDatagram;
@@ -39,12 +43,15 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.SatelliteStats;
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
+import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
@@ -61,11 +68,14 @@
private static final int EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT = 4;
private static final int EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT = 5;
private static final int EVENT_ABORT_SENDING_SATELLITE_DATAGRAMS_DONE = 6;
-
+ private static final int EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT = 7;
+ private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
@NonNull private static DatagramDispatcher sInstance;
@NonNull private final Context mContext;
@NonNull private final DatagramController mDatagramController;
@NonNull private final ControllerMetricsStats mControllerMetricsStats;
+ @NonNull private final SessionMetricsStats mSessionMetricsStats;
+ @NonNull private final FeatureFlags mFeatureFlags;
private boolean mIsDemoMode = false;
private boolean mIsAligned = false;
@@ -76,6 +86,7 @@
private AtomicBoolean mShouldSendDatagramToModemInDemoMode = null;
private final Object mLock = new Object();
+ private long mDemoTimeoutDuration = TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE;
@GuardedBy("mLock")
private boolean mSendingDatagramInProgress;
@@ -97,18 +108,34 @@
mPendingNonEmergencyDatagramsMap = new LinkedHashMap<>();
private long mWaitTimeForDatagramSendingResponse;
+ private long mWaitTimeForDatagramSendingForLastMessageResponse;
+ @SatelliteManager.DatagramType
+ private int mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
+ @Nullable private PersistentLogger mPersistentLogger = null;
/**
* Create the DatagramDispatcher singleton instance.
* @param context The Context to use to create the DatagramDispatcher.
* @param looper The looper for the handler.
+ * @param featureFlags The telephony feature flags.
* @param datagramController DatagramController which is used to update datagram transfer state.
* @return The singleton instance of DatagramDispatcher.
*/
public static DatagramDispatcher make(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
@NonNull DatagramController datagramController) {
if (sInstance == null) {
- sInstance = new DatagramDispatcher(context, looper, datagramController);
+ sInstance = new DatagramDispatcher(context, looper, featureFlags, datagramController);
+ }
+ return sInstance;
+ }
+
+ /**
+ * @return The singleton instance of DatagramDispatcher.
+ */
+ public static DatagramDispatcher getInstance() {
+ if (sInstance == null) {
+ loge("DatagramDispatcher was not yet initialized.");
}
return sInstance;
}
@@ -118,20 +145,30 @@
*
* @param context The Context for the DatagramDispatcher.
* @param looper The looper for the handler.
+ * @param featureFlags The telephony feature flags.
* @param datagramController DatagramController which is used to update datagram transfer state.
*/
@VisibleForTesting
protected DatagramDispatcher(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
@NonNull DatagramController datagramController) {
super(looper);
mContext = context;
+ mFeatureFlags = featureFlags;
mDatagramController = datagramController;
mControllerMetricsStats = ControllerMetricsStats.getInstance();
+ mSessionMetricsStats = SessionMetricsStats.getInstance();
+ if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+ mPersistentLogger = new PersistentLogger(
+ DropBoxManagerLoggerBackend.getInstance(context));
+ }
synchronized (mLock) {
mSendingDatagramInProgress = false;
}
mWaitTimeForDatagramSendingResponse = getWaitForDatagramSendingResponseTimeoutMillis();
+ mWaitTimeForDatagramSendingForLastMessageResponse =
+ getWaitForDatagramSendingResponseForLastMessageTimeoutMillis();
}
private static final class DatagramDispatcherHandlerRequest {
@@ -196,7 +233,9 @@
switch(msg.what) {
case CMD_SEND_SATELLITE_DATAGRAM: {
- logd("CMD_SEND_SATELLITE_DATAGRAM");
+ plogd("CMD_SEND_SATELLITE_DATAGRAM mIsDemoMode=" + mIsDemoMode
+ + ", shouldSendDatagramToModemInDemoMode="
+ + shouldSendDatagramToModemInDemoMode());
request = (DatagramDispatcherHandlerRequest) msg.obj;
SendSatelliteDatagramArgument argument =
(SendSatelliteDatagramArgument) request.argument;
@@ -205,11 +244,11 @@
synchronized (mLock) {
if (mIsDemoMode && !shouldSendDatagramToModemInDemoMode()) {
AsyncResult.forMessage(onCompleted, SATELLITE_RESULT_SUCCESS, null);
- onCompleted.sendToTarget();
+ sendMessageDelayed(onCompleted, getDemoTimeoutDuration());
} else {
SatelliteModemInterface.getInstance().sendSatelliteDatagram(
argument.datagram,
- argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ SatelliteServiceUtils.isSosMessage(argument.datagramType),
argument.needFullScreenPointingUI, onCompleted);
startWaitForDatagramSendingResponseTimer(argument);
}
@@ -226,14 +265,16 @@
synchronized (mLock) {
if (mIsDemoMode && (error == SatelliteManager.SATELLITE_RESULT_SUCCESS)) {
if (argument.skipCheckingSatelliteAligned) {
- logd("Satellite was already aligned. No need to check alignment again");
- } else if (!mIsAligned) {
- logd("Satellite is not aligned in demo mode, wait for the alignment.");
+ plogd("Satellite was already aligned. "
+ + "No need to check alignment again");
+ } else if (mDatagramController.waitForAligningToSatellite(mIsAligned)) {
+ plogd("Satellite is not aligned in demo mode, wait for the alignment.");
startSatelliteAlignedTimer(request);
break;
}
}
- logd("EVENT_SEND_SATELLITE_DATAGRAM_DONE error: " + error);
+ plogd("EVENT_SEND_SATELLITE_DATAGRAM_DONE error: " + error
+ + ", mIsDemoMode=" + mIsDemoMode);
/*
* The response should be ignored if either of the following hold
@@ -243,7 +284,7 @@
* 3) All pending send requests have been aborted due to some error.
*/
if (!shouldProcessEventSendSatelliteDatagramDone(argument)) {
- logw("The message " + argument.datagramId + " was already processed");
+ plogw("The message " + argument.datagramId + " was already processed");
break;
}
@@ -253,48 +294,37 @@
// Log metrics about the outgoing datagram
reportSendDatagramCompleted(argument, error);
// Remove current datagram from pending map.
- if (argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
+ if (SatelliteServiceUtils.isSosMessage(argument.datagramType)) {
mPendingEmergencyDatagramsMap.remove(argument.datagramId);
} else {
mPendingNonEmergencyDatagramsMap.remove(argument.datagramId);
}
- if (error == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ if (error == SATELLITE_RESULT_SUCCESS) {
// Update send status for current datagram
- mDatagramController.updateSendStatus(argument.subId,
+ mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
getPendingDatagramCount(), error);
- mControllerMetricsStats.reportOutgoingDatagramSuccessCount(
- argument.datagramType);
-
- if (getPendingDatagramCount() > 0) {
- // Send response for current datagram
- argument.callback.accept(error);
- // Send pending datagrams
- sendPendingDatagrams();
- } else {
- mDatagramController.updateSendStatus(argument.subId,
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- 0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
- // Send response for current datagram
- argument.callback.accept(error);
- }
+ startWaitForSimulatedPollDatagramsDelayTimer(request);
} else {
// Update send status
- mDatagramController.updateSendStatus(argument.subId,
+ mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
getPendingDatagramCount(), error);
- mDatagramController.updateSendStatus(argument.subId,
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
- 0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ }
+
+ if (getPendingDatagramCount() > 0) {
// Send response for current datagram
- // after updating datagram transfer state internally.
argument.callback.accept(error);
- // Abort sending all the pending datagrams
- mControllerMetricsStats.reportOutgoingDatagramFailCount(
- argument.datagramType);
- abortSendingPendingDatagrams(argument.subId,
- SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
+ // Send pending datagrams
+ sendPendingDatagrams();
+ } else {
+ mDatagramController.updateSendStatus(argument.subId,
+ argument.datagramType,
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0,
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ // Send response for current datagram
+ argument.callback.accept(error);
}
}
break;
@@ -311,11 +341,18 @@
}
case EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT:
- handleEventDatagramWaitForConnectedStateTimedOut();
+ handleEventDatagramWaitForConnectedStateTimedOut(
+ (SendSatelliteDatagramArgument) msg.obj);
+ break;
+
+ case EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT:
+ request = (DatagramDispatcherHandlerRequest) msg.obj;
+ handleEventWaitForSimulatedPollDatagramsDelayTimedOut(
+ (SendSatelliteDatagramArgument) request.argument);
break;
default:
- logw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
+ plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
break;
}
}
@@ -343,36 +380,36 @@
long datagramId = mNextDatagramId.getAndUpdate(
n -> ((n + 1) % DatagramController.MAX_DATAGRAM_ID));
-
SendSatelliteDatagramArgument datagramArgs =
new SendSatelliteDatagramArgument(subId, datagramId, datagramType, datagram,
needFullScreenPointingUI, callback);
+ mLastSendRequestDatagramType = datagramType;
synchronized (mLock) {
// Add datagram to pending datagram map
- if (datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
+ if (SatelliteServiceUtils.isSosMessage(datagramType)) {
mPendingEmergencyDatagramsMap.put(datagramId, datagramArgs);
} else {
mPendingNonEmergencyDatagramsMap.put(datagramId, datagramArgs);
}
- if (mDatagramController.needsWaitingForSatelliteConnected()) {
- logd("sendDatagram: wait for satellite connected");
- mDatagramController.updateSendStatus(subId,
+ if (mDatagramController.needsWaitingForSatelliteConnected(datagramType)) {
+ plogd("sendDatagram: wait for satellite connected");
+ mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT,
getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
- startDatagramWaitForConnectedStateTimer();
+ startDatagramWaitForConnectedStateTimer(datagramArgs);
} else if (!mSendingDatagramInProgress && mDatagramController.isPollingInIdleState()) {
// Modem can be busy receiving datagrams, so send datagram only when modem is
// not busy.
mSendingDatagramInProgress = true;
datagramArgs.setDatagramStartTime();
- mDatagramController.updateSendStatus(subId,
+ mDatagramController.updateSendStatus(subId, datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
sendRequestAsync(CMD_SEND_SATELLITE_DATAGRAM, datagramArgs, phone);
} else {
- logd("sendDatagram: mSendingDatagramInProgress="
+ plogd("sendDatagram: mSendingDatagramInProgress="
+ mSendingDatagramInProgress + ", isPollingInIdleState="
+ mDatagramController.isPollingInIdleState());
}
@@ -392,21 +429,24 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected void setDemoMode(boolean isDemoMode) {
mIsDemoMode = isDemoMode;
+ plogd("setDemoMode: mIsDemoMode=" + mIsDemoMode);
}
+ /**
+ * Set whether the device is aligned with the satellite.
+ */
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected void setDeviceAlignedWithSatellite(boolean isAligned) {
- if (mIsDemoMode) {
- synchronized (mLock) {
- mIsAligned = isAligned;
- if (isAligned) handleEventSatelliteAligned();
- }
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
+ synchronized (mLock) {
+ mIsAligned = isAligned;
+ plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
+ if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
}
}
private void startSatelliteAlignedTimer(@NonNull DatagramDispatcherHandlerRequest request) {
if (isSatelliteAlignedTimerStarted()) {
- logd("Satellite aligned timer was already started");
+ plogd("Satellite aligned timer was already started");
return;
}
mSendSatelliteDatagramRequest = request;
@@ -425,7 +465,7 @@
stopSatelliteAlignedTimer();
if (mSendSatelliteDatagramRequest == null) {
- loge("handleEventSatelliteAligned: mSendSatelliteDatagramRequest is null");
+ ploge("handleEventSatelliteAligned: mSendSatelliteDatagramRequest is null");
} else {
SendSatelliteDatagramArgument argument =
(SendSatelliteDatagramArgument) mSendSatelliteDatagramRequest.argument;
@@ -435,15 +475,18 @@
mSendSatelliteDatagramRequest = null;
AsyncResult.forMessage(message, null, null);
message.sendToTarget();
+ plogd("handleEventSatelliteAligned: EVENT_SEND_SATELLITE_DATAGRAM_DONE");
}
}
}
private void handleEventSatelliteAlignedTimeout(
@NonNull DatagramDispatcherHandlerRequest request) {
+ plogd("handleEventSatelliteAlignedTimeout");
+ mSendSatelliteDatagramRequest = null;
SatelliteManager.SatelliteException exception =
new SatelliteManager.SatelliteException(
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ SATELLITE_RESULT_NOT_REACHABLE);
Message message = obtainMessage(EVENT_SEND_SATELLITE_DATAGRAM_DONE, request);
AsyncResult.forMessage(message, null, exception);
message.sendToTarget();
@@ -463,15 +506,15 @@
*/
@GuardedBy("mLock")
private void sendPendingDatagrams() {
- logd("sendPendingDatagrams()");
+ plogd("sendPendingDatagrams()");
if (!mDatagramController.isPollingInIdleState()) {
// Datagram should be sent to satellite modem when modem is free.
- logd("sendPendingDatagrams: modem is receiving datagrams");
+ plogd("sendPendingDatagrams: modem is receiving datagrams");
return;
}
if (getPendingDatagramCount() <= 0) {
- logd("sendPendingDatagrams: no pending datagrams to send");
+ plogd("sendPendingDatagrams: no pending datagrams to send");
return;
}
@@ -484,12 +527,17 @@
}
if ((pendingDatagram != null) && pendingDatagram.iterator().hasNext()) {
- mSendingDatagramInProgress = true;
SendSatelliteDatagramArgument datagramArg =
pendingDatagram.iterator().next().getValue();
+ if (mDatagramController.needsWaitingForSatelliteConnected(datagramArg.datagramType)) {
+ plogd("sendPendingDatagrams: wait for satellite connected");
+ return;
+ }
+
+ mSendingDatagramInProgress = true;
// Sets the trigger time for getting pending datagrams
datagramArg.setDatagramStartTime();
- mDatagramController.updateSendStatus(datagramArg.subId,
+ mDatagramController.updateSendStatus(datagramArg.subId, datagramArg.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING,
getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_SUCCESS);
sendRequestAsync(CMD_SEND_SATELLITE_DATAGRAM, datagramArg, phone);
@@ -509,14 +557,13 @@
if (pendingDatagramsMap.size() == 0) {
return;
}
- loge("sendErrorCodeAndCleanupPendingDatagrams: cleaning up resources");
+ ploge("sendErrorCodeAndCleanupPendingDatagrams: cleaning up resources");
// Send error code to all the pending datagrams
for (Entry<Long, SendSatelliteDatagramArgument> entry :
pendingDatagramsMap.entrySet()) {
SendSatelliteDatagramArgument argument = entry.getValue();
reportSendDatagramCompleted(argument, errorCode);
- mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType);
argument.callback.accept(errorCode);
}
@@ -533,7 +580,7 @@
@GuardedBy("mLock")
private void abortSendingPendingDatagrams(int subId,
@SatelliteManager.SatelliteResult int errorCode) {
- logd("abortSendingPendingDatagrams()");
+ plogd("abortSendingPendingDatagrams()");
sendErrorCodeAndCleanupPendingDatagrams(mPendingEmergencyDatagramsMap, errorCode);
sendErrorCodeAndCleanupPendingDatagrams(mPendingNonEmergencyDatagramsMap, errorCode);
}
@@ -548,6 +595,22 @@
}
}
+ /** Return pending user messages count */
+ public int getPendingUserMessagesCount() {
+ synchronized (mLock) {
+ int pendingUserMessagesCount = 0;
+ for (Entry<Long, SendSatelliteDatagramArgument> entry :
+ mPendingNonEmergencyDatagramsMap.entrySet()) {
+ SendSatelliteDatagramArgument argument = entry.getValue();
+ if (argument.datagramType != SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ pendingUserMessagesCount += 1;
+ }
+ }
+ pendingUserMessagesCount += mPendingEmergencyDatagramsMap.size();
+ return pendingUserMessagesCount;
+ }
+ }
+
/**
* Posts the specified command to be executed on the main thread and returns immediately.
*
@@ -569,9 +632,22 @@
.setDatagramType(argument.datagramType)
.setResultCode(resultCode)
.setDatagramSizeBytes(argument.getDatagramRoundedSizeBytes())
- .setDatagramTransferTimeMillis(
- System.currentTimeMillis() - argument.datagramStartTime)
+ /* In case pending datagram has not been attempted to send to modem
+ interface. transfer time will be 0. */
+ .setDatagramTransferTimeMillis(argument.datagramStartTime > 0
+ ? (System.currentTimeMillis() - argument.datagramStartTime) : 0)
+ .setIsDemoMode(mIsDemoMode)
.build());
+ if (resultCode == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ mControllerMetricsStats.reportOutgoingDatagramSuccessCount(argument.datagramType,
+ mIsDemoMode);
+ mSessionMetricsStats.addCountOfSuccessfulOutgoingDatagram(argument.datagramType);
+ } else {
+ mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType,
+ mIsDemoMode);
+ mSessionMetricsStats.addCountOfFailedOutgoingDatagram(argument.datagramType,
+ resultCode);
+ }
}
/**
@@ -592,7 +668,7 @@
synchronized (mLock) {
if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF
|| state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) {
- logd("onSatelliteModemStateChanged: cleaning up resources");
+ plogd("onSatelliteModemStateChanged: cleaning up resources");
cleanUpResources();
} else if (state == SatelliteManager.SATELLITE_MODEM_STATE_IDLE) {
sendPendingDatagrams();
@@ -608,14 +684,16 @@
@GuardedBy("mLock")
private void cleanUpResources() {
+ plogd("cleanUpResources");
mSendingDatagramInProgress = false;
if (getPendingDatagramCount() > 0) {
- mDatagramController.updateSendStatus(
- SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mLastSendRequestDatagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
getPendingDatagramCount(), SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
}
mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mLastSendRequestDatagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
@@ -624,19 +702,23 @@
stopSatelliteAlignedTimer();
stopDatagramWaitForConnectedStateTimer();
stopWaitForDatagramSendingResponseTimer();
+ stopWaitForSimulatedPollDatagramsDelayTimer();
mIsDemoMode = false;
mSendSatelliteDatagramRequest = null;
mIsAligned = false;
+ mLastSendRequestDatagramType = DATAGRAM_TYPE_UNKNOWN;
}
- private void startDatagramWaitForConnectedStateTimer() {
+ private void startDatagramWaitForConnectedStateTimer(
+ @NonNull SendSatelliteDatagramArgument datagramArgs) {
if (isDatagramWaitForConnectedStateTimerStarted()) {
- logd("DatagramWaitForConnectedStateTimer is already started");
+ plogd("DatagramWaitForConnectedStateTimer is already started");
return;
}
sendMessageDelayed(obtainMessage(
- EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT),
- mDatagramController.getDatagramWaitTimeForConnectedState());
+ EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT, datagramArgs),
+ mDatagramController.getDatagramWaitTimeForConnectedState(
+ SatelliteServiceUtils.isLastSosMessage(datagramArgs.datagramType)));
}
private void stopDatagramWaitForConnectedStateTimer() {
@@ -662,31 +744,38 @@
private void startWaitForDatagramSendingResponseTimer(
@NonNull SendSatelliteDatagramArgument argument) {
if (hasMessages(EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT)) {
- logd("WaitForDatagramSendingResponseTimer was already started");
+ plogd("WaitForDatagramSendingResponseTimer was already started");
return;
}
+ long waitTime = SatelliteServiceUtils.isLastSosMessage(argument.datagramType)
+ ? mWaitTimeForDatagramSendingForLastMessageResponse
+ : mWaitTimeForDatagramSendingResponse;
+ logd("startWaitForDatagramSendingResponseTimer: datagramType=" + argument.datagramType
+ + ", waitTime=" + waitTime);
sendMessageDelayed(obtainMessage(
- EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT, argument),
- mWaitTimeForDatagramSendingResponse);
+ EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT, argument), waitTime);
}
private void stopWaitForDatagramSendingResponseTimer() {
removeMessages(EVENT_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMED_OUT);
}
- private void handleEventDatagramWaitForConnectedStateTimedOut() {
- logw("Timed out to wait for satellite connected before sending datagrams");
+ private void handleEventDatagramWaitForConnectedStateTimedOut(
+ @NonNull SendSatelliteDatagramArgument argument) {
+ plogw("Timed out to wait for satellite connected before sending datagrams");
synchronized (mLock) {
// Update send status
mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
getPendingDatagramCount(),
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ SATELLITE_RESULT_NOT_REACHABLE);
mDatagramController.updateSendStatus(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
abortSendingPendingDatagrams(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ SATELLITE_RESULT_NOT_REACHABLE);
}
}
@@ -702,7 +791,7 @@
return mShouldSendDatagramToModemInDemoMode.get();
} catch (Resources.NotFoundException ex) {
- loge("shouldSendDatagramToModemInDemoMode: id= "
+ ploge("shouldSendDatagramToModemInDemoMode: id= "
+ R.bool.config_send_satellite_datagram_to_modem_in_demo_mode + ", ex=" + ex);
return false;
}
@@ -713,10 +802,15 @@
R.integer.config_wait_for_datagram_sending_response_timeout_millis);
}
+ private long getWaitForDatagramSendingResponseForLastMessageTimeoutMillis() {
+ return mContext.getResources().getInteger(R.integer
+ .config_wait_for_datagram_sending_response_for_last_message_timeout_millis);
+ }
+
private boolean shouldProcessEventSendSatelliteDatagramDone(
@NonNull SendSatelliteDatagramArgument argument) {
synchronized (mLock) {
- if (argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
+ if (SatelliteServiceUtils.isSosMessage(argument.datagramType)) {
return mPendingEmergencyDatagramsMap.containsKey(argument.datagramId);
} else {
return mPendingNonEmergencyDatagramsMap.containsKey(argument.datagramId);
@@ -727,7 +821,7 @@
private void handleEventWaitForDatagramSendingResponseTimedOut(
@NonNull SendSatelliteDatagramArgument argument) {
synchronized (mLock) {
- logw("Timed out to wait for the response of the request to send the datagram "
+ plogw("Timed out to wait for the response of the request to send the datagram "
+ argument.datagramId);
// Ask vendor service to abort all datagram-sending requests
@@ -736,10 +830,10 @@
mSendingDatagramInProgress = false;
// Update send status
- mDatagramController.updateSendStatus(argument.subId,
+ mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED,
getPendingDatagramCount(), SATELLITE_RESULT_MODEM_TIMEOUT);
- mDatagramController.updateSendStatus(argument.subId,
+ mDatagramController.updateSendStatus(argument.subId, argument.datagramType,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
0, SatelliteManager.SATELLITE_RESULT_SUCCESS);
@@ -749,17 +843,15 @@
// Log metrics about the outgoing datagram
reportSendDatagramCompleted(argument, SATELLITE_RESULT_MODEM_TIMEOUT);
- mControllerMetricsStats.reportOutgoingDatagramFailCount(argument.datagramType);
// Remove current datagram from pending map.
- if (argument.datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
+ if (SatelliteServiceUtils.isSosMessage(argument.datagramType)) {
mPendingEmergencyDatagramsMap.remove(argument.datagramId);
} else {
mPendingNonEmergencyDatagramsMap.remove(argument.datagramId);
}
// Abort sending all the pending datagrams
- abortSendingPendingDatagrams(argument.subId,
- SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
+ abortSendingPendingDatagrams(argument.subId, SATELLITE_RESULT_MODEM_TIMEOUT);
}
}
@@ -774,7 +866,7 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
protected void setShouldSendDatagramToModemInDemoMode(
@Nullable Boolean shouldSendToModemInDemoMode) {
- logd("setShouldSendDatagramToModemInDemoMode(" + (shouldSendToModemInDemoMode == null
+ plogd("setShouldSendDatagramToModemInDemoMode(" + (shouldSendToModemInDemoMode == null
? "null" : shouldSendToModemInDemoMode) + ")");
if (shouldSendToModemInDemoMode == null) {
@@ -789,6 +881,59 @@
}
}
+ private void startWaitForSimulatedPollDatagramsDelayTimer(
+ @NonNull DatagramDispatcherHandlerRequest request) {
+ if (mIsDemoMode) {
+ plogd("startWaitForSimulatedPollDatagramsDelayTimer");
+ sendMessageDelayed(
+ obtainMessage(EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT, request),
+ getDemoTimeoutDuration());
+ } else {
+ plogd("Should not start WaitForSimulatedPollDatagramsDelayTimer in non-demo mode");
+ }
+ }
+
+ private void stopWaitForSimulatedPollDatagramsDelayTimer() {
+ removeMessages(EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT);
+ }
+
+ private void handleEventWaitForSimulatedPollDatagramsDelayTimedOut(
+ @NonNull SendSatelliteDatagramArgument argument) {
+ if (mIsDemoMode) {
+ plogd("handleEventWaitForSimulatedPollDatagramsDelayTimedOut");
+ mDatagramController.pushDemoModeDatagram(argument.datagramType, argument.datagram);
+ Consumer<Integer> internalCallback = new Consumer<Integer>() {
+ @Override
+ public void accept(Integer result) {
+ plogd("pollPendingSatelliteDatagrams result: " + result);
+ }
+ };
+ mDatagramController.pollPendingSatelliteDatagrams(argument.subId, internalCallback);
+ } else {
+ plogd("Unexpected EVENT_WAIT_FOR_SIMULATED_POLL_DATAGRAMS_DELAY_TIMED_OUT in "
+ + "non-demo mode");
+ }
+ }
+
+ long getDemoTimeoutDuration() {
+ return mDemoTimeoutDuration;
+ }
+
+ /**
+ * This API is used by CTS tests to override the mDemoTimeoutDuration.
+ */
+ void setTimeoutDatagramDelayInDemoMode(boolean reset, long timeoutMillis) {
+ if (!mIsDemoMode) {
+ return;
+ }
+ if (reset) {
+ mDemoTimeoutDuration = TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE;
+ } else {
+ mDemoTimeoutDuration = timeoutMillis;
+ }
+ plogd("setTimeoutDatagramDelayInDemoMode " + mDemoTimeoutDuration + " reset=" + reset);
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
@@ -798,4 +943,38 @@
}
private static void logw(@NonNull String log) { Rlog.w(TAG, log); }
+
+ private boolean isSatellitePersistentLoggingEnabled(
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (featureFlags.satellitePersistentLogging()) {
+ return true;
+ }
+ try {
+ return context.getResources().getBoolean(
+ R.bool.config_dropboxmanager_persistent_logging_enabled);
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ private void plogd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
+ private void plogw(@NonNull String log) {
+ Rlog.w(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.warn(TAG, log);
+ }
+ }
+
+ private void ploge(@NonNull String log) {
+ Rlog.e(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.error(TAG, log);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
index c267fd7..ea75f03 100644
--- a/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
+++ b/src/java/com/android/internal/telephony/satellite/DatagramReceiver.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.satellite;
import static android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.DatagramController.ROUNDING_UNIT;
@@ -36,6 +37,8 @@
import android.os.Message;
import android.os.RemoteException;
import android.provider.Telephony;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.telephony.satellite.ISatelliteDatagramCallback;
@@ -49,8 +52,10 @@
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.IVoidConsumer;
import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.SatelliteStats;
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
+import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import com.android.internal.util.FunctionalUtils;
import java.util.concurrent.ConcurrentHashMap;
@@ -79,7 +84,9 @@
@NonNull private SharedPreferences mSharedPreferences = null;
@NonNull private final DatagramController mDatagramController;
@NonNull private final ControllerMetricsStats mControllerMetricsStats;
+ @NonNull private final SessionMetricsStats mSessionMetricsStats;
@NonNull private final Looper mLooper;
+ @NonNull private final FeatureFlags mFeatureFlags;
private long mDatagramTransferStartTime = 0;
private boolean mIsDemoMode = false;
@@ -90,6 +97,8 @@
@Nullable
private DatagramReceiverHandlerRequest mPendingPollSatelliteDatagramsRequest = null;
private final Object mLock = new Object();
+ @Nullable
+ private PersistentLogger mPersistentLogger = null;
/**
* Map key: subId, value: SatelliteDatagramListenerHandler to notify registrants.
@@ -109,13 +118,15 @@
* Create the DatagramReceiver singleton instance.
* @param context The Context to use to create the DatagramReceiver.
* @param looper The looper for the handler.
+ * @param featureFlags The telephony feature flags.
* @param datagramController DatagramController which is used to update datagram transfer state.
* @return The singleton instance of DatagramReceiver.
*/
public static DatagramReceiver make(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
@NonNull DatagramController datagramController) {
if (sInstance == null) {
- sInstance = new DatagramReceiver(context, looper, datagramController);
+ sInstance = new DatagramReceiver(context, looper, featureFlags, datagramController);
}
return sInstance;
}
@@ -126,24 +137,31 @@
*
* @param context The Context for the DatagramReceiver.
* @param looper The looper for the handler.
+ * @param featureFlags The telephony feature flags.
* @param datagramController DatagramController which is used to update datagram transfer state.
*/
@VisibleForTesting
protected DatagramReceiver(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
@NonNull DatagramController datagramController) {
super(looper);
mContext = context;
mLooper = looper;
+ mFeatureFlags = featureFlags;
mContentResolver = context.getContentResolver();
mDatagramController = datagramController;
mControllerMetricsStats = ControllerMetricsStats.getInstance();
-
+ mSessionMetricsStats = SessionMetricsStats.getInstance();
+ if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+ mPersistentLogger = new PersistentLogger(
+ DropBoxManagerLoggerBackend.getInstance(context));
+ }
try {
mSharedPreferences =
mContext.getSharedPreferences(SatelliteController.SATELLITE_SHARED_PREF,
Context.MODE_PRIVATE);
} catch (Exception e) {
- loge("Cannot get default shared preferences: " + e);
+ ploge("Cannot get default shared preferences: " + e);
}
}
@@ -354,9 +372,6 @@
obtainMessage(EVENT_RETRY_DELIVERING_RECEIVED_DATAGRAM,
argument), getTimeoutToReceiveAck());
});
-
- sInstance.mControllerMetricsStats.reportIncomingDatagramCount(
- SatelliteManager.SATELLITE_RESULT_SUCCESS);
}
if (pendingCount <= 0) {
@@ -377,8 +392,8 @@
}
// Send the captured data about incoming datagram to metric
- sInstance.reportMetrics(
- satelliteDatagram, SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ sInstance.reportMetrics(satelliteDatagram,
+ SatelliteManager.SATELLITE_RESULT_SUCCESS);
break;
}
@@ -439,7 +454,7 @@
"pollPendingSatelliteDatagrams");
if (mIsDemoMode && error == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
- SatelliteDatagram datagram = mDatagramController.getDemoModeDatagram();
+ SatelliteDatagram datagram = mDatagramController.popDemoModeDatagram();
final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(
request.subId, mContext);
SatelliteDatagramListenerHandler listenerHandler =
@@ -456,7 +471,7 @@
}
}
- logd("EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE error: " + error);
+ plogd("EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE error: " + error);
if (error != SatelliteManager.SATELLITE_RESULT_SUCCESS) {
mDatagramController.updateReceiveStatus(request.subId,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
@@ -468,7 +483,6 @@
SatelliteManager.SATELLITE_RESULT_SUCCESS);
reportMetrics(null, error);
- mControllerMetricsStats.reportIncomingDatagramCount(error);
}
// Send response for current request
((Consumer<Integer>) request.argument).accept(error);
@@ -485,7 +499,7 @@
break;
default:
- logw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
+ plogw("DatagramDispatcherHandler: unexpected message code: " + msg.what);
break;
}
}
@@ -558,7 +572,7 @@
public void pollPendingSatelliteDatagrams(int subId, @NonNull Consumer<Integer> callback) {
if (!mDatagramController.isPollingInIdleState()) {
// Poll request should be sent to satellite modem only when it is free.
- logd("pollPendingSatelliteDatagrams: satellite modem is busy receiving datagrams.");
+ plogd("pollPendingSatelliteDatagrams: satellite modem is busy receiving datagrams.");
callback.accept(SatelliteManager.SATELLITE_RESULT_MODEM_BUSY);
return;
}
@@ -570,7 +584,7 @@
if (isDatagramWaitForConnectedStateTimerStarted()) {
stopDatagramWaitForConnectedStateTimer();
if (mPendingPollSatelliteDatagramsRequest == null) {
- loge("handleSatelliteConnectedEvent: mPendingPollSatelliteDatagramsRequest is"
+ ploge("handleSatelliteConnectedEvent: mPendingPollSatelliteDatagramsRequest is"
+ " null");
return;
}
@@ -588,14 +602,15 @@
@NonNull Consumer<Integer> callback) {
if (!mDatagramController.isSendingInIdleState()) {
// Poll request should be sent to satellite modem only when it is free.
- logd("pollPendingSatelliteDatagramsInternal: satellite modem is busy sending "
+ plogd("pollPendingSatelliteDatagramsInternal: satellite modem is busy sending "
+ "datagrams.");
callback.accept(SatelliteManager.SATELLITE_RESULT_MODEM_BUSY);
return;
}
- if (mDatagramController.needsWaitingForSatelliteConnected()) {
- logd("pollPendingSatelliteDatagramsInternal: wait for satellite connected");
+ if (mDatagramController.needsWaitingForSatelliteConnected(
+ SatelliteManager.DATAGRAM_TYPE_UNKNOWN)) {
+ plogd("pollPendingSatelliteDatagramsInternal: wait for satellite connected");
synchronized (mLock) {
mPendingPollSatelliteDatagramsRequest = new DatagramReceiverHandlerRequest(
callback, SatelliteServiceUtils.getPhone(), subId);
@@ -619,7 +634,7 @@
DatagramReceiverHandlerRequest request = new DatagramReceiverHandlerRequest(
callback, phone, subId);
synchronized (mLock) {
- if (mIsAligned) {
+ if (!mDatagramController.waitForAligningToSatellite(mIsAligned)) {
Message msg = obtainMessage(EVENT_POLL_PENDING_SATELLITE_DATAGRAMS_DONE,
request);
AsyncResult.forMessage(msg, null, null);
@@ -643,7 +658,7 @@
synchronized (mLock) {
if (state == SatelliteManager.SATELLITE_MODEM_STATE_OFF
|| state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE) {
- logd("onSatelliteModemStateChanged: cleaning up resources");
+ plogd("onSatelliteModemStateChanged: cleaning up resources");
cleanUpResources();
} else if (state == SATELLITE_MODEM_STATE_CONNECTED) {
handleSatelliteConnectedEvent();
@@ -656,7 +671,7 @@
if (isSatelliteAlignedTimerStarted()) {
stopSatelliteAlignedTimer();
if (mDemoPollPendingSatelliteDatagramsRequest == null) {
- loge("Satellite aligned timer was started "
+ ploge("Satellite aligned timer was started "
+ "but mDemoPollPendingSatelliteDatagramsRequest is null");
} else {
Consumer<Integer> callback =
@@ -712,7 +727,7 @@
private void reportMetrics(@Nullable SatelliteDatagram satelliteDatagram,
@NonNull @SatelliteManager.SatelliteResult int resultCode) {
int datagramSizeRoundedBytes = -1;
- int datagramTransferTime = 0;
+ long datagramTransferTime = 0;
if (satelliteDatagram != null) {
if (satelliteDatagram.getSatelliteDatagram() != null) {
@@ -721,7 +736,7 @@
datagramSizeRoundedBytes =
(int) (Math.round((double) sizeBytes / ROUNDING_UNIT) * ROUNDING_UNIT);
}
- datagramTransferTime = (int) (System.currentTimeMillis() - mDatagramTransferStartTime);
+ datagramTransferTime = (System.currentTimeMillis() - mDatagramTransferStartTime);
mDatagramTransferStartTime = 0;
}
@@ -730,7 +745,15 @@
.setResultCode(resultCode)
.setDatagramSizeBytes(datagramSizeRoundedBytes)
.setDatagramTransferTimeMillis(datagramTransferTime)
+ .setIsDemoMode(mIsDemoMode)
.build());
+
+ mControllerMetricsStats.reportIncomingDatagramCount(resultCode, mIsDemoMode);
+ if (resultCode == SATELLITE_RESULT_SUCCESS) {
+ mSessionMetricsStats.addCountOfSuccessfulIncomingDatagram();
+ } else {
+ mSessionMetricsStats.addCountOfFailedIncomingDatagram();
+ }
}
/** Set demo mode
@@ -743,18 +766,17 @@
}
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
- protected void setDeviceAlignedWithSatellite(boolean isAligned) {
- if (mIsDemoMode) {
- synchronized (mLock) {
- mIsAligned = isAligned;
- if (isAligned) handleEventSatelliteAligned();
- }
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
+ synchronized (mLock) {
+ mIsAligned = isAligned;
+ plogd("setDeviceAlignedWithSatellite: " + mIsAligned);
+ if (isAligned && mIsDemoMode) handleEventSatelliteAligned();
}
}
private void startSatelliteAlignedTimer(DatagramReceiverHandlerRequest request) {
if (isSatelliteAlignedTimerStarted()) {
- logd("Satellite aligned timer was already started");
+ plogd("Satellite aligned timer was already started");
return;
}
mDemoPollPendingSatelliteDatagramsRequest = request;
@@ -773,7 +795,7 @@
stopSatelliteAlignedTimer();
if (mDemoPollPendingSatelliteDatagramsRequest == null) {
- loge("handleSatelliteAlignedTimer: mDemoPollPendingSatelliteDatagramsRequest "
+ ploge("handleSatelliteAlignedTimer: mDemoPollPendingSatelliteDatagramsRequest "
+ "is null");
} else {
Message message = obtainMessage(
@@ -805,12 +827,12 @@
private void startDatagramWaitForConnectedStateTimer() {
if (isDatagramWaitForConnectedStateTimerStarted()) {
- logd("DatagramWaitForConnectedStateTimer is already started");
+ plogd("DatagramWaitForConnectedStateTimer is already started");
return;
}
sendMessageDelayed(obtainMessage(
EVENT_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMED_OUT),
- mDatagramController.getDatagramWaitTimeForConnectedState());
+ mDatagramController.getDatagramWaitTimeForConnectedState(false));
}
private void stopDatagramWaitForConnectedStateTimer() {
@@ -825,12 +847,12 @@
private void handleEventDatagramWaitForConnectedStateTimedOut() {
synchronized (mLock) {
if (mPendingPollSatelliteDatagramsRequest == null) {
- logw("handleEventDatagramWaitForConnectedStateTimedOut: "
+ plogw("handleEventDatagramWaitForConnectedStateTimedOut: "
+ "mPendingPollSatelliteDatagramsRequest is null");
return;
}
- logw("Timed out to wait for satellite connected before polling datagrams");
+ plogw("Timed out to wait for satellite connected before polling datagrams");
mDatagramController.updateReceiveStatus(mPendingPollSatelliteDatagramsRequest.subId,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED,
mDatagramController.getReceivePendingCount(),
@@ -842,8 +864,6 @@
SatelliteManager.SATELLITE_RESULT_SUCCESS);
reportMetrics(null, SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
- mControllerMetricsStats.reportIncomingDatagramCount(
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
Consumer<Integer> callback =
(Consumer<Integer>) mPendingPollSatelliteDatagramsRequest.argument;
@@ -871,4 +891,38 @@
private static void logw(@NonNull String log) {
Rlog.w(TAG, log);
}
+
+ private boolean isSatellitePersistentLoggingEnabled(
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (featureFlags.satellitePersistentLogging()) {
+ return true;
+ }
+ try {
+ return context.getResources().getBoolean(
+ R.bool.config_dropboxmanager_persistent_logging_enabled);
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ private void plogd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
+ private void plogw(@NonNull String log) {
+ Rlog.w(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.warn(TAG, log);
+ }
+ }
+
+ private void ploge(@NonNull String log) {
+ Rlog.e(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.error(TAG, log);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/DemoSimulator.java b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
new file mode 100644
index 0000000..3c31ae8
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/DemoSimulator.java
@@ -0,0 +1,329 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.IIntegerConsumer;
+import android.telephony.satellite.stub.ISatelliteListener;
+import android.telephony.satellite.stub.NtnSignalStrength;
+import android.telephony.satellite.stub.SatelliteModemState;
+import android.telephony.satellite.stub.SatelliteResult;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.State;
+import com.android.internal.util.StateMachine;
+
+public class DemoSimulator extends StateMachine {
+ private static final String TAG = "DemoSimulator";
+ private static final boolean DBG = true;
+
+ private static final int EVENT_SATELLITE_MODE_ON = 1;
+ private static final int EVENT_SATELLITE_MODE_OFF = 2;
+ private static final int EVENT_DEVICE_ALIGNED_WITH_SATELLITE = 3;
+ protected static final int EVENT_DEVICE_ALIGNED = 4;
+ protected static final int EVENT_DEVICE_NOT_ALIGNED = 5;
+
+ @NonNull private static DemoSimulator sInstance;
+
+ @NonNull private final Context mContext;
+ @NonNull private final SatelliteController mSatelliteController;
+ @NonNull private final PowerOffState mPowerOffState = new PowerOffState();
+ @NonNull private final NotConnectedState mNotConnectedState = new NotConnectedState();
+ @NonNull private final ConnectedState mConnectedState = new ConnectedState();
+ @NonNull private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private boolean mIsAligned = false;
+ private ISatelliteListener mISatelliteListener;
+
+ /**
+ * @return The singleton instance of DemoSimulator.
+ */
+ public static DemoSimulator getInstance() {
+ if (sInstance == null) {
+ Log.e(TAG, "DemoSimulator was not yet initialized.");
+ }
+ return sInstance;
+ }
+
+ /**
+ * Create the DemoSimulator singleton instance.
+ *
+ * @param context The Context for the DemoSimulator.
+ * @return The singleton instance of DemoSimulator.
+ */
+ public static DemoSimulator make(@NonNull Context context,
+ @NonNull SatelliteController satelliteController) {
+ if (sInstance == null) {
+ sInstance = new DemoSimulator(context, Looper.getMainLooper(), satelliteController);
+ }
+ return sInstance;
+ }
+
+ /**
+ * Create a DemoSimulator.
+ *
+ * @param context The Context for the DemoSimulator.
+ * @param looper The looper associated with the handler of this class.
+ */
+ protected DemoSimulator(@NonNull Context context, @NonNull Looper looper,
+ @NonNull SatelliteController satelliteController) {
+ super(TAG, looper);
+
+ mContext = context;
+ mSatelliteController = satelliteController;
+ addState(mPowerOffState);
+ addState(mNotConnectedState);
+ addState(mConnectedState);
+ setInitialState(mPowerOffState);
+ start();
+ }
+
+ private class PowerOffState extends State {
+ @Override
+ public void enter() {
+ logd("Entering PowerOffState");
+ }
+
+ @Override
+ public void exit() {
+ logd("Exiting PowerOffState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("PowerOffState: processing " + getWhatToString(msg.what));
+ switch (msg.what) {
+ case EVENT_SATELLITE_MODE_ON:
+ transitionTo(mNotConnectedState);
+ break;
+ }
+ // Ignore all unexpected events.
+ return HANDLED;
+ }
+ }
+
+ private class NotConnectedState extends State {
+ @Override
+ public void enter() {
+ logd("Entering NotConnectedState");
+
+ try {
+ NtnSignalStrength ntnSignalStrength = new NtnSignalStrength();
+ ntnSignalStrength.signalStrengthLevel = 0;
+ mISatelliteListener.onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength);
+
+ synchronized (mLock) {
+ if (mIsAligned) {
+ handleEventDeviceAlignedWithSatellite(true);
+ }
+ }
+ } catch (RemoteException e) {
+ loge("NotConnectedState: RemoteException " + e);
+ }
+ }
+
+ @Override
+ public void exit() {
+ logd("Exiting NotConnectedState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("NotConnectedState: processing " + getWhatToString(msg.what));
+ switch (msg.what) {
+ case EVENT_SATELLITE_MODE_OFF:
+ transitionTo(mPowerOffState);
+ break;
+ case EVENT_DEVICE_ALIGNED_WITH_SATELLITE:
+ handleEventDeviceAlignedWithSatellite((boolean) msg.obj);
+ break;
+ case EVENT_DEVICE_ALIGNED:
+ transitionTo(mConnectedState);
+ break;
+ }
+ // Ignore all unexpected events.
+ return HANDLED;
+ }
+
+ private void handleEventDeviceAlignedWithSatellite(boolean isAligned) {
+ if (isAligned && !hasMessages(EVENT_DEVICE_ALIGNED)) {
+ long durationMillis = mSatelliteController.getDemoPointingAlignedDurationMillis();
+ logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=true."
+ + " Send delayed EVENT_DEVICE_ALIGNED message in"
+ + " durationMillis=" + durationMillis);
+ sendMessageDelayed(EVENT_DEVICE_ALIGNED, durationMillis);
+ } else if (!isAligned && hasMessages(EVENT_DEVICE_ALIGNED)) {
+ logd("NotConnectedState: handleEventAlignedWithSatellite isAligned=false."
+ + " Remove EVENT_DEVICE_ALIGNED message.");
+ removeMessages(EVENT_DEVICE_ALIGNED);
+ }
+ }
+ }
+
+ private class ConnectedState extends State {
+ @Override
+ public void enter() {
+ logd("Entering ConnectedState");
+
+ try {
+ NtnSignalStrength ntnSignalStrength = new NtnSignalStrength();
+ ntnSignalStrength.signalStrengthLevel = 2;
+ mISatelliteListener.onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED);
+ mISatelliteListener.onNtnSignalStrengthChanged(ntnSignalStrength);
+
+ synchronized (mLock) {
+ if (!mIsAligned) {
+ handleEventDeviceAlignedWithSatellite(false);
+ }
+ }
+ } catch (RemoteException e) {
+ loge("ConnectedState: RemoteException " + e);
+ }
+ }
+
+ @Override
+ public void exit() {
+ logd("Exiting ConnectedState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) log("ConnectedState: processing " + getWhatToString(msg.what));
+ switch (msg.what) {
+ case EVENT_SATELLITE_MODE_OFF:
+ transitionTo(mPowerOffState);
+ break;
+ case EVENT_DEVICE_ALIGNED_WITH_SATELLITE:
+ handleEventDeviceAlignedWithSatellite((boolean) msg.obj);
+ break;
+ case EVENT_DEVICE_NOT_ALIGNED:
+ transitionTo(mNotConnectedState);
+ break;
+ }
+ // Ignore all unexpected events.
+ return HANDLED;
+ }
+
+ private void handleEventDeviceAlignedWithSatellite(boolean isAligned) {
+ if (!isAligned && !hasMessages(EVENT_DEVICE_NOT_ALIGNED)) {
+ long durationMillis =
+ mSatelliteController.getDemoPointingNotAlignedDurationMillis();
+ logd("ConnectedState: handleEventAlignedWithSatellite isAligned=false."
+ + " Send delayed EVENT_DEVICE_NOT_ALIGNED message"
+ + " in durationMillis=" + durationMillis);
+ sendMessageDelayed(EVENT_DEVICE_NOT_ALIGNED, durationMillis);
+ } else if (isAligned && hasMessages(EVENT_DEVICE_NOT_ALIGNED)) {
+ logd("ConnectedState: handleEventAlignedWithSatellite isAligned=true."
+ + " Remove EVENT_DEVICE_NOT_ALIGNED message.");
+ removeMessages(EVENT_DEVICE_NOT_ALIGNED);
+ }
+ }
+ }
+
+ /**
+ * @return the string for msg.what
+ */
+ @Override
+ protected String getWhatToString(int what) {
+ String whatString;
+ switch (what) {
+ case EVENT_SATELLITE_MODE_ON:
+ whatString = "EVENT_SATELLITE_MODE_ON";
+ break;
+ case EVENT_SATELLITE_MODE_OFF:
+ whatString = "EVENT_SATELLITE_MODE_OFF";
+ break;
+ case EVENT_DEVICE_ALIGNED_WITH_SATELLITE:
+ whatString = "EVENT_DEVICE_ALIGNED_WITH_SATELLITE";
+ break;
+ case EVENT_DEVICE_ALIGNED:
+ whatString = "EVENT_DEVICE_ALIGNED";
+ break;
+ case EVENT_DEVICE_NOT_ALIGNED:
+ whatString = "EVENT_DEVICE_NOT_ALIGNED";
+ break;
+ default:
+ whatString = "UNKNOWN EVENT " + what;
+ }
+ return whatString;
+ }
+
+ /**
+ * Register the callback interface with satellite service.
+ *
+ * @param listener The callback interface to handle satellite service indications.
+ */
+ public void setSatelliteListener(@NonNull ISatelliteListener listener) {
+ mISatelliteListener = listener;
+ }
+
+ /**
+ * Allow cellular modem scanning while satellite mode is on.
+ *
+ * @param enabled {@code true} to enable cellular modem while satellite mode is on
+ * and {@code false} to disable
+ * @param errorCallback The callback to receive the error code result of the operation.
+ */
+ public void enableCellularModemWhileSatelliteModeIsOn(boolean enabled,
+ @NonNull IIntegerConsumer errorCallback) {
+ try {
+ errorCallback.accept(SatelliteResult.SATELLITE_RESULT_SUCCESS);
+ } catch (RemoteException e) {
+ loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
+ }
+ }
+
+ /**
+ * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator}
+ * that satellite mode is ON.
+ */
+ public void onSatelliteModeOn() {
+ if (mSatelliteController.isDemoModeEnabled()) {
+ sendMessage(EVENT_SATELLITE_MODE_ON);
+ }
+ }
+
+ /**
+ * This function is used by {@link SatelliteSessionController} to notify {@link DemoSimulator}
+ * that satellite mode is OFF.
+ */
+ public void onSatelliteModeOff() {
+ sendMessage(EVENT_SATELLITE_MODE_OFF);
+ }
+
+ /**
+ * Set whether the device is aligned with the satellite.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
+ synchronized (mLock) {
+ if (mSatelliteController.isDemoModeEnabled()) {
+ mIsAligned = isAligned;
+ sendMessage(EVENT_DEVICE_ALIGNED_WITH_SATELLITE, isAligned);
+ }
+ }
+ }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
index add01c0..dfc7919 100644
--- a/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
+++ b/src/java/com/android/internal/telephony/satellite/NtnCapabilityResolver.java
@@ -39,11 +39,16 @@
*/
public static void resolveNtnCapability(
@NonNull NetworkRegistrationInfo networkRegistrationInfo, int subId) {
+ String registeredPlmn = networkRegistrationInfo.getRegisteredPlmn();
+ if (TextUtils.isEmpty(registeredPlmn)) {
+ return;
+ }
+
SatelliteController satelliteController = SatelliteController.getInstance();
List<String> satellitePlmnList = satelliteController.getSatellitePlmnsForCarrier(subId);
- String registeredPlmn = networkRegistrationInfo.getRegisteredPlmn();
for (String satellitePlmn : satellitePlmnList) {
- if (TextUtils.equals(satellitePlmn, registeredPlmn)) {
+ if (TextUtils.equals(satellitePlmn, registeredPlmn)
+ && networkRegistrationInfo.isInService()) {
logd("Registered to satellite PLMN " + satellitePlmn);
networkRegistrationInfo.setIsNonTerrestrialNetwork(true);
networkRegistrationInfo.setAvailableServices(
diff --git a/src/java/com/android/internal/telephony/satellite/PointingAppController.java b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
index 878ee96..06281c7 100644
--- a/src/java/com/android/internal/telephony/satellite/PointingAppController.java
+++ b/src/java/com/android/internal/telephony/satellite/PointingAppController.java
@@ -34,6 +34,8 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.PointingInfo;
@@ -42,6 +44,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
import java.util.ArrayList;
import java.util.Arrays;
@@ -60,8 +63,11 @@
@NonNull
private static PointingAppController sInstance;
@NonNull private final Context mContext;
+ @NonNull private final FeatureFlags mFeatureFlags;
private boolean mStartedSatelliteTransmissionUpdates;
private boolean mLastNeedFullScreenPointingUI;
+ private boolean mLastIsDemoMode;
+ private boolean mLastIsEmergency;
private boolean mListenerForPointingUIRegistered;
@NonNull private String mPointingUiPackageName = "";
@NonNull private String mPointingUiClassName = "";
@@ -72,6 +78,7 @@
*/
private final ConcurrentHashMap<Integer, SatelliteTransmissionUpdateHandler>
mSatelliteTransmissionUpdateHandlers = new ConcurrentHashMap<>();
+ @Nullable private PersistentLogger mPersistentLogger = null;
/**
* @return The singleton instance of PointingAppController.
@@ -86,11 +93,13 @@
/**
* Create the PointingAppController singleton instance.
* @param context The Context to use to create the PointingAppController.
+ * @param featureFlags The telephony feature flags.
* @return The singleton instance of PointingAppController.
*/
- public static PointingAppController make(@NonNull Context context) {
+ public static PointingAppController make(@NonNull Context context,
+ @NonNull FeatureFlags featureFlags) {
if (sInstance == null) {
- sInstance = new PointingAppController(context);
+ sInstance = new PointingAppController(context, featureFlags);
}
return sInstance;
}
@@ -101,12 +110,20 @@
* @param context The Context for the PointingUIController.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public PointingAppController(@NonNull Context context) {
+ public PointingAppController(@NonNull Context context,
+ @NonNull FeatureFlags featureFlags) {
mContext = context;
+ mFeatureFlags = featureFlags;
mStartedSatelliteTransmissionUpdates = false;
mLastNeedFullScreenPointingUI = false;
+ mLastIsDemoMode = false;
+ mLastIsEmergency = false;
mListenerForPointingUIRegistered = false;
mActivityManager = mContext.getSystemService(ActivityManager.class);
+ if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+ mPersistentLogger = new PersistentLogger(
+ DropBoxManagerLoggerBackend.getInstance(context));
+ }
}
/**
@@ -130,15 +147,6 @@
}
/**
- * Get the flag mStartedSatelliteTransmissionUpdates
- * @return returns mStartedSatelliteTransmissionUpdates
- */
- @VisibleForTesting
- public boolean getLastNeedFullScreenPointingUI() {
- return mLastNeedFullScreenPointingUI;
- }
-
- /**
* Listener for handling pointing UI App in the event of crash
*/
@VisibleForTesting
@@ -152,20 +160,23 @@
if (callerPackages != null) {
if (Arrays.stream(callerPackages).anyMatch(pointingUiPackage::contains)) {
- logd("Restarting pointingUI");
- startPointingUI(mLastNeedFullScreenPointingUI);
+ plogd("Restarting pointingUI");
+ startPointingUI(mLastNeedFullScreenPointingUI, mLastIsDemoMode,
+ mLastIsEmergency);
}
}
}
}
private static final class DatagramTransferStateHandlerRequest {
+ public int datagramType;
public int datagramTransferState;
public int pendingCount;
public int errorCode;
- DatagramTransferStateHandlerRequest(int datagramTransferState, int pendingCount,
- int errorCode) {
+ DatagramTransferStateHandlerRequest(int datagramType, int datagramTransferState,
+ int pendingCount, int errorCode) {
+ this.datagramType = datagramType;
this.datagramTransferState = datagramTransferState;
this.pendingCount = pendingCount;
this.errorCode = errorCode;
@@ -232,8 +243,9 @@
List<IBinder> toBeRemoved = new ArrayList<>();
mListeners.values().forEach(listener -> {
try {
- listener.onSendDatagramStateChanged(request.datagramTransferState,
- request.pendingCount, request.errorCode);
+ listener.onSendDatagramStateChanged(request.datagramType,
+ request.datagramTransferState, request.pendingCount,
+ request.errorCode);
} catch (RemoteException e) {
logd("EVENT_SEND_DATAGRAM_STATE_CHANGED RemoteException: " + e);
toBeRemoved.add(listener.asBinder());
@@ -332,7 +344,7 @@
*/
public void startSatelliteTransmissionUpdates(@NonNull Message message) {
if (mStartedSatelliteTransmissionUpdates) {
- logd("startSatelliteTransmissionUpdates: already started");
+ plogd("startSatelliteTransmissionUpdates: already started");
AsyncResult.forMessage(message, null, new SatelliteManager.SatelliteException(
SatelliteManager.SATELLITE_RESULT_SUCCESS));
message.sendToTarget();
@@ -356,10 +368,11 @@
* Check if Pointing is needed and Launch Pointing UI
* @param needFullScreenPointingUI if pointing UI has to be launchd with Full screen
*/
- public void startPointingUI(boolean needFullScreenPointingUI) {
+ public void startPointingUI(boolean needFullScreenPointingUI, boolean isDemoMode,
+ boolean isEmergency) {
String packageName = getPointingUiPackageName();
if (TextUtils.isEmpty(packageName)) {
- logd("startPointingUI: config_pointing_ui_package is not set. Ignore the request");
+ plogd("startPointingUI: config_pointing_ui_package is not set. Ignore the request");
return;
}
@@ -373,11 +386,14 @@
launchIntent = mContext.getPackageManager().getLaunchIntentForPackage(packageName);
}
if (launchIntent == null) {
- loge("startPointingUI: launchIntent is null");
+ ploge("startPointingUI: launchIntent is null");
return;
}
- logd("startPointingUI: needFullScreenPointingUI: " + needFullScreenPointingUI);
+ plogd("startPointingUI: needFullScreenPointingUI: " + needFullScreenPointingUI
+ + ", isDemoMode: " + isDemoMode + ", isEmergency: " + isEmergency);
launchIntent.putExtra("needFullScreen", needFullScreenPointingUI);
+ launchIntent.putExtra("isDemoMode", isDemoMode);
+ launchIntent.putExtra("isEmergency", isEmergency);
try {
if (!mListenerForPointingUIRegistered) {
@@ -386,9 +402,11 @@
mListenerForPointingUIRegistered = true;
}
mLastNeedFullScreenPointingUI = needFullScreenPointingUI;
+ mLastIsDemoMode = isDemoMode;
+ mLastIsEmergency = isEmergency;
mContext.startActivity(launchIntent);
} catch (ActivityNotFoundException ex) {
- loge("startPointingUI: Pointing UI app activity is not found, ex=" + ex);
+ ploge("startPointingUI: Pointing UI app activity is not found, ex=" + ex);
}
}
@@ -403,10 +421,11 @@
}
public void updateSendDatagramTransferState(int subId,
+ @SatelliteManager.DatagramType int datagramType,
@SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
int sendPendingCount, int errorCode) {
DatagramTransferStateHandlerRequest request = new DatagramTransferStateHandlerRequest(
- datagramTransferState, sendPendingCount, errorCode);
+ datagramType, datagramTransferState, sendPendingCount, errorCode);
SatelliteTransmissionUpdateHandler handler =
mSatelliteTransmissionUpdateHandlers.get(subId);
@@ -416,7 +435,7 @@
request);
msg.sendToTarget();
} else {
- loge("SatelliteTransmissionUpdateHandler not found for subId: " + subId);
+ ploge("SatelliteTransmissionUpdateHandler not found for subId: " + subId);
}
}
@@ -424,7 +443,8 @@
@SatelliteManager.SatelliteDatagramTransferState int datagramTransferState,
int receivePendingCount, int errorCode) {
DatagramTransferStateHandlerRequest request = new DatagramTransferStateHandlerRequest(
- datagramTransferState, receivePendingCount, errorCode);
+ SatelliteManager.DATAGRAM_TYPE_UNKNOWN, datagramTransferState, receivePendingCount,
+ errorCode);
SatelliteTransmissionUpdateHandler handler =
mSatelliteTransmissionUpdateHandlers.get(subId);
@@ -434,7 +454,7 @@
request);
msg.sendToTarget();
} else {
- loge(" SatelliteTransmissionUpdateHandler not found for subId: " + subId);
+ ploge(" SatelliteTransmissionUpdateHandler not found for subId: " + subId);
}
}
@@ -449,12 +469,12 @@
boolean setSatellitePointingUiClassName(
@Nullable String packageName, @Nullable String className) {
if (!isMockModemAllowed()) {
- loge("setSatellitePointingUiClassName: modifying satellite pointing UI package and "
+ ploge("setSatellitePointingUiClassName: modifying satellite pointing UI package and "
+ "class name is not allowed");
return false;
}
- logd("setSatellitePointingUiClassName: config_pointing_ui_package is updated, new "
+ plogd("setSatellitePointingUiClassName: config_pointing_ui_package is updated, new "
+ "packageName=" + packageName
+ ", config_pointing_ui_class new className=" + className);
@@ -500,6 +520,33 @@
private static void loge(@NonNull String log) {
Rlog.e(TAG, log);
}
+
+ private boolean isSatellitePersistentLoggingEnabled(
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (featureFlags.satellitePersistentLogging()) {
+ return true;
+ }
+ try {
+ return context.getResources().getBoolean(
+ R.bool.config_dropboxmanager_persistent_logging_enabled);
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ private void plogd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
+ private void ploge(@NonNull String log) {
+ Rlog.e(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.error(TAG, log);
+ }
+ }
/**
* TODO: The following needs to be added in this class:
* - check if pointingUI crashes - then restart it
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
index 8d7e723..0568d86 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConfig.java
@@ -19,6 +19,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -51,7 +52,7 @@
private Map<Integer, Map<String, Set<Integer>>> mSupportedServicesPerCarrier;
private List<String> mSatelliteRegionCountryCodes;
private Boolean mIsSatelliteRegionAllowed;
- private Path mSatS2FilePath;
+ private File mSatS2File;
private SatelliteConfigData.SatelliteConfigProto mConfigData;
public SatelliteConfig(SatelliteConfigData.SatelliteConfigProto configData) {
@@ -61,13 +62,14 @@
mSatelliteRegionCountryCodes = List.of(
mConfigData.deviceSatelliteRegion.countryCodes);
mIsSatelliteRegionAllowed = mConfigData.deviceSatelliteRegion.isAllowed;
- mSatS2FilePath = null;
+ mSatS2File = null;
Log.d(TAG, "mVersion:" + mVersion + " | "
+ "mSupportedServicesPerCarrier:" + mSupportedServicesPerCarrier + " | "
- + "mSatelliteRegionCountryCodes:" + mSatelliteRegionCountryCodes + " | "
+ + "mSatelliteRegionCountryCodes:"
+ + String.join(",", mSatelliteRegionCountryCodes) + " | "
+ "mIsSatelliteRegionAllowed:" + mIsSatelliteRegionAllowed + " | "
- + "s2CellFile size:" + mConfigData.deviceSatelliteRegion.s2CellFile.length);
+ + " | s2CellFile size:" + mConfigData.deviceSatelliteRegion.s2CellFile.length);
}
/**
@@ -139,6 +141,19 @@
}
/**
+ * Get carrier identifier set for the satellite
+ *
+ * @return carrier identifier set from the config data.
+ */
+ @NonNull
+ public Set<Integer> getAllSatelliteCarrierIds() {
+ if (mSupportedServicesPerCarrier != null) {
+ return new ArraySet<>(mSupportedServicesPerCarrier.keySet());
+ }
+ return new ArraySet<>();
+ }
+
+ /**
* @return satellite region country codes
*/
@NonNull
@@ -167,23 +182,23 @@
* @return satellite s2_cell_file path
*/
@Nullable
- public Path getSatelliteS2CellFile(@Nullable Context context) {
+ public File getSatelliteS2CellFile(@Nullable Context context) {
if (context == null) {
Log.d(TAG, "getSatelliteS2CellFile : context is null");
return null;
}
- if (isFileExist(mSatS2FilePath)) {
- Log.d(TAG, "File mSatS2FilePath is already exist");
- return mSatS2FilePath;
+ if (isFileExist(mSatS2File)) {
+ Log.d(TAG, "File mSatS2File is already exist");
+ return mSatS2File;
}
if (mConfigData != null && mConfigData.deviceSatelliteRegion != null) {
- mSatS2FilePath = copySatS2FileToPhoneDirectory(context,
- mConfigData.deviceSatelliteRegion.s2CellFile);
- return mSatS2FilePath;
+ mSatS2File = copySatS2FileToPhoneDirectory(
+ context, mConfigData.deviceSatelliteRegion.s2CellFile);
+ return mSatS2File;
}
- Log.d(TAG, "getSatelliteS2CellFile :"
+ Log.d(TAG, "getSatelliteS2CellFile: "
+ "mConfigData is null or mConfigData.deviceSatelliteRegion is null");
return null;
}
@@ -195,7 +210,7 @@
*/
@Nullable
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public Path copySatS2FileToPhoneDirectory(@Nullable Context context,
+ public File copySatS2FileToPhoneDirectory(@Nullable Context context,
@Nullable byte[] byteArrayFile) {
if (context == null || byteArrayFile == null) {
@@ -220,14 +235,18 @@
} catch (IOException ex) {
Log.e(TAG, "copySatS2FileToPhoneDirectory: ex=" + ex);
}
- return targetSatS2FilePath;
+ return targetSatS2FilePath.toFile();
}
/**
* @return {@code true} if the SatS2File is already existed and {@code false} otherwise.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
- public boolean isFileExist(Path filePath) {
- return Files.exists(filePath);
+ public boolean isFileExist(@Nullable File file) {
+ if (file == null) {
+ Log.d(TAG, "isFileExist : file is null");
+ return false;
+ }
+ return file.exists();
}
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
new file mode 100644
index 0000000..384dfa5
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteConstants.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+public class SatelliteConstants {
+ public static final int CONFIG_DATA_SOURCE_UNKNOWN = 0;
+ public static final int CONFIG_DATA_SOURCE_ENTITLEMENT = 1;
+ public static final int CONFIG_DATA_SOURCE_CONFIG_UPDATER = 2;
+ public static final int CONFIG_DATA_SOURCE_CARRIER_CONFIG = 3;
+ public static final int CONFIG_DATA_SOURCE_DEVICE_CONFIG = 4;
+
+ @IntDef(prefix = {"CONFIG_DATA_SOURCE_"}, value = {
+ CONFIG_DATA_SOURCE_UNKNOWN,
+ CONFIG_DATA_SOURCE_ENTITLEMENT,
+ CONFIG_DATA_SOURCE_CONFIG_UPDATER,
+ CONFIG_DATA_SOURCE_CARRIER_CONFIG,
+ CONFIG_DATA_SOURCE_DEVICE_CONFIG
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ConfigDataSource {}
+
+ public static final int SATELLITE_ENTITLEMENT_STATUS_UNKNOWN = 0;
+ public static final int SATELLITE_ENTITLEMENT_STATUS_DISABLED = 1;
+ public static final int SATELLITE_ENTITLEMENT_STATUS_ENABLED = 2;
+ public static final int SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE = 3;
+ public static final int SATELLITE_ENTITLEMENT_STATUS_PROVISIONING = 4;
+
+ @IntDef(prefix = {"SATELLITE_ENTITLEMENT_STATUS_"}, value = {
+ SATELLITE_ENTITLEMENT_STATUS_UNKNOWN,
+ SATELLITE_ENTITLEMENT_STATUS_DISABLED,
+ SATELLITE_ENTITLEMENT_STATUS_ENABLED,
+ SATELLITE_ENTITLEMENT_STATUS_INCOMPATIBLE,
+ SATELLITE_ENTITLEMENT_STATUS_PROVISIONING
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SatelliteEntitlementStatus {}
+
+ public static final int CONFIG_UPDATE_RESULT_UNKNOWN = 0;
+ public static final int CONFIG_UPDATE_RESULT_SUCCESS = 1;
+ public static final int CONFIG_UPDATE_RESULT_INVALID_DOMAIN = 2;
+ public static final int CONFIG_UPDATE_RESULT_INVALID_VERSION = 3;
+ public static final int CONFIG_UPDATE_RESULT_NO_DATA = 4;
+ public static final int CONFIG_UPDATE_RESULT_NO_SATELLITE_DATA = 5;
+ public static final int CONFIG_UPDATE_RESULT_PARSE_ERROR = 6;
+ public static final int CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_PLMN = 7;
+ public static final int CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_SUPPORTED_SERVICES = 8;
+ public static final int CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_COUNTRY_CODE = 9;
+ public static final int CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_S2_CELL_FILE = 10;
+ public static final int CONFIG_UPDATE_RESULT_IO_ERROR = 11;
+
+ @IntDef(prefix = {"CONFIG_UPDATE_RESULT_"}, value = {
+ CONFIG_UPDATE_RESULT_UNKNOWN,
+ CONFIG_UPDATE_RESULT_SUCCESS,
+ CONFIG_UPDATE_RESULT_INVALID_DOMAIN,
+ CONFIG_UPDATE_RESULT_INVALID_VERSION,
+ CONFIG_UPDATE_RESULT_NO_DATA,
+ CONFIG_UPDATE_RESULT_NO_SATELLITE_DATA,
+ CONFIG_UPDATE_RESULT_PARSE_ERROR,
+ CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_PLMN,
+ CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_SUPPORTED_SERVICES,
+ CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_COUNTRY_CODE,
+ CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_S2_CELL_FILE,
+ CONFIG_UPDATE_RESULT_IO_ERROR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ConfigUpdateResult {}
+
+ // Access control type is unknown
+ public static final int ACCESS_CONTROL_TYPE_UNKNOWN = 0;
+ // Network country code is used for satellite access decision
+ public static final int ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE = 1;
+ // Device's current location is used for satellite access decision
+ public static final int ACCESS_CONTROL_TYPE_CURRENT_LOCATION = 2;
+ // Device's last known location is used for satellite access decision
+ public static final int ACCESS_CONTROL_TYPE_LAST_KNOWN_LOCATION = 3;
+ // Cached country codes are used for satellite access decision
+ public static final int ACCESS_CONTROL_TYPE_CACHED_COUNTRY_CODE = 4;
+
+ @IntDef(prefix = {"ACCESS_CONTROL_TYPE_"}, value = {
+ ACCESS_CONTROL_TYPE_UNKNOWN,
+ ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE,
+ ACCESS_CONTROL_TYPE_CURRENT_LOCATION,
+ ACCESS_CONTROL_TYPE_LAST_KNOWN_LOCATION,
+ ACCESS_CONTROL_TYPE_CACHED_COUNTRY_CODE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface AccessControlType {}
+}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteController.java b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
index 2c12939..f826f0b 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteController.java
@@ -17,7 +17,10 @@
package com.android.internal.telephony.satellite;
import static android.provider.Settings.ACTION_SATELLITE_SETTING;
+import static android.telephony.CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY;
import static android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE;
+import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT;
+import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL;
@@ -50,6 +53,7 @@
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.Uri;
@@ -77,7 +81,12 @@
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.Settings;
+import android.provider.Telephony;
+import android.telephony.AccessNetworkConstants;
import android.telephony.CarrierConfigManager;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -87,6 +96,7 @@
import android.telephony.satellite.ISatelliteDatagramCallback;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
+import android.telephony.satellite.ISatelliteSupportedStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
@@ -110,10 +120,13 @@
import com.android.internal.telephony.configupdate.ConfigProviderAdaptor;
import com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteControllerStats;
+import com.android.internal.telephony.satellite.metrics.CarrierRoamingSatelliteSessionStats;
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
import com.android.internal.telephony.satellite.metrics.ProvisionMetricsStats;
import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.FunctionalUtils;
import java.util.ArrayList;
@@ -123,13 +136,15 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
+import java.util.stream.Collectors;
/**
* Satellite controller is the backend service of
@@ -143,6 +158,7 @@
private static final boolean DEBUG = !"user".equals(Build.TYPE);
/** File used to store shared preferences related to satellite. */
public static final String SATELLITE_SHARED_PREF = "satellite_shared_pref";
+ public static final String SATELLITE_SUBSCRIPTION_ID = "satellite_subscription_id";
/** Value to pass for the setting key SATELLITE_MODE_ENABLED, enabled = 1, disabled = 0 */
public static final int SATELLITE_MODE_ENABLED_TRUE = 1;
public static final int SATELLITE_MODE_ENABLED_FALSE = 0;
@@ -152,11 +168,18 @@
* to enable satellite.
*/
public static final int TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE = 1;
+ /** This is used by CTS to override demo pointing aligned duration. */
+ public static final int TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS = 2;
+ /** This is used by CTS to override demo pointing not aligned duration. */
+ public static final int TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS = 3;
/** Key used to read/write OEM-enabled satellite provision status in shared preferences. */
private static final String OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY =
"oem_enabled_satellite_provision_status_key";
+ public static final long DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS =
+ TimeUnit.SECONDS.toMillis(30);
+
/** Message codes used in handleMessage() */
//TODO: Move the Commands and events related to position updates to PointingAppController
private static final int CMD_START_SATELLITE_TRANSMISSION_UPDATES = 1;
@@ -175,8 +198,6 @@
private static final int EVENT_IS_SATELLITE_SUPPORTED_DONE = 16;
private static final int CMD_GET_SATELLITE_CAPABILITIES = 17;
private static final int EVENT_GET_SATELLITE_CAPABILITIES_DONE = 18;
- private static final int CMD_IS_SATELLITE_COMMUNICATION_ALLOWED = 19;
- private static final int EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE = 20;
private static final int CMD_GET_TIME_SATELLITE_NEXT_VISIBLE = 21;
private static final int EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE = 22;
private static final int EVENT_RADIO_STATE_CHANGED = 23;
@@ -197,15 +218,20 @@
private static final int EVENT_SATELLITE_CAPABILITIES_CHANGED = 38;
private static final int EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT = 39;
private static final int EVENT_SATELLITE_CONFIG_DATA_UPDATED = 40;
+ private static final int EVENT_SATELLITE_SUPPORTED_STATE_CHANGED = 41;
+ private static final int EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT = 42;
@NonNull private static SatelliteController sInstance;
@NonNull private final Context mContext;
@NonNull private final SatelliteModemInterface mSatelliteModemInterface;
- @NonNull private SatelliteSessionController mSatelliteSessionController;
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ @NonNull protected SatelliteSessionController mSatelliteSessionController;
@NonNull private final PointingAppController mPointingAppController;
@NonNull private final DatagramController mDatagramController;
@NonNull private final ControllerMetricsStats mControllerMetricsStats;
@NonNull private final ProvisionMetricsStats mProvisionMetricsStats;
+ @NonNull private SessionMetricsStats mSessionMetricsStats;
+ @NonNull private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats;
@NonNull private final SubscriptionManagerService mSubscriptionManagerService;
private final CommandsInterface mCi;
private ContentResolver mContentResolver;
@@ -250,7 +276,12 @@
private final AtomicBoolean mRegisteredForNtnSignalStrengthChanged = new AtomicBoolean(false);
private final AtomicBoolean mRegisteredForSatelliteCapabilitiesChanged =
new AtomicBoolean(false);
- private final AtomicBoolean mShouldReportNtnSignalStrength = new AtomicBoolean(false);
+ private final AtomicBoolean mIsModemEnabledReportingNtnSignalStrength =
+ new AtomicBoolean(false);
+ private final AtomicBoolean mLatestRequestedStateForNtnSignalStrengthReport =
+ new AtomicBoolean(false);
+ private final AtomicBoolean mRegisteredForSatelliteSupportedStateChanged =
+ new AtomicBoolean(false);
/**
* Map key: subId, value: callback to get error code of the provision request.
*/
@@ -274,13 +305,21 @@
*/
private final ConcurrentHashMap<IBinder, ISatelliteCapabilitiesCallback>
mSatelliteCapabilitiesChangedListeners = new ConcurrentHashMap<>();
+ /**
+ * Map key: binder of the callback, value: callback to receive supported state changed events.
+ */
+ private final ConcurrentHashMap<IBinder, ISatelliteSupportedStateCallback>
+ mSatelliteSupportedStateChangedListeners = new ConcurrentHashMap<>();
private final Object mIsSatelliteSupportedLock = new Object();
@GuardedBy("mIsSatelliteSupportedLock")
private Boolean mIsSatelliteSupported = null;
private boolean mIsDemoModeEnabled = false;
+ private boolean mIsEmergency = false;
private final Object mIsSatelliteEnabledLock = new Object();
@GuardedBy("mIsSatelliteEnabledLock")
private Boolean mIsSatelliteEnabled = null;
+ private final Object mIsRadioOnLock = new Object();
+ @GuardedBy("mIsRadioOnLock")
private boolean mIsRadioOn = false;
private final Object mSatelliteViaOemProvisionLock = new Object();
@GuardedBy("mSatelliteViaOemProvisionLock")
@@ -336,8 +375,22 @@
mWasSatelliteConnectedViaCarrier = new SparseBooleanArray();
@GuardedBy("mSatelliteConnectedLock")
- @NonNull private final SparseBooleanArray
- mIsSatelliteConnectedViaCarrierHysteresisTimeExpired = new SparseBooleanArray();
+ @NonNull private final SparseBooleanArray mLastNotifiedNtnMode = new SparseBooleanArray();
+
+ @GuardedBy("mSatelliteConnectedLock")
+ @NonNull private final SparseBooleanArray mInitialized = new SparseBooleanArray();
+
+ @GuardedBy("mSatelliteConnectedLock")
+ @NonNull private final Map<Integer, CarrierRoamingSatelliteSessionStats>
+ mCarrierRoamingSatelliteSessionStatsMap = new HashMap<>();
+
+ /**
+ * Key: Subscription ID; Value: set of
+ * {@link android.telephony.NetworkRegistrationInfo.ServiceType}
+ */
+ @GuardedBy("mSatelliteConnectedLock")
+ @NonNull private final Map<Integer, List<Integer>>
+ mSatModeCapabilitiesForCarrierRoaming = new HashMap<>();
/**
* This is used for testing only. When mEnforcedEmergencyCallToSatelliteHandoverType is valid,
@@ -349,6 +402,8 @@
private int mDelayInSendingEventDisplayEmergencyMessage = 0;
@NonNull private SharedPreferences mSharedPreferences = null;
+ @Nullable private PersistentLogger mPersistentLogger = null;
+
/**
* Key : Subscription ID, Value: {@code true} if the EntitlementStatus is enabled,
* {@code false} otherwise.
@@ -358,6 +413,9 @@
/** Key Subscription ID, value : PLMN allowed list from entitlement. */
@GuardedBy("mSupportedSatelliteServicesLock")
private SparseArray<List<String>> mEntitlementPlmnListPerCarrier = new SparseArray<>();
+ /** Key Subscription ID, value : PLMN barred list from entitlement. */
+ @GuardedBy("mSupportedSatelliteServicesLock")
+ private SparseArray<List<String>> mEntitlementBarredPlmnListPerCarrier = new SparseArray<>();
/**
* Key : Subscription ID, Value : If there is an entitlementPlmnList, use it. Otherwise, use the
* carrierPlmnList. */
@@ -365,6 +423,13 @@
private final SparseArray<List<String>> mMergedPlmnListPerCarrier = new SparseArray<>();
private static AtomicLong sNextSatelliteEnableRequestId = new AtomicLong(0);
private long mWaitTimeForSatelliteEnablingResponse;
+ private long mDemoPointingAlignedDurationMillis;
+ private long mDemoPointingNotAlignedDurationMillis;
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private long mLastEmergencyCallTime;
+ private long mSatelliteEmergencyModeDurationMillis;
+ private static final int DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS = 300;
/** Key used to read/write satellite system notification done in shared preferences. */
private static final String SATELLITE_SYSTEM_NOTIFICATION_DONE_KEY =
@@ -377,6 +442,14 @@
private static final String NOTIFICATION_CHANNEL_ID = "satellite";
private final RegistrantList mSatelliteConfigUpdateChangedRegistrants = new RegistrantList();
+ private final BTWifiNFCStateReceiver mBTWifiNFCSateReceiver;
+ private final UwbAdapterStateCallback mUwbAdapterStateCallback;
+
+ private long mSessionStartTimeStamp;
+ private long mSessionProcessingTimeStamp;
+
+ // Variable for backup and restore device's screen rotation settings.
+ private String mDeviceRotationLockToBackupAndRestore = null;
/**
* @return The singleton instance of SatelliteController.
@@ -414,6 +487,11 @@
@NonNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags) {
super(looper);
+ if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+ mPersistentLogger = new PersistentLogger(
+ DropBoxManagerLoggerBackend.getInstance(context));
+ }
+
mContext = context;
mFeatureFlags = featureFlags;
Phone phone = SatelliteServiceUtils.getPhone();
@@ -421,24 +499,32 @@
mDSM = phone.getDeviceStateMonitor();
// Create the SatelliteModemInterface singleton, which is used to manage connections
// to the satellite service and HAL interface.
- mSatelliteModemInterface = SatelliteModemInterface.make(mContext, this);
+ mSatelliteModemInterface = SatelliteModemInterface.make(
+ mContext, this, mFeatureFlags);
// Create the PointingUIController singleton,
// which is used to manage interactions with PointingUI app.
- mPointingAppController = PointingAppController.make(mContext);
+ mPointingAppController = PointingAppController.make(mContext, mFeatureFlags);
// Create the SatelliteControllerMetrics to report controller metrics
// should be called before making DatagramController
mControllerMetricsStats = ControllerMetricsStats.make(mContext);
mProvisionMetricsStats = ProvisionMetricsStats.getOrCreateInstance();
+ mSessionMetricsStats = SessionMetricsStats.getInstance();
+ mCarrierRoamingSatelliteControllerStats =
+ CarrierRoamingSatelliteControllerStats.getOrCreateInstance();
mSubscriptionManagerService = SubscriptionManagerService.getInstance();
// Create the DatagramController singleton,
// which is used to send and receive satellite datagrams.
- mDatagramController = DatagramController.make(mContext, looper, mPointingAppController);
+ mDatagramController = DatagramController.make(
+ mContext, looper, mFeatureFlags, mPointingAppController);
mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
- mIsRadioOn = phone.isRadioOn();
+ synchronized (mIsRadioOnLock) {
+ mIsRadioOn = phone.isRadioOn();
+ }
+
registerForSatelliteProvisionStateChanged();
registerForPendingDatagramCount();
registerForSatelliteModemStateChanged();
@@ -446,6 +532,8 @@
mContentResolver = mContext.getContentResolver();
mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
+ mBTWifiNFCSateReceiver = new BTWifiNFCStateReceiver();
+ mUwbAdapterStateCallback = new UwbAdapterStateCallback();
initializeSatelliteModeRadios();
ContentObserver satelliteModeRadiosContentObserver = new ContentObserver(this) {
@@ -484,6 +572,11 @@
null);
loadSatelliteSharedPreferences();
mWaitTimeForSatelliteEnablingResponse = getWaitForSatelliteEnablingResponseTimeoutMillis();
+ mDemoPointingAlignedDurationMillis = getDemoPointingAlignedDurationMillisFromResources();
+ mDemoPointingNotAlignedDurationMillis =
+ getDemoPointingNotAlignedDurationMillisFromResources();
+ mSatelliteEmergencyModeDurationMillis =
+ getSatelliteEmergencyModeDurationFromOverlayConfig(context);
}
/**
@@ -509,11 +602,12 @@
* Get satelliteConfig from SatelliteConfigParser
*/
public SatelliteConfig getSatelliteConfig() {
- if (getSatelliteConfigParser() == null) {
- Log.d(TAG, "getSatelliteConfigParser() is not ready");
+ SatelliteConfigParser satelliteConfigParser = getSatelliteConfigParser();
+ if (satelliteConfigParser == null) {
+ Log.d(TAG, "satelliteConfigParser is not ready");
return null;
}
- return (SatelliteConfig) getSatelliteConfigParser().getConfig();
+ return satelliteConfigParser.getConfig();
}
/**
@@ -528,8 +622,6 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected void initializeSatelliteModeRadios() {
if (mContentResolver != null) {
- BTWifiNFCStateReceiver bTWifiNFCSateReceiver = new BTWifiNFCStateReceiver();
- UwbAdapterStateCallback uwbAdapterStateCallback = new UwbAdapterStateCallback();
IntentFilter radioStateIntentFilter = new IntentFilter();
synchronized (mRadioStateLock) {
@@ -548,10 +640,10 @@
String satelliteModeRadios = Settings.Global.getString(mContentResolver,
Settings.Global.SATELLITE_MODE_RADIOS);
if (satelliteModeRadios == null) {
- loge("initializeSatelliteModeRadios: satelliteModeRadios is null");
+ ploge("initializeSatelliteModeRadios: satelliteModeRadios is null");
return;
}
- logd("Radios To be checked when satellite is on: " + satelliteModeRadios);
+ plogd("Radios To be checked when satellite is on: " + satelliteModeRadios);
if (satelliteModeRadios.contains(Settings.Global.RADIO_BLUETOOTH)) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -583,7 +675,14 @@
radioStateIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
}
}
- mContext.registerReceiver(bTWifiNFCSateReceiver, radioStateIntentFilter);
+
+ try {
+ // Unregister receiver before registering it.
+ mContext.unregisterReceiver(mBTWifiNFCSateReceiver);
+ } catch (IllegalArgumentException e) {
+ plogd("initializeSatelliteModeRadios: unregisterReceiver, e=" + e);
+ }
+ mContext.registerReceiver(mBTWifiNFCSateReceiver, radioStateIntentFilter);
if (satelliteModeRadios.contains(Settings.Global.RADIO_UWB)) {
UwbManager uwbManager = mContext.getSystemService(UwbManager.class);
@@ -592,20 +691,22 @@
mUwbStateEnabled = uwbManager.isUwbEnabled();
final long identity = Binder.clearCallingIdentity();
try {
+ // Unregister callback before registering it.
+ uwbManager.unregisterAdapterStateCallback(mUwbAdapterStateCallback);
uwbManager.registerAdapterStateCallback(mContext.getMainExecutor(),
- uwbAdapterStateCallback);
+ mUwbAdapterStateCallback);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
- logd("mDisableBTOnSatelliteEnabled: " + mDisableBTOnSatelliteEnabled
+ plogd("mDisableBTOnSatelliteEnabled: " + mDisableBTOnSatelliteEnabled
+ " mDisableNFCOnSatelliteEnabled: " + mDisableNFCOnSatelliteEnabled
+ " mDisableWifiOnSatelliteEnabled: " + mDisableWifiOnSatelliteEnabled
+ " mDisableUWBOnSatelliteEnabled: " + mDisableUWBOnSatelliteEnabled);
- logd("mBTStateEnabled: " + mBTStateEnabled
+ plogd("mBTStateEnabled: " + mBTStateEnabled
+ " mNfcStateEnabled: " + mNfcStateEnabled
+ " mWifiStateEnabled: " + mWifiStateEnabled
+ " mUwbStateEnabled: " + mUwbStateEnabled);
@@ -633,8 +734,8 @@
@Override
public void onStateChanged(int state, int reason) {
- logd("UwbAdapterStateCallback#onStateChanged() called, state = " + toString(state));
- logd("Adapter state changed reason " + String.valueOf(reason));
+ plogd("UwbAdapterStateCallback#onStateChanged() called, state = " + toString(state));
+ plogd("Adapter state changed reason " + String.valueOf(reason));
synchronized (mRadioStateLock) {
if (state == UwbManager.AdapterStateCallback.STATE_DISABLED) {
mUwbStateEnabled = false;
@@ -642,7 +743,7 @@
} else {
mUwbStateEnabled = true;
}
- logd("mUwbStateEnabled: " + mUwbStateEnabled);
+ plogd("mUwbStateEnabled: " + mUwbStateEnabled);
}
}
}
@@ -652,7 +753,7 @@
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action == null) {
- logd("BTWifiNFCStateReceiver NULL action for intent " + intent);
+ plogd("BTWifiNFCStateReceiver NULL action for intent " + intent);
return;
}
@@ -669,7 +770,7 @@
mBTStateEnabled = true;
}
if (currentBTStateEnabled != mBTStateEnabled) {
- logd("mBTStateEnabled=" + mBTStateEnabled);
+ plogd("mBTStateEnabled=" + mBTStateEnabled);
}
}
break;
@@ -685,7 +786,7 @@
evaluateToSendSatelliteEnabledSuccess();
}
if (currentNfcStateEnabled != mNfcStateEnabled) {
- logd("mNfcStateEnabled=" + mNfcStateEnabled);
+ plogd("mNfcStateEnabled=" + mNfcStateEnabled);
}
}
break;
@@ -702,7 +803,7 @@
evaluateToSendSatelliteEnabledSuccess();
}
if (currentWifiStateEnabled != mWifiStateEnabled) {
- logd("mWifiStateEnabled=" + mWifiStateEnabled);
+ plogd("mWifiStateEnabled=" + mWifiStateEnabled);
}
}
break;
@@ -729,13 +830,15 @@
private static final class RequestSatelliteEnabledArgument {
public boolean enableSatellite;
public boolean enableDemoMode;
+ public boolean isEmergency;
@NonNull public Consumer<Integer> callback;
public long requestId;
RequestSatelliteEnabledArgument(boolean enableSatellite, boolean enableDemoMode,
- Consumer<Integer> callback) {
+ boolean isEmergency, Consumer<Integer> callback) {
this.enableSatellite = enableSatellite;
this.enableDemoMode = enableDemoMode;
+ this.isEmergency = isEmergency;
this.callback = callback;
this.requestId = sNextSatelliteEnableRequestId.getAndUpdate(
n -> ((n + 1) % Long.MAX_VALUE));
@@ -889,14 +992,14 @@
RequestSatelliteEnabledArgument argument =
(RequestSatelliteEnabledArgument) request.argument;
int error = SatelliteServiceUtils.getSatelliteError(ar, "setSatelliteEnabled");
- logd("EVENT_SET_SATELLITE_ENABLED_DONE = " + error);
+ plogd("EVENT_SET_SATELLITE_ENABLED_DONE = " + error);
/*
* The timer to wait for EVENT_SET_SATELLITE_ENABLED_DONE might have expired and
* thus the request resources might have been cleaned up.
*/
if (!shouldProcessEventSetSatelliteEnabledDone(argument)) {
- logw("The request ID=" + argument.requestId + ", enableSatellite="
+ plogw("The request ID=" + argument.requestId + ", enableSatellite="
+ argument.enableSatellite + " was already processed");
return;
}
@@ -908,6 +1011,7 @@
mWaitingForRadioDisabled = true;
}
setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_TRUE);
+ setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_TRUE);
evaluateToSendSatelliteEnabledSuccess();
} else {
/**
@@ -934,12 +1038,15 @@
SATELLITE_RESULT_SUCCESS,
argument.callback);
} else {
- logd("Wait for satellite modem off before updating satellite"
+ plogd("Wait for satellite modem off before updating satellite"
+ " modem state");
}
mWaitingForDisableSatelliteModemResponse = false;
}
}
+ // Request Ntn signal strength report when satellite enabled or disabled done.
+ mLatestRequestedStateForNtnSignalStrengthReport.set(argument.enableSatellite);
+ updateNtnSignalStrengthReporting(argument.enableSatellite);
} else {
synchronized (mSatelliteEnabledRequestLock) {
if (mSatelliteEnabledRequest != null &&
@@ -951,6 +1058,7 @@
SATELLITE_RESULT_SUCCESS);
}
}
+ notifyEnablementFailedToSatelliteSessionController();
resetSatelliteEnabledRequest();
// If Satellite enable/disable request returned Error, no need to wait for radio
@@ -958,18 +1066,34 @@
}
if (argument.enableSatellite) {
+ mSessionMetricsStats.setInitializationResult(error)
+ .setSatelliteTechnology(getSupportedNtnRadioTechnology())
+ .setInitializationProcessingTime(
+ System.currentTimeMillis() - mSessionProcessingTimeStamp)
+ .setIsDemoMode(mIsDemoModeEnabled);
+ mSessionProcessingTimeStamp = 0;
+
if (error == SATELLITE_RESULT_SUCCESS) {
mControllerMetricsStats.onSatelliteEnabled();
mControllerMetricsStats.reportServiceEnablementSuccessCount();
} else {
+ mSessionMetricsStats.reportSessionMetrics();
+ mSessionStartTimeStamp = 0;
mControllerMetricsStats.reportServiceEnablementFailCount();
}
- SessionMetricsStats.getInstance()
- .setInitializationResult(error)
- .setRadioTechnology(getSupportedNtnRadioTechnology())
- .reportSessionMetrics();
} else {
+ mSessionMetricsStats.setTerminationResult(error)
+ .setTerminationProcessingTime(System.currentTimeMillis()
+ - mSessionProcessingTimeStamp)
+ .setSessionDurationSec(calculateSessionDurationTimeSec())
+ .reportSessionMetrics();
+ mSessionStartTimeStamp = 0;
+ mSessionProcessingTimeStamp = 0;
+
mControllerMetricsStats.onSatelliteDisabled();
+
+ handlePersistentLoggingOnSessionEnd(mIsEmergency);
+
synchronized (mIsSatelliteEnabledLock) {
mWaitingForDisableSatelliteModemResponse = false;
}
@@ -997,11 +1121,11 @@
Bundle bundle = new Bundle();
if (error == SATELLITE_RESULT_SUCCESS) {
if (ar.result == null) {
- loge("isSatelliteEnabled: result is null");
+ ploge("isSatelliteEnabled: result is null");
error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
} else {
boolean enabled = ((int[]) ar.result)[0] == 1;
- if (DBG) logd("isSatelliteEnabled: " + enabled);
+ if (DBG) plogd("isSatelliteEnabled: " + enabled);
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_ENABLED, enabled);
updateSatelliteEnabledState(enabled, "EVENT_IS_SATELLITE_ENABLED_DONE");
}
@@ -1026,11 +1150,11 @@
Bundle bundle = new Bundle();
if (error == SATELLITE_RESULT_SUCCESS) {
if (ar.result == null) {
- loge("isSatelliteSupported: result is null");
+ ploge("isSatelliteSupported: result is null");
error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
} else {
boolean supported = (boolean) ar.result;
- logd("isSatelliteSupported: " + supported);
+ plogd("isSatelliteSupported: " + supported);
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, supported);
updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported);
}
@@ -1054,14 +1178,14 @@
Bundle bundle = new Bundle();
if (error == SATELLITE_RESULT_SUCCESS) {
if (ar.result == null) {
- loge("getSatelliteCapabilities: result is null");
+ ploge("getSatelliteCapabilities: result is null");
error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
} else {
SatelliteCapabilities capabilities = (SatelliteCapabilities) ar.result;
synchronized (mNeedsSatellitePointingLock) {
mNeedsSatellitePointing = capabilities.isPointingRequired();
}
- if (DBG) logd("getSatelliteCapabilities: " + capabilities);
+ if (DBG) plogd("getSatelliteCapabilities: " + capabilities);
bundle.putParcelable(SatelliteManager.KEY_SATELLITE_CAPABILITIES,
capabilities);
synchronized (mSatelliteCapabilitiesLock) {
@@ -1073,39 +1197,6 @@
break;
}
- case CMD_IS_SATELLITE_COMMUNICATION_ALLOWED: {
- request = (SatelliteControllerHandlerRequest) msg.obj;
- onCompleted =
- obtainMessage(EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE, request);
- mSatelliteModemInterface
- .requestIsSatelliteCommunicationAllowedForCurrentLocation(onCompleted);
- break;
- }
-
- case EVENT_IS_SATELLITE_COMMUNICATION_ALLOWED_DONE: {
- ar = (AsyncResult) msg.obj;
- request = (SatelliteControllerHandlerRequest) ar.userObj;
- int error = SatelliteServiceUtils.getSatelliteError(ar,
- "isSatelliteCommunicationAllowedForCurrentLocation");
- Bundle bundle = new Bundle();
- if (error == SATELLITE_RESULT_SUCCESS) {
- if (ar.result == null) {
- loge("isSatelliteCommunicationAllowedForCurrentLocation: result is null");
- error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
- } else {
- boolean communicationAllowed = (boolean) ar.result;
- if (DBG) {
- logd("isSatelliteCommunicationAllowedForCurrentLocation: "
- + communicationAllowed);
- }
- bundle.putBoolean(SatelliteManager.KEY_SATELLITE_COMMUNICATION_ALLOWED,
- communicationAllowed);
- }
- }
- ((ResultReceiver) request.argument).send(error, bundle);
- break;
- }
-
case CMD_GET_TIME_SATELLITE_NEXT_VISIBLE: {
request = (SatelliteControllerHandlerRequest) msg.obj;
onCompleted = obtainMessage(EVENT_GET_TIME_SATELLITE_NEXT_VISIBLE_DONE,
@@ -1122,13 +1213,13 @@
Bundle bundle = new Bundle();
if (error == SATELLITE_RESULT_SUCCESS) {
if (ar.result == null) {
- loge("requestTimeForNextSatelliteVisibility: result is null");
+ ploge("requestTimeForNextSatelliteVisibility: result is null");
error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
} else {
int nextVisibilityDuration = ((int[]) ar.result)[0];
if (DBG) {
- logd("requestTimeForNextSatelliteVisibility: " +
- nextVisibilityDuration);
+ plogd("requestTimeForNextSatelliteVisibility: "
+ + nextVisibilityDuration);
}
bundle.putInt(SatelliteManager.KEY_SATELLITE_NEXT_VISIBILITY,
nextVisibilityDuration);
@@ -1139,9 +1230,15 @@
}
case EVENT_RADIO_STATE_CHANGED: {
- if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
- mIsRadioOn = true;
+ synchronized (mIsRadioOnLock) {
+ logd("EVENT_RADIO_STATE_CHANGED: radioState=" + mCi.getRadioState());
+ if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
+ mIsRadioOn = true;
+ } else if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_OFF) {
+ resetCarrierRoamingSatelliteModeParams();
+ }
}
+
if (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
if (mSatelliteModemInterface.isSatelliteServiceConnected()) {
synchronized (mIsSatelliteSupportedLock) {
@@ -1150,7 +1247,7 @@
@Override
protected void onReceiveResult(
int resultCode, Bundle resultData) {
- logd("onRadioStateChanged.requestIsSatelliteSupported: "
+ plogd("onRadioStateChanged.requestIsSatelliteSupported: "
+ "resultCode=" + resultCode
+ ", resultData=" + resultData);
}
@@ -1178,18 +1275,18 @@
case EVENT_SATELLITE_PROVISION_STATE_CHANGED:
ar = (AsyncResult) msg.obj;
if (ar.result == null) {
- loge("EVENT_SATELLITE_PROVISION_STATE_CHANGED: result is null");
+ ploge("EVENT_SATELLITE_PROVISION_STATE_CHANGED: result is null");
} else {
handleEventSatelliteProvisionStateChanged((boolean) ar.result);
}
break;
case EVENT_PENDING_DATAGRAMS:
- logd("Received EVENT_PENDING_DATAGRAMS");
+ plogd("Received EVENT_PENDING_DATAGRAMS");
IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
- logd("pollPendingSatelliteDatagram result: " + result);
+ plogd("pollPendingSatelliteDatagram result: " + result);
}
};
pollPendingDatagrams(
@@ -1199,7 +1296,7 @@
case EVENT_SATELLITE_MODEM_STATE_CHANGED:
ar = (AsyncResult) msg.obj;
if (ar.result == null) {
- loge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null");
+ ploge("EVENT_SATELLITE_MODEM_STATE_CHANGED: result is null");
} else {
handleEventSatelliteModemStateChanged((int) ar.result);
}
@@ -1210,7 +1307,7 @@
break;
case CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE: {
- logd("CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE");
+ plogd("CMD_EVALUATE_SATELLITE_ATTACH_RESTRICTION_CHANGE");
request = (SatelliteControllerHandlerRequest) msg.obj;
handleRequestSatelliteAttachRestrictionForCarrierCmd(request);
break;
@@ -1241,7 +1338,7 @@
}
case CMD_REQUEST_NTN_SIGNAL_STRENGTH: {
- logd("CMD_REQUEST_NTN_SIGNAL_STRENGTH");
+ plogd("CMD_REQUEST_NTN_SIGNAL_STRENGTH");
request = (SatelliteControllerHandlerRequest) msg.obj;
onCompleted = obtainMessage(EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE, request);
mSatelliteModemInterface.requestNtnSignalStrength(onCompleted);
@@ -1270,7 +1367,7 @@
NTN_SIGNAL_STRENGTH_NONE);
}
}
- loge("EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: ntnSignalStrength is null");
+ ploge("EVENT_REQUEST_NTN_SIGNAL_STRENGTH_DONE: ntnSignalStrength is null");
result.send(SatelliteManager.SATELLITE_RESULT_REQUEST_FAILED, null);
}
} else {
@@ -1287,7 +1384,7 @@
case EVENT_NTN_SIGNAL_STRENGTH_CHANGED: {
ar = (AsyncResult) msg.obj;
if (ar.result == null) {
- loge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null");
+ ploge("EVENT_NTN_SIGNAL_STRENGTH_CHANGED: result is null");
} else {
handleEventNtnSignalStrengthChanged((NtnSignalStrength) ar.result);
}
@@ -1298,27 +1395,9 @@
ar = (AsyncResult) msg.obj;
boolean shouldReport = (boolean) ar.result;
if (DBG) {
- logd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: shouldReport=" + shouldReport);
+ plogd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING: shouldReport=" + shouldReport);
}
- request = new SatelliteControllerHandlerRequest(shouldReport,
- SatelliteServiceUtils.getPhone());
- if (SATELLITE_RESULT_SUCCESS != evaluateOemSatelliteRequestAllowed(true)) {
- return;
- }
- if (mShouldReportNtnSignalStrength.get() == shouldReport) {
- if (DBG) {
- logd("CMD_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING : modem state matches the "
- + "expected state, return.");
- }
- return;
- }
- onCompleted = obtainMessage(EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE,
- request);
- if (shouldReport) {
- mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted);
- } else {
- mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted);
- }
+ handleCmdUpdateNtnSignalStrengthReporting(shouldReport);
break;
}
@@ -1327,9 +1406,17 @@
request = (SatelliteControllerHandlerRequest) ar.userObj;
boolean shouldReport = (boolean) request.argument;
int errorCode = SatelliteServiceUtils.getSatelliteError(ar,
- "EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE");
+ "EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE: shouldReport="
+ + shouldReport);
if (errorCode == SATELLITE_RESULT_SUCCESS) {
- mShouldReportNtnSignalStrength.set(shouldReport);
+ mIsModemEnabledReportingNtnSignalStrength.set(shouldReport);
+ if (mLatestRequestedStateForNtnSignalStrengthReport.get()
+ != mIsModemEnabledReportingNtnSignalStrength.get()) {
+ logd("mLatestRequestedStateForNtnSignalStrengthReport does not match with "
+ + "mIsModemEnabledReportingNtnSignalStrength");
+ updateNtnSignalStrengthReporting(
+ mLatestRequestedStateForNtnSignalStrengthReport.get());
+ }
} else {
loge(((boolean) request.argument ? "startSendingNtnSignalStrength"
: "stopSendingNtnSignalStrength") + "returns " + errorCode);
@@ -1345,19 +1432,36 @@
case EVENT_SATELLITE_CAPABILITIES_CHANGED: {
ar = (AsyncResult) msg.obj;
if (ar.result == null) {
- loge("EVENT_SATELLITE_CAPABILITIES_CHANGED: result is null");
+ ploge("EVENT_SATELLITE_CAPABILITIES_CHANGED: result is null");
} else {
handleEventSatelliteCapabilitiesChanged((SatelliteCapabilities) ar.result);
}
break;
}
+ case EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: {
+ ar = (AsyncResult) msg.obj;
+ if (ar.result == null) {
+ ploge("EVENT_SATELLITE_SUPPORTED_STATE_CHANGED: result is null");
+ } else {
+ handleEventSatelliteSupportedStateChanged((boolean) ar.result);
+ }
+ break;
+ }
+
case EVENT_SATELLITE_CONFIG_DATA_UPDATED: {
handleEventConfigDataUpdated();
mSatelliteConfigUpdateChangedRegistrants.notifyRegistrants();
break;
}
+ case EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT: {
+ int phoneId = (int) msg.obj;
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ updateLastNotifiedNtnModeAndNotify(phone);
+ break;
+ }
+
default:
Log.w(TAG, "SatelliteControllerHandler: unexpected message code: " +
msg.what);
@@ -1373,7 +1477,7 @@
processNewCarrierConfigData(subId);
}
} else {
- loge("updateSupportedSatelliteServicesForActiveSubscriptions: "
+ ploge("updateSupportedSatelliteServicesForActiveSubscriptions: "
+ "activeSubIds is null");
}
}
@@ -1393,12 +1497,13 @@
* @param enableSatellite {@code true} to enable the satellite modem and
* {@code false} to disable.
* @param enableDemoMode {@code true} to enable demo mode and {@code false} to disable.
+ * @param isEmergency {@code true} to enable emergency mode, {@code false} otherwise.
* @param callback The callback to get the error code of the request.
*/
public void requestSatelliteEnabled(int subId, boolean enableSatellite, boolean enableDemoMode,
- @NonNull IIntegerConsumer callback) {
- logd("requestSatelliteEnabled subId: " + subId + " enableSatellite: " + enableSatellite
- + " enableDemoMode: " + enableDemoMode);
+ boolean isEmergency, @NonNull IIntegerConsumer callback) {
+ plogd("requestSatelliteEnabled subId: " + subId + " enableSatellite: " + enableSatellite
+ + " enableDemoMode: " + enableDemoMode + " isEmergency: " + isEmergency);
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) {
@@ -1407,11 +1512,13 @@
}
if (enableSatellite) {
- if (!mIsRadioOn) {
- loge("Radio is not on, can not enable satellite");
- sendErrorAndReportSessionMetrics(
- SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
- return;
+ synchronized (mIsRadioOnLock) {
+ if (!mIsRadioOn) {
+ ploge("Radio is not on, can not enable satellite");
+ sendErrorAndReportSessionMetrics(
+ SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE, result);
+ return;
+ }
}
} else {
/* if disable satellite, always assume demo is also disabled */
@@ -1422,13 +1529,13 @@
if (mIsSatelliteEnabled != null) {
if (mIsSatelliteEnabled == enableSatellite) {
if (enableDemoMode != mIsDemoModeEnabled) {
- loge("Received invalid demo mode while satellite session is enabled"
+ ploge("Received invalid demo mode while satellite session is enabled"
+ " enableDemoMode = " + enableDemoMode);
sendErrorAndReportSessionMetrics(
SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS, result);
return;
} else {
- logd("Enable request matches with current state"
+ plogd("Enable request matches with current state"
+ " enableSatellite = " + enableSatellite);
sendErrorAndReportSessionMetrics(
SatelliteManager.SATELLITE_RESULT_SUCCESS, result);
@@ -1439,7 +1546,8 @@
}
RequestSatelliteEnabledArgument request =
- new RequestSatelliteEnabledArgument(enableSatellite, enableDemoMode, result);
+ new RequestSatelliteEnabledArgument(enableSatellite, enableDemoMode, isEmergency,
+ result);
/**
* Multiple satellite enabled requests are handled as below:
* 1. If there are no ongoing requests, store current request in mSatelliteEnabledRequest
@@ -1454,14 +1562,14 @@
if (mSatelliteEnabledRequest == null) {
mSatelliteEnabledRequest = request;
} else if (mSatelliteEnabledRequest.enableSatellite == request.enableSatellite) {
- logd("requestSatelliteEnabled enableSatellite: " + enableSatellite
+ plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite
+ " is already in progress.");
sendErrorAndReportSessionMetrics(
SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS, result);
return;
} else if (mSatelliteEnabledRequest.enableSatellite == false
&& request.enableSatellite == true) {
- logd("requestSatelliteEnabled enableSatellite: " + enableSatellite + " cannot be "
+ plogd("requestSatelliteEnabled enableSatellite: " + enableSatellite + " cannot be "
+ "processed. Disable satellite is already in progress.");
sendErrorAndReportSessionMetrics(
SatelliteManager.SATELLITE_RESULT_ERROR, result);
@@ -1507,7 +1615,7 @@
*/
public boolean isSatelliteEnabled() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled");
+ plogd("isSatelliteEnabled: oemEnabledSatelliteFlag is disabled");
return false;
}
if (mIsSatelliteEnabled == null) return false;
@@ -1515,6 +1623,23 @@
}
/**
+ * Get whether satellite modem is being enabled.
+ *
+ * @return {@code true} if the satellite modem is being enabled and {@code false} otherwise.
+ */
+ public boolean isSatelliteBeingEnabled() {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ plogd("isSatelliteBeingEnabled: oemEnabledSatelliteFlag is disabled");
+ return false;
+ }
+
+ if (mSatelliteSessionController != null) {
+ return mSatelliteSessionController.isInEnablingState();
+ }
+ return false;
+ }
+
+ /**
* Request to get whether the satellite service demo mode is enabled.
*
* @param subId The subId of the subscription to check whether the satellite demo mode
@@ -1541,7 +1666,7 @@
*/
public boolean isDemoModeEnabled() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("isDemoModeEnabled: oemEnabledSatelliteFlag is disabled");
+ plogd("isDemoModeEnabled: oemEnabledSatelliteFlag is disabled");
return false;
}
return mIsDemoModeEnabled;
@@ -1556,7 +1681,7 @@
*/
public void requestIsSatelliteSupported(int subId, @NonNull ResultReceiver result) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("requestIsSatelliteSupported: oemEnabledSatelliteFlag is disabled");
+ plogd("requestIsSatelliteSupported: oemEnabledSatelliteFlag is disabled");
result.send(SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED, null);
return;
}
@@ -1565,6 +1690,7 @@
/* We have already successfully queried the satellite modem. */
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_SUPPORTED, mIsSatelliteSupported);
+ bundle.putInt(SATELLITE_SUBSCRIPTION_ID, subId);
result.send(SATELLITE_RESULT_SUCCESS, bundle);
return;
}
@@ -1768,7 +1894,7 @@
public void unregisterForSatelliteProvisionStateChanged(
int subId, @NonNull ISatelliteProvisionStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("unregisterForSatelliteProvisionStateChanged: "
+ plogd("unregisterForSatelliteProvisionStateChanged: "
+ "oemEnabledSatelliteFlag is disabled");
return;
}
@@ -1814,13 +1940,13 @@
@SatelliteManager.SatelliteResult public int registerForSatelliteModemStateChanged(int subId,
@NonNull ISatelliteModemStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
+ plogd("registerForSatelliteModemStateChanged: oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
if (mSatelliteSessionController != null) {
mSatelliteSessionController.registerForSatelliteModemStateChanged(callback);
} else {
- loge("registerForSatelliteModemStateChanged: mSatelliteSessionController"
+ ploge("registerForSatelliteModemStateChanged: mSatelliteSessionController"
+ " is not initialized yet");
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
}
@@ -1838,13 +1964,13 @@
public void unregisterForModemStateChanged(int subId,
@NonNull ISatelliteModemStateCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("unregisterForModemStateChanged: oemEnabledSatelliteFlag is disabled");
+ plogd("unregisterForModemStateChanged: oemEnabledSatelliteFlag is disabled");
return;
}
if (mSatelliteSessionController != null) {
mSatelliteSessionController.unregisterForSatelliteModemStateChanged(callback);
} else {
- loge("unregisterForModemStateChanged: mSatelliteSessionController"
+ ploge("unregisterForModemStateChanged: mSatelliteSessionController"
+ " is not initialized yet");
}
}
@@ -1860,13 +1986,13 @@
@SatelliteManager.SatelliteResult public int registerForIncomingDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("registerForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
+ plogd("registerForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
return SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED;
}
- logd("registerForIncomingDatagram: callback=" + callback);
+ plogd("registerForIncomingDatagram: callback=" + callback);
return mDatagramController.registerForSatelliteDatagram(subId, callback);
}
@@ -1881,13 +2007,13 @@
public void unregisterForIncomingDatagram(int subId,
@NonNull ISatelliteDatagramCallback callback) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("unregisterForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
+ plogd("unregisterForIncomingDatagram: oemEnabledSatelliteFlag is disabled");
return;
}
if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
return;
}
- logd("unregisterForIncomingDatagram: callback=" + callback);
+ plogd("unregisterForIncomingDatagram: callback=" + callback);
mDatagramController.unregisterForSatelliteDatagram(subId, callback);
}
@@ -1933,7 +2059,7 @@
public void sendDatagram(int subId, @SatelliteManager.DatagramType int datagramType,
SatelliteDatagram datagram, boolean needFullScreenPointingUI,
@NonNull IIntegerConsumer callback) {
- logd("sendSatelliteDatagram: subId: " + subId + " datagramType: " + datagramType
+ plogd("sendSatelliteDatagram: subId: " + subId + " datagramType: " + datagramType
+ " needFullScreenPointingUI: " + needFullScreenPointingUI);
Consumer<Integer> result = FunctionalUtils.ignoreRemoteException(callback::accept);
@@ -1947,7 +2073,9 @@
* TODO for NTN-based satellites: Check if satellite is acquired.
*/
if (mNeedsSatellitePointing) {
- mPointingAppController.startPointingUI(needFullScreenPointingUI);
+
+ mPointingAppController.startPointingUI(needFullScreenPointingUI, mIsDemoModeEnabled,
+ mIsEmergency);
}
final int validSubId = SatelliteServiceUtils.getValidSatelliteSubId(subId, mContext);
@@ -1956,26 +2084,6 @@
}
/**
- * Request to get whether satellite communication is allowed for the current location.
- *
- * @param subId The subId of the subscription to check whether satellite communication is
- * allowed for the current location for.
- * @param result The result receiver that returns whether satellite communication is allowed
- * for the current location if the request is successful or an error code
- * if the request failed.
- */
- public void requestIsSatelliteCommunicationAllowedForCurrentLocation(int subId,
- @NonNull ResultReceiver result) {
- int error = evaluateOemSatelliteRequestAllowed(false);
- if (error != SATELLITE_RESULT_SUCCESS) {
- result.send(error, null);
- return;
- }
-
- sendRequestAsync(CMD_IS_SATELLITE_COMMUNICATION_ALLOWED, result, null);
- }
-
- /**
* Request to get the time after which the satellite will be visible.
*
* @param subId The subId to get the time after which the satellite will be visible for.
@@ -2000,9 +2108,11 @@
*/
public void setDeviceAlignedWithSatellite(@NonNull int subId, @NonNull boolean isAligned) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled");
+ plogd("setDeviceAlignedWithSatellite: oemEnabledSatelliteFlag is disabled");
return;
}
+
+ DemoSimulator.getInstance().setDeviceAlignedWithSatellite(isAligned);
mDatagramController.setDeviceAlignedWithSatellite(isAligned);
}
@@ -2115,7 +2225,7 @@
* strength of the satellite connection.
*/
public void requestNtnSignalStrength(int subId, @NonNull ResultReceiver result) {
- if (DBG) logd("requestNtnSignalStrength()");
+ if (DBG) plogd("requestNtnSignalStrength()");
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) {
@@ -2154,7 +2264,7 @@
*/
public void registerForNtnSignalStrengthChanged(int subId,
@NonNull INtnSignalStrengthCallback callback) throws RemoteException {
- if (DBG) logd("registerForNtnSignalStrengthChanged()");
+ if (DBG) plogd("registerForNtnSignalStrengthChanged()");
int error = evaluateOemSatelliteRequestAllowed(true);
if (error == SATELLITE_RESULT_SUCCESS) {
@@ -2175,7 +2285,7 @@
*/
public void unregisterForNtnSignalStrengthChanged(
int subId, @NonNull INtnSignalStrengthCallback callback) {
- if (DBG) logd("unregisterForNtnSignalStrengthChanged()");
+ if (DBG) plogd("unregisterForNtnSignalStrengthChanged()");
int error = evaluateOemSatelliteRequestAllowed(true);
if (error == SATELLITE_RESULT_SUCCESS) {
@@ -2193,7 +2303,7 @@
*/
@SatelliteManager.SatelliteResult public int registerForCapabilitiesChanged(
int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
- if (DBG) logd("registerForCapabilitiesChanged()");
+ if (DBG) plogd("registerForCapabilitiesChanged()");
int error = evaluateOemSatelliteRequestAllowed(true);
if (error != SATELLITE_RESULT_SUCCESS) return error;
@@ -2213,7 +2323,7 @@
*/
public void unregisterForCapabilitiesChanged(
int subId, @NonNull ISatelliteCapabilitiesCallback callback) {
- if (DBG) logd("unregisterForCapabilitiesChanged()");
+ if (DBG) plogd("unregisterForCapabilitiesChanged()");
int error = evaluateOemSatelliteRequestAllowed(true);
if (error == SATELLITE_RESULT_SUCCESS) {
@@ -2222,6 +2332,43 @@
}
/**
+ * Registers for the satellite supported state changed.
+ *
+ * @param subId The subId of the subscription to register for supported state changed.
+ * @param callback The callback to handle the satellite supported state changed event.
+ *
+ * @return The {@link SatelliteManager.SatelliteResult} result of the operation.
+ */
+ @SatelliteManager.SatelliteResult public int registerForSatelliteSupportedStateChanged(
+ int subId, @NonNull ISatelliteSupportedStateCallback callback) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ plogd("registerForSatelliteSupportedStateChanged: oemEnabledSatelliteFlag is disabled");
+ return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
+ }
+
+ mSatelliteSupportedStateChangedListeners.put(callback.asBinder(), callback);
+ return SATELLITE_RESULT_SUCCESS;
+ }
+
+ /**
+ * Unregisters for the satellite supported state changed.
+ * If callback was not registered before, the request will be ignored.
+ *
+ * @param subId The subId of the subscription to unregister for supported state changed.
+ * @param callback The callback that was passed to
+ * {@link #registerForSatelliteSupportedStateChanged(int, ISatelliteSupportedStateCallback)}.
+ */
+ public void unregisterForSatelliteSupportedStateChanged(
+ int subId, @NonNull ISatelliteSupportedStateCallback callback) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ plogd("unregisterForSatelliteSupportedStateChanged: "
+ + "oemEnabledSatelliteFlag is disabled");
+ return;
+ }
+ mSatelliteSupportedStateChangedListeners.remove(callback.asBinder());
+ }
+
+ /**
* This API can be used by only CTS to update satellite vendor service package name.
*
* @param servicePackageName The package name of the satellite vendor service.
@@ -2230,16 +2377,16 @@
*/
public boolean setSatelliteServicePackageName(@Nullable String servicePackageName) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("setSatelliteServicePackageName: oemEnabledSatelliteFlag is disabled");
+ plogd("setSatelliteServicePackageName: oemEnabledSatelliteFlag is disabled");
return false;
}
if (!isMockModemAllowed()) {
- logd("setSatelliteServicePackageName: mock modem not allowed");
+ plogd("setSatelliteServicePackageName: mock modem not allowed");
return false;
}
// Cached states need to be cleared whenever switching satellite vendor services.
- logd("setSatelliteServicePackageName: Resetting cached states");
+ plogd("setSatelliteServicePackageName: Resetting cached states");
synchronized (mIsSatelliteSupportedLock) {
mIsSatelliteSupported = null;
}
@@ -2266,11 +2413,11 @@
*/
public boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("setSatelliteListeningTimeoutDuration: oemEnabledSatelliteFlag is disabled");
+ plogd("setSatelliteListeningTimeoutDuration: oemEnabledSatelliteFlag is disabled");
return false;
}
if (mSatelliteSessionController == null) {
- loge("mSatelliteSessionController is not initialized yet");
+ ploge("mSatelliteSessionController is not initialized yet");
return false;
}
return mSatelliteSessionController.setSatelliteListeningTimeoutDuration(timeoutMillis);
@@ -2286,16 +2433,35 @@
public boolean setDatagramControllerTimeoutDuration(
boolean reset, int timeoutType, long timeoutMillis) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("setDatagramControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
+ plogd("setDatagramControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
return false;
}
- logd("setDatagramControllerTimeoutDuration: reset=" + reset + ", timeoutType="
+ plogd("setDatagramControllerTimeoutDuration: reset=" + reset + ", timeoutType="
+ timeoutType + ", timeoutMillis=" + timeoutMillis);
return mDatagramController.setDatagramControllerTimeoutDuration(
reset, timeoutType, timeoutMillis);
}
/**
+ * This API can be used by only CTS to override the boolean configs used by the
+ * DatagramController module.
+ *
+ * @param enable Whether to enable or disable boolean config.
+ * @return {@code true} if the boolean config is set successfully, {@code false} otherwise.
+ */
+ public boolean setDatagramControllerBooleanConfig(
+ boolean reset, int booleanType, boolean enable) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ logd("setDatagramControllerBooleanConfig: oemEnabledSatelliteFlag is disabled");
+ return false;
+ }
+ logd("setDatagramControllerBooleanConfig: reset=" + reset + ", booleanType="
+ + booleanType + ", enable=" + enable);
+ return mDatagramController.setDatagramControllerBooleanConfig(
+ reset, booleanType, enable);
+ }
+
+ /**
* This API can be used by only CTS to override timeout durations used by SatelliteController
* module.
*
@@ -2305,14 +2471,14 @@
public boolean setSatelliteControllerTimeoutDuration(
boolean reset, int timeoutType, long timeoutMillis) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("setSatelliteControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
+ plogd("setSatelliteControllerTimeoutDuration: oemEnabledSatelliteFlag is disabled");
return false;
}
if (!isMockModemAllowed()) {
- logd("setSatelliteControllerTimeoutDuration: mock modem is not allowed");
+ plogd("setSatelliteControllerTimeoutDuration: mock modem is not allowed");
return false;
}
- logd("setSatelliteControllerTimeoutDuration: reset=" + reset + ", timeoutType="
+ plogd("setSatelliteControllerTimeoutDuration: reset=" + reset + ", timeoutType="
+ timeoutType + ", timeoutMillis=" + timeoutMillis);
if (timeoutType == TIMEOUT_TYPE_WAIT_FOR_SATELLITE_ENABLING_RESPONSE) {
if (reset) {
@@ -2321,9 +2487,23 @@
} else {
mWaitTimeForSatelliteEnablingResponse = timeoutMillis;
}
- logd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse);
+ plogd("mWaitTimeForSatelliteEnablingResponse=" + mWaitTimeForSatelliteEnablingResponse);
+ } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_ALIGNED_DURATION_MILLIS) {
+ if (reset) {
+ mDemoPointingAlignedDurationMillis =
+ getDemoPointingAlignedDurationMillisFromResources();
+ } else {
+ mDemoPointingAlignedDurationMillis = timeoutMillis;
+ }
+ } else if (timeoutType == TIMEOUT_TYPE_DEMO_POINTING_NOT_ALIGNED_DURATION_MILLIS) {
+ if (reset) {
+ mDemoPointingNotAlignedDurationMillis =
+ getDemoPointingNotAlignedDurationMillisFromResources();
+ } else {
+ mDemoPointingNotAlignedDurationMillis = timeoutMillis;
+ }
} else {
- logw("Invalid timeoutType=" + timeoutType);
+ plogw("Invalid timeoutType=" + timeoutType);
return false;
}
return true;
@@ -2338,11 +2518,11 @@
*/
public boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("setSatelliteGatewayServicePackageName: oemEnabledSatelliteFlag is disabled");
+ plogd("setSatelliteGatewayServicePackageName: oemEnabledSatelliteFlag is disabled");
return false;
}
if (mSatelliteSessionController == null) {
- loge("mSatelliteSessionController is not initialized yet");
+ ploge("mSatelliteSessionController is not initialized yet");
return false;
}
return mSatelliteSessionController.setSatelliteGatewayServicePackageName(
@@ -2360,7 +2540,7 @@
public boolean setSatellitePointingUiClassName(
@Nullable String packageName, @Nullable String className) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("setSatellitePointingUiClassName: oemEnabledSatelliteFlag is disabled");
+ plogd("setSatellitePointingUiClassName: oemEnabledSatelliteFlag is disabled");
return false;
}
return mPointingAppController.setSatellitePointingUiClassName(packageName, className);
@@ -2381,7 +2561,7 @@
*/
public boolean setEmergencyCallToSatelliteHandoverType(int handoverType, int delaySeconds) {
if (!isMockModemAllowed()) {
- loge("setEmergencyCallToSatelliteHandoverType: mock modem not allowed");
+ ploge("setEmergencyCallToSatelliteHandoverType: mock modem not allowed");
return false;
}
if (isHandoverTypeValid(handoverType)) {
@@ -2405,7 +2585,7 @@
*/
public boolean setOemEnabledSatelliteProvisionStatus(boolean reset, boolean isProvisioned) {
if (!isMockModemAllowed()) {
- loge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed");
+ ploge("setOemEnabledSatelliteProvisionStatus: mock modem not allowed");
return false;
}
synchronized (mSatelliteViaOemProvisionLock) {
@@ -2450,7 +2630,7 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void onSatelliteServiceConnected() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("onSatelliteServiceConnected: oemEnabledSatelliteFlag is disabled");
+ plogd("onSatelliteServiceConnected: oemEnabledSatelliteFlag is disabled");
return;
}
if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
@@ -2460,7 +2640,7 @@
@Override
protected void onReceiveResult(
int resultCode, Bundle resultData) {
- logd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
+ plogd("onSatelliteServiceConnected.requestIsSatelliteSupported:"
+ " resultCode=" + resultCode);
}
};
@@ -2469,7 +2649,7 @@
}
}
} else {
- logd("onSatelliteServiceConnected: Satellite vendor service is not supported."
+ plogd("onSatelliteServiceConnected: Satellite vendor service is not supported."
+ " Ignored the event");
}
}
@@ -2480,18 +2660,21 @@
* modem. {@link SatelliteController} will then power off the satellite modem.
*/
public void onCellularRadioPowerOffRequested() {
+ logd("onCellularRadioPowerOffRequested()");
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("onCellularRadioPowerOffRequested: oemEnabledSatelliteFlag is disabled");
+ plogd("onCellularRadioPowerOffRequested: oemEnabledSatelliteFlag is disabled");
return;
}
- mIsRadioOn = false;
+ synchronized (mIsRadioOnLock) {
+ mIsRadioOn = false;
+ }
requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- false /* enableSatellite */, false /* enableDemoMode */,
+ false /* enableSatellite */, false /* enableDemoMode */, false /* isEmergency */,
new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
- logd("onRadioPowerOffRequested: requestSatelliteEnabled result=" + result);
+ plogd("onRadioPowerOffRequested: requestSatelliteEnabled result=" + result);
}
});
}
@@ -2502,7 +2685,7 @@
*/
public boolean isSatelliteSupportedViaOem() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("isSatelliteSupported: oemEnabledSatelliteFlag is disabled");
+ plogd("isSatelliteSupported: oemEnabledSatelliteFlag is disabled");
return false;
}
Boolean supported = isSatelliteSupportedViaOemInternal();
@@ -2519,6 +2702,12 @@
logd("getSatellitePlmnsForCarrier: carrierEnabledSatelliteFlag is disabled");
return new ArrayList<>();
}
+
+ if (!isSatelliteSupportedViaCarrier(subId)) {
+ logd("Satellite for carrier is not supported.");
+ return new ArrayList<>();
+ }
+
synchronized (mSupportedSatelliteServicesLock) {
return mMergedPlmnListPerCarrier.get(subId, new ArrayList<>()).stream().toList();
}
@@ -2550,7 +2739,22 @@
loge("getSupportedSatelliteServices: mSatelliteServicesSupportedByCarriers does "
+ "not contain key subId=" + subId);
}
- return new ArrayList<>();
+
+ /* Returns default capabilities when carrier config does not contain service
+ capabilities for the given plmn */
+ PersistableBundle config = getPersistableBundle(subId);
+ int [] defaultCapabilities = config.getIntArray(
+ KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY);
+ if (defaultCapabilities == null) {
+ logd("getSupportedSatelliteServices: defaultCapabilities is null");
+ return new ArrayList<>();
+ }
+ List<Integer> capabilitiesList = Arrays.stream(
+ defaultCapabilities).boxed().collect(Collectors.toList());
+ logd("getSupportedSatelliteServices: subId=" + subId
+ + ", supportedServices does not contain key plmn=" + plmn
+ + ", return default values " + capabilitiesList);
+ return capabilitiesList;
}
}
@@ -2562,13 +2766,13 @@
*/
public boolean isSatelliteAttachRequired() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("isSatelliteAttachRequired: oemEnabledSatelliteFlag is disabled");
+ plogd("isSatelliteAttachRequired: oemEnabledSatelliteFlag is disabled");
return false;
}
synchronized (mSatelliteCapabilitiesLock) {
if (mSatelliteCapabilities == null) {
- loge("isSatelliteAttachRequired: mSatelliteCapabilities is null");
+ ploge("isSatelliteAttachRequired: mSatelliteCapabilities is null");
return false;
}
if (mSatelliteCapabilities.getSupportedRadioTechnologies().contains(
@@ -2597,6 +2801,32 @@
}
/**
+ * @return {@code true} if satellite emergency messaging is supported via carrier by any
+ * subscription on the device, {@code false} otherwise.
+ */
+ public boolean isSatelliteEmergencyMessagingSupportedViaCarrier() {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("isSatelliteEmergencyMessagingSupportedViaCarrier: carrierEnabledSatelliteFlag is"
+ + " disabled");
+ return false;
+ }
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (isSatelliteEmergencyMessagingSupportedViaCarrier(phone.getSubId())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isSatelliteEmergencyMessagingSupportedViaCarrier(int subId) {
+ if (!isSatelliteSupportedViaCarrier(subId)) {
+ return false;
+ }
+ PersistableBundle config = getPersistableBundle(subId);
+ return config.getBoolean(KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL);
+ }
+
+ /**
* @return {@code Pair<true, subscription ID>} if any subscription on the device is connected to
* satellite, {@code Pair<false, null>} otherwise.
*/
@@ -2629,39 +2859,170 @@
return true;
}
for (Phone phone : PhoneFactory.getPhones()) {
- if (isSatelliteSupportedViaCarrier(phone.getSubId())) {
- synchronized (mSatelliteConnectedLock) {
- Boolean isHysteresisTimeExpired =
- mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.get(
- phone.getSubId());
- if (isHysteresisTimeExpired != null && isHysteresisTimeExpired) {
- continue;
- }
-
- Long lastDisconnectedTime =
- mLastSatelliteDisconnectedTimesMillis.get(phone.getSubId());
- long satelliteConnectionHysteresisTime =
- getSatelliteConnectionHysteresisTimeMillis(phone.getSubId());
- if (lastDisconnectedTime != null
- && (getElapsedRealtime() - lastDisconnectedTime)
- <= satelliteConnectionHysteresisTime) {
- return true;
- } else {
- mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.put(
- phone.getSubId(), true);
- }
- }
+ if (isInSatelliteModeForCarrierRoaming(phone)) {
+ logd("isSatelliteConnectedViaCarrierWithinHysteresisTime: "
+ + "subId:" + phone.getSubId()
+ + " is connected to satellite within hysteresis time");
+ return true;
}
}
return false;
}
+ /**
+ * Get whether device is connected to satellite via carrier.
+ *
+ * @param phone phone object
+ * @return {@code true} if the device is connected to satellite using the phone within the
+ * {@link CarrierConfigManager#KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT}
+ * duration, {@code false} otherwise.
+ */
+ public boolean isInSatelliteModeForCarrierRoaming(@Nullable Phone phone) {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("isInSatelliteModeForCarrierRoaming: carrierEnabledSatelliteFlag is disabled");
+ return false;
+ }
+
+ if (phone == null) {
+ return false;
+ }
+
+ int subId = phone.getSubId();
+ if (!isSatelliteSupportedViaCarrier(subId)) {
+ return false;
+ }
+
+ ServiceState serviceState = phone.getServiceState();
+ if (serviceState == null) {
+ return false;
+ }
+
+ if (serviceState.isUsingNonTerrestrialNetwork()) {
+ return true;
+ }
+
+ if (getWwanIsInService(serviceState)) {
+ // Device is connected to terrestrial network which has coverage
+ resetCarrierRoamingSatelliteModeParams(subId);
+ return false;
+ }
+
+ synchronized (mSatelliteConnectedLock) {
+ Long lastDisconnectedTime = mLastSatelliteDisconnectedTimesMillis.get(subId);
+ long satelliteConnectionHysteresisTime =
+ getSatelliteConnectionHysteresisTimeMillis(subId);
+ if (lastDisconnectedTime != null
+ && (getElapsedRealtime() - lastDisconnectedTime)
+ <= satelliteConnectionHysteresisTime) {
+ logd("isInSatelliteModeForCarrierRoaming: " + "subId:" + subId
+ + " is connected to satellite within hysteresis time");
+ return true;
+ } else {
+ resetCarrierRoamingSatelliteModeParams(subId);
+ return false;
+ }
+ }
+ }
+
+ /**
+ * Return capabilities of carrier roaming satellite network.
+ *
+ * @param phone phone object
+ * @return The list of services supported by the carrier associated with the {@code subId}
+ */
+ @NonNull
+ public List<Integer> getCapabilitiesForCarrierRoamingSatelliteMode(Phone phone) {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("getCapabilitiesForCarrierRoamingSatelliteMode: carrierEnabledSatelliteFlag"
+ + " is disabled");
+ return new ArrayList<>();
+ }
+
+ synchronized (mSatelliteConnectedLock) {
+ int subId = phone.getSubId();
+ if (mSatModeCapabilitiesForCarrierRoaming.containsKey(subId)) {
+ return mSatModeCapabilitiesForCarrierRoaming.get(subId);
+ }
+ }
+
+ return new ArrayList<>();
+ }
+
+ /**
+ * Request to get the {@link SatelliteSessionStats} of the satellite service.
+ *
+ * @param subId The subId of the subscription to the satellite session stats for.
+ * @param result The result receiver that returns the {@link SatelliteSessionStats}
+ * if the request is successful or an error code if the request failed.
+ */
+ public void requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ return;
+ }
+ mSessionMetricsStats.requestSatelliteSessionStats(subId, result);
+ }
+
+ /**
+ * Get the carrier-enabled emergency call wait for connection timeout millis
+ */
+ public long getCarrierEmergencyCallWaitForConnectionTimeoutMillis() {
+ long maxTimeoutMillis = 0;
+ for (Phone phone : PhoneFactory.getPhones()) {
+ if (!isSatelliteEmergencyMessagingSupportedViaCarrier(phone.getSubId())) {
+ continue;
+ }
+
+ int timeoutMillis =
+ getCarrierEmergencyCallWaitForConnectionTimeoutMillis(phone.getSubId());
+ // Prioritize getting the timeout duration from the phone that is in satellite mode
+ // with carrier roaming
+ if (isInSatelliteModeForCarrierRoaming(phone)) {
+ return timeoutMillis;
+ }
+ if (maxTimeoutMillis < timeoutMillis) {
+ maxTimeoutMillis = timeoutMillis;
+ }
+ }
+ if (maxTimeoutMillis != 0) {
+ return maxTimeoutMillis;
+ }
+ return DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS;
+ }
+
+ private int getCarrierEmergencyCallWaitForConnectionTimeoutMillis(int subId) {
+ PersistableBundle config = getPersistableBundle(subId);
+ return config.getInt(KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT);
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected long getElapsedRealtime() {
return SystemClock.elapsedRealtime();
}
/**
+ * Register the handler for SIM Refresh notifications.
+ * @param handler Handler for notification message.
+ * @param what User-defined message code.
+ */
+ public void registerIccRefresh(Handler handler, int what) {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ CommandsInterface ci = phone.mCi;
+ ci.registerForIccRefresh(handler, what, null);
+ }
+ }
+
+ /**
+ * Unregister the handler for SIM Refresh notifications.
+ * @param handler Handler for notification message.
+ */
+ public void unRegisterIccRefresh(Handler handler) {
+ for (Phone phone : PhoneFactory.getPhones()) {
+ CommandsInterface ci = phone.mCi;
+ ci.unregisterForIccRefresh(handler);
+ }
+ }
+
+ /**
* To use the satellite service, update the EntitlementStatus and the PlmnAllowedList after
* receiving the satellite configuration from the entitlement server. If satellite
* entitlement is enabled, enable satellite for the carrier. Otherwise, disable satellite.
@@ -2669,11 +3030,14 @@
* @param subId subId
* @param entitlementEnabled {@code true} Satellite service enabled
* @param allowedPlmnList plmn allowed list to use the satellite service
+ * @param barredPlmnList plmn barred list to pass the modem
* @param callback callback for accept
*/
public void onSatelliteEntitlementStatusUpdated(int subId, boolean entitlementEnabled,
- List<String> allowedPlmnList, @Nullable IIntegerConsumer callback) {
+ @Nullable List<String> allowedPlmnList, @Nullable List<String> barredPlmnList,
+ @Nullable IIntegerConsumer callback) {
if (!mFeatureFlags.carrierEnabledSatelliteFlag()) {
+ logd("onSatelliteEntitlementStatusUpdated: carrierEnabledSatelliteFlag is not enabled");
return;
}
@@ -2685,9 +3049,16 @@
}
};
}
- logd("onSatelliteEntitlementStatusUpdated subId=" + subId + " , entitlementEnabled="
- + entitlementEnabled + ", allowedPlmnList=" + (Objects.equals(null, allowedPlmnList)
- ? "" : allowedPlmnList + ""));
+ if (allowedPlmnList == null) {
+ allowedPlmnList = new ArrayList<>();
+ }
+ if (barredPlmnList == null) {
+ barredPlmnList = new ArrayList<>();
+ }
+ logd("onSatelliteEntitlementStatusUpdated subId=" + subId + ", entitlementEnabled="
+ + entitlementEnabled + ", allowedPlmnList=["
+ + String.join(",", allowedPlmnList) + "]" + ", barredPlmnList=["
+ + String.join(",", barredPlmnList) + "]");
synchronized (mSupportedSatelliteServicesLock) {
if (mSatelliteEntitlementStatusPerCarrier.get(subId, false) != entitlementEnabled) {
@@ -2700,12 +3071,18 @@
loge("onSatelliteEntitlementStatusUpdated: setSubscriptionProperty, e=" + e);
}
}
- mMergedPlmnListPerCarrier.remove(subId);
- mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList);
- updatePlmnListPerCarrier(subId);
- configureSatellitePlmnForCarrier(subId);
- mSubscriptionManagerService.setSatelliteEntitlementPlmnList(subId, allowedPlmnList);
+ if (isValidPlmnList(allowedPlmnList) && isValidPlmnList(barredPlmnList)) {
+ mMergedPlmnListPerCarrier.remove(subId);
+ mEntitlementPlmnListPerCarrier.put(subId, allowedPlmnList);
+ mEntitlementBarredPlmnListPerCarrier.put(subId, barredPlmnList);
+ updatePlmnListPerCarrier(subId);
+ configureSatellitePlmnForCarrier(subId);
+ mSubscriptionManagerService.setSatelliteEntitlementPlmnList(subId, allowedPlmnList);
+ } else {
+ loge("onSatelliteEntitlementStatusUpdated: either invalid allowedPlmnList "
+ + "or invalid barredPlmnList");
+ }
if (mSatelliteEntitlementStatusPerCarrier.get(subId, false)) {
removeAttachRestrictionForCarrier(subId,
@@ -2718,6 +3095,20 @@
}
/**
+ * A list of PLMNs is considered valid if either the list is empty or all PLMNs in the list
+ * are valid.
+ */
+ private boolean isValidPlmnList(@NonNull List<String> plmnList) {
+ for (String plmn : plmnList) {
+ if (!TelephonyUtils.isValidPlmn(plmn)) {
+ ploge("Invalid PLMN = " + plmn);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* If we have not successfully queried the satellite modem for its satellite service support,
* we will retry the query one more time. Otherwise, we will return the cached result.
*/
@@ -2736,7 +3127,7 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:"
+ plogd("isSatelliteSupportedViaOemInternal.requestIsSatelliteSupported:"
+ " resultCode=" + resultCode);
}
});
@@ -2746,12 +3137,12 @@
private void handleEventProvisionSatelliteServiceDone(
@NonNull ProvisionSatelliteServiceArgument arg,
@SatelliteManager.SatelliteResult int result) {
- logd("handleEventProvisionSatelliteServiceDone: result="
+ plogd("handleEventProvisionSatelliteServiceDone: result="
+ result + ", subId=" + arg.subId);
Consumer<Integer> callback = mSatelliteProvisionCallbacks.remove(arg.subId);
if (callback == null) {
- loge("handleEventProvisionSatelliteServiceDone: callback is null for subId="
+ ploge("handleEventProvisionSatelliteServiceDone: callback is null for subId="
+ arg.subId);
mProvisionMetricsStats
.setResultCode(SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE)
@@ -2772,16 +3163,20 @@
} else {
callback.accept(result);
}
+ mProvisionMetricsStats.setResultCode(result)
+ .setIsProvisionRequest(true)
+ .reportProvisionMetrics();
+ mControllerMetricsStats.reportProvisionCount(result);
}
private void handleEventDeprovisionSatelliteServiceDone(
@NonNull ProvisionSatelliteServiceArgument arg,
@SatelliteManager.SatelliteResult int result) {
if (arg == null) {
- loge("handleEventDeprovisionSatelliteServiceDone: arg is null");
+ ploge("handleEventDeprovisionSatelliteServiceDone: arg is null");
return;
}
- logd("handleEventDeprovisionSatelliteServiceDone: result="
+ plogd("handleEventDeprovisionSatelliteServiceDone: result="
+ result + ", subId=" + arg.subId);
if (result == SATELLITE_RESULT_SUCCESS
@@ -2889,7 +3284,7 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("isSatelliteViaOemProvisioned: resultCode=" + resultCode);
+ plogd("isSatelliteViaOemProvisioned: resultCode=" + resultCode);
}
});
return null;
@@ -2898,6 +3293,13 @@
private void handleSatelliteEnabled(SatelliteControllerHandlerRequest request) {
RequestSatelliteEnabledArgument argument =
(RequestSatelliteEnabledArgument) request.argument;
+ handlePersistentLoggingOnSessionStart(argument);
+ if (mSatelliteSessionController != null) {
+ mSatelliteSessionController.onSatelliteEnablementStarted(argument.enableSatellite);
+ } else {
+ ploge("handleSatelliteEnabled: mSatelliteSessionController is not initialized yet");
+ }
+
if (!argument.enableSatellite && mSatelliteModemInterface.isSatelliteServiceSupported()) {
synchronized (mIsSatelliteEnabledLock) {
mWaitingForDisableSatelliteModemResponse = true;
@@ -2907,8 +3309,13 @@
Message onCompleted = obtainMessage(EVENT_SET_SATELLITE_ENABLED_DONE, request);
mSatelliteModemInterface.requestSatelliteEnabled(argument.enableSatellite,
- argument.enableDemoMode, onCompleted);
+ argument.enableDemoMode, argument.isEmergency, onCompleted);
startWaitForSatelliteEnablingResponseTimer(argument);
+ // Logs satellite session timestamps for session metrics
+ if (argument.enableSatellite) {
+ mSessionStartTimeStamp = System.currentTimeMillis();
+ }
+ mSessionProcessingTimeStamp = System.currentTimeMillis();
}
private void handleRequestSatelliteAttachRestrictionForCarrierCmd(
@@ -2931,7 +3338,10 @@
mIsSatelliteSupported = supported;
}
mSatelliteSessionController = SatelliteSessionController.make(
- mContext, getLooper(), supported);
+ mContext, getLooper(), mFeatureFlags, supported);
+ plogd("create a new SatelliteSessionController due to isSatelliteSupported state has "
+ + "changed to " + supported);
+
if (supported) {
registerForSatelliteProvisionStateChanged();
registerForPendingDatagramCount();
@@ -2943,14 +3353,14 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("requestIsSatelliteProvisioned: resultCode=" + resultCode
+ plogd("requestIsSatelliteProvisioned: resultCode=" + resultCode
+ ", resultData=" + resultData);
requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
- false, false,
+ false, false, false,
new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
- logd("requestSatelliteEnabled: result=" + result);
+ plogd("requestSatelliteEnabled: result=" + result);
}
});
}
@@ -2959,11 +3369,12 @@
new ResultReceiver(this) {
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
- logd("requestSatelliteCapabilities: resultCode=" + resultCode
+ plogd("requestSatelliteCapabilities: resultCode=" + resultCode
+ ", resultData=" + resultData);
}
});
}
+ registerForSatelliteSupportedStateChanged();
}
private void updateSatelliteEnabledState(boolean enabled, String caller) {
@@ -2974,7 +3385,10 @@
mSatelliteSessionController.onSatelliteEnabledStateChanged(enabled);
mSatelliteSessionController.setDemoMode(mIsDemoModeEnabled);
} else {
- loge(caller + ": mSatelliteSessionController is not initialized yet");
+ ploge(caller + ": mSatelliteSessionController is not initialized yet");
+ }
+ if (!enabled) {
+ mIsModemEnabledReportingNtnSignalStrength.set(false);
}
}
@@ -3010,7 +3424,7 @@
private void registerForNtnSignalStrengthChanged() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("registerForNtnSignalStrengthChanged: oemEnabledSatelliteFlag is disabled");
+ plogd("registerForNtnSignalStrengthChanged: oemEnabledSatelliteFlag is disabled");
return;
}
@@ -3025,7 +3439,7 @@
private void registerForCapabilitiesChanged() {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("registerForCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
+ plogd("registerForCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
return;
}
@@ -3038,8 +3452,18 @@
}
}
+ private void registerForSatelliteSupportedStateChanged() {
+ if (mSatelliteModemInterface.isSatelliteServiceSupported()) {
+ if (!mRegisteredForSatelliteSupportedStateChanged.get()) {
+ mSatelliteModemInterface.registerForSatelliteSupportedStateChanged(
+ this, EVENT_SATELLITE_SUPPORTED_STATE_CHANGED, null);
+ mRegisteredForSatelliteSupportedStateChanged.set(true);
+ }
+ }
+ }
+
private void handleEventSatelliteProvisionStateChanged(boolean provisioned) {
- logd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
+ plogd("handleSatelliteProvisionStateChangedEvent: provisioned=" + provisioned);
synchronized (mSatelliteViaOemProvisionLock) {
persistOemEnabledSatelliteProvisionStatus(provisioned);
@@ -3051,7 +3475,7 @@
try {
listener.onSatelliteProvisionStateChanged(provisioned);
} catch (RemoteException e) {
- logd("handleSatelliteProvisionStateChangedEvent RemoteException: " + e);
+ plogd("handleSatelliteProvisionStateChangedEvent RemoteException: " + e);
deadCallersList.add(listener);
}
});
@@ -3062,7 +3486,7 @@
private void handleEventSatelliteModemStateChanged(
@SatelliteManager.SatelliteModemState int state) {
- logd("handleEventSatelliteModemStateChanged: state=" + state);
+ plogd("handleEventSatelliteModemStateChanged: state=" + state);
if (state == SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE
|| state == SatelliteManager.SATELLITE_MODEM_STATE_OFF) {
synchronized (mIsSatelliteEnabledLock) {
@@ -3080,8 +3504,8 @@
}
moveSatelliteToOffStateAndCleanUpResources(error, callback);
} else {
- logd("Either waiting for the response of disabling satellite modem or the event"
- + " should be ignored because isSatelliteEnabled="
+ plogd("Either waiting for the response of disabling satellite modem or the"
+ + " event should be ignored because isSatelliteEnabled="
+ isSatelliteEnabled()
+ ", mIsSatelliteEnabled=" + mIsSatelliteEnabled);
}
@@ -3091,7 +3515,7 @@
if (mSatelliteSessionController != null) {
mSatelliteSessionController.onSatelliteModemStateChanged(state);
} else {
- loge("handleEventSatelliteModemStateChanged: mSatelliteSessionController is null");
+ ploge("handleEventSatelliteModemStateChanged: mSatelliteSessionController is null");
}
}
}
@@ -3106,13 +3530,14 @@
synchronized (mNtnSignalsStrengthLock) {
mNtnSignalStrength = ntnSignalStrength;
}
+ mSessionMetricsStats.updateMaxNtnSignalStrengthLevel(ntnSignalStrength.getLevel());
List<INtnSignalStrengthCallback> deadCallersList = new ArrayList<>();
mNtnSignalStrengthChangedListeners.values().forEach(listener -> {
try {
listener.onNtnSignalStrengthChanged(ntnSignalStrength);
} catch (RemoteException e) {
- logd("handleEventNtnSignalStrengthChanged RemoteException: " + e);
+ plogd("handleEventNtnSignalStrengthChanged RemoteException: " + e);
deadCallersList.add(listener);
}
});
@@ -3122,9 +3547,9 @@
}
private void handleEventSatelliteCapabilitiesChanged(SatelliteCapabilities capabilities) {
- logd("handleEventSatelliteCapabilitiesChanged()");
+ plogd("handleEventSatelliteCapabilitiesChanged()");
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("handleEventSatelliteCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
+ plogd("handleEventSatelliteCapabilitiesChanged: oemEnabledSatelliteFlag is disabled");
return;
}
@@ -3137,7 +3562,7 @@
try {
listener.onSatelliteCapabilitiesChanged(capabilities);
} catch (RemoteException e) {
- logd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e);
+ plogd("handleEventSatelliteCapabilitiesChanged RemoteException: " + e);
deadCallersList.add(listener);
}
});
@@ -3146,13 +3571,167 @@
});
}
+ private void handleEventSatelliteSupportedStateChanged(boolean supported) {
+ plogd("handleSatelliteSupportedStateChangedEvent: supported=" + supported);
+
+ synchronized (mIsSatelliteSupportedLock) {
+ if (mIsSatelliteSupported != null && mIsSatelliteSupported == supported) {
+ if (DBG) {
+ plogd("current satellite support state and new supported state are matched,"
+ + " ignore update.");
+ }
+ return;
+ }
+
+ updateSatelliteSupportedStateWhenSatelliteServiceConnected(supported);
+
+ /* In case satellite has been reported as not support from modem, but satellite is
+ enabled, request disable satellite. */
+ synchronized (mIsSatelliteEnabledLock) {
+ if (!supported && mIsSatelliteEnabled != null && mIsSatelliteEnabled) {
+ plogd("Invoke requestSatelliteEnabled(), supported=false, "
+ + "mIsSatelliteEnabled=true");
+ requestSatelliteEnabled(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ false /* enableSatellite */, false /* enableDemoMode */,
+ false /* isEmergency */,
+ new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ plogd("handleSatelliteSupportedStateChangedEvent: request "
+ + "satellite disable, result="
+ + result);
+ }
+ });
+
+ }
+ }
+ mIsSatelliteSupported = supported;
+ }
+
+ List<ISatelliteSupportedStateCallback> deadCallersList = new ArrayList<>();
+ mSatelliteSupportedStateChangedListeners.values().forEach(listener -> {
+ try {
+ listener.onSatelliteSupportedStateChanged(supported);
+ } catch (RemoteException e) {
+ plogd("handleSatelliteSupportedStateChangedEvent RemoteException: " + e);
+ deadCallersList.add(listener);
+ }
+ });
+ deadCallersList.forEach(listener -> {
+ mSatelliteSupportedStateChangedListeners.remove(listener.asBinder());
+ });
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected void setSettingsKeyForSatelliteMode(int val) {
- logd("setSettingsKeyForSatelliteMode val: " + val);
+ plogd("setSettingsKeyForSatelliteMode val: " + val);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.SATELLITE_MODE_ENABLED, val);
}
+ /**
+ * Allow screen rotation temporary in rotation locked foldable device.
+ * <p>
+ * Temporarily allow screen rotation user to catch satellite signals properly by UI guide in
+ * emergency situations. Unlock the setting value so that the screen rotation is not locked, and
+ * return it to the original value when the satellite service is finished.
+ * <p>
+ * Note that, only the unfolded screen will be temporarily allowed screen rotation.
+ *
+ * @param val {@link SATELLITE_MODE_ENABLED_TRUE} if satellite mode is enabled,
+ * {@link SATELLITE_MODE_ENABLED_FALSE} satellite mode is not enabled.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+ protected void setSettingsKeyToAllowDeviceRotation(int val) {
+ // Only allows on a foldable device type.
+ if (!isFoldable(mContext)) {
+ return;
+ }
+
+ switch (val) {
+ case SATELLITE_MODE_ENABLED_TRUE:
+ mDeviceRotationLockToBackupAndRestore =
+ Settings.Secure.getString(mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK);
+ String unlockedRotationSettings = replaceDeviceRotationValue(
+ mDeviceRotationLockToBackupAndRestore == null
+ ? "" : mDeviceRotationLockToBackupAndRestore,
+ Settings.Secure.DEVICE_STATE_ROTATION_KEY_UNFOLDED,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK_UNLOCKED);
+ Settings.Secure.putString(mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK, unlockedRotationSettings);
+ logd("setSettingsKeyToAllowDeviceRotation(TRUE), RotationSettings is changed"
+ + " from " + mDeviceRotationLockToBackupAndRestore
+ + " to " + unlockedRotationSettings);
+ break;
+ case SATELLITE_MODE_ENABLED_FALSE:
+ if (mDeviceRotationLockToBackupAndRestore == null) {
+ break;
+ }
+ Settings.Secure.putString(mContentResolver,
+ Settings.Secure.DEVICE_STATE_ROTATION_LOCK,
+ mDeviceRotationLockToBackupAndRestore);
+ logd("setSettingsKeyToAllowDeviceRotation(FALSE), RotationSettings is restored to"
+ + mDeviceRotationLockToBackupAndRestore);
+ mDeviceRotationLockToBackupAndRestore = "";
+ break;
+ default:
+ loge("setSettingsKeyToAllowDeviceRotation(" + val + "), never reach here.");
+ break;
+ }
+ }
+
+ /**
+ * If the device type is foldable.
+ *
+ * @param context context
+ * @return {@code true} if device type is foldable. {@code false} for otherwise.
+ */
+ private boolean isFoldable(Context context) {
+ return context.getResources().getIntArray(R.array.config_foldedDeviceStates).length > 0;
+ }
+
+ /**
+ * Replaces a value of given a target key with a new value in a string of key-value pairs.
+ * <p>
+ * Replaces the value corresponding to the target key with a new value. If the key value is not
+ * found in the device rotation information, it is not replaced.
+ *
+ * @param deviceRotationValue Device rotation key values separated by colon(':').
+ * @param targetKey The key of the new item caller wants to add.
+ * @param newValue The value of the new item caller want to add.
+ * @return A new string where all the key-value pairs.
+ */
+ private static String replaceDeviceRotationValue(
+ @NonNull String deviceRotationValue, int targetKey, int newValue) {
+ // Use list of Key-Value pair
+ List<Pair<Integer, Integer>> keyValuePairs = new ArrayList<>();
+
+ String[] pairs = deviceRotationValue.split(":");
+ if (pairs.length % 2 != 0) {
+ // Return without modifying. The key-value may be incorrect if length is an odd number.
+ loge("The length of key-value pair do not match. Return without modification.");
+ return deviceRotationValue;
+ }
+
+ // collect into keyValuePairs
+ for (int i = 0; i < pairs.length; i += 2) {
+ try {
+ int key = Integer.parseInt(pairs[i]);
+ int value = Integer.parseInt(pairs[i + 1]);
+ keyValuePairs.add(new Pair<>(key, key == targetKey ? newValue : value));
+ } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
+ // Return without modifying if got exception.
+ loge("got error while parsing key-value. Return without modification. e:" + e);
+ return deviceRotationValue;
+ }
+ }
+
+ return keyValuePairs.stream()
+ .map(pair -> pair.first + ":" + pair.second) // Convert to "key:value" format
+ .collect(Collectors.joining(":")); // Join pairs with colons
+ }
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected boolean areAllRadiosDisabled() {
synchronized (mRadioStateLock) {
@@ -3160,21 +3739,22 @@
|| (mDisableNFCOnSatelliteEnabled && mNfcStateEnabled)
|| (mDisableWifiOnSatelliteEnabled && mWifiStateEnabled)
|| (mDisableUWBOnSatelliteEnabled && mUwbStateEnabled)) {
- logd("All radios are not disabled yet.");
+ plogd("All radios are not disabled yet.");
return false;
}
- logd("All radios are disabled.");
+ plogd("All radios are disabled.");
return true;
}
}
private void evaluateToSendSatelliteEnabledSuccess() {
- logd("evaluateToSendSatelliteEnabledSuccess");
+ plogd("evaluateToSendSatelliteEnabledSuccess");
synchronized (mSatelliteEnabledRequestLock) {
if (areAllRadiosDisabled() && (mSatelliteEnabledRequest != null)
&& mWaitingForRadioDisabled) {
- logd("Sending success to callback that sent enable satellite request");
+ plogd("Sending success to callback that sent enable satellite request");
setDemoModeEnabled(mSatelliteEnabledRequest.enableDemoMode);
+ mIsEmergency = mSatelliteEnabledRequest.isEmergency;
synchronized (mIsSatelliteEnabledLock) {
mIsSatelliteEnabled = mSatelliteEnabledRequest.enableSatellite;
}
@@ -3189,7 +3769,7 @@
}
private void resetSatelliteEnabledRequest() {
- logd("resetSatelliteEnabledRequest");
+ plogd("resetSatelliteEnabledRequest");
synchronized (mSatelliteEnabledRequestLock) {
mSatelliteEnabledRequest = null;
mWaitingForRadioDisabled = false;
@@ -3198,12 +3778,15 @@
private void moveSatelliteToOffStateAndCleanUpResources(
@SatelliteManager.SatelliteResult int error, @Nullable Consumer<Integer> callback) {
- logd("moveSatelliteToOffStateAndCleanUpResources");
+ plogd("moveSatelliteToOffStateAndCleanUpResources");
synchronized (mIsSatelliteEnabledLock) {
resetSatelliteEnabledRequest();
setDemoModeEnabled(false);
+ handlePersistentLoggingOnSessionEnd(mIsEmergency);
+ mIsEmergency = false;
mIsSatelliteEnabled = false;
setSettingsKeyForSatelliteMode(SATELLITE_MODE_ENABLED_FALSE);
+ setSettingsKeyToAllowDeviceRotation(SATELLITE_MODE_ENABLED_FALSE);
if (callback != null) callback.accept(error);
updateSatelliteEnabledState(
false, "moveSatelliteToOffStateAndCleanUpResources");
@@ -3213,6 +3796,7 @@
private void setDemoModeEnabled(boolean enabled) {
mIsDemoModeEnabled = enabled;
mDatagramController.setDemoMode(mIsDemoModeEnabled);
+ plogd("setDemoModeEnabled: mIsDemoModeEnabled=" + mIsDemoModeEnabled);
}
private boolean isMockModemAllowed() {
@@ -3228,10 +3812,12 @@
synchronized (mSupportedSatelliteServicesLock) {
List<String> carrierPlmnList = mMergedPlmnListPerCarrier.get(subId,
new ArrayList<>()).stream().toList();
+ List<String> barredPlmnList = mEntitlementBarredPlmnListPerCarrier.get(subId,
+ new ArrayList<>()).stream().toList();
int slotId = SubscriptionManager.getSlotIndex(subId);
mSatelliteModemInterface.setSatellitePlmn(slotId, carrierPlmnList,
SatelliteServiceUtils.mergeStrLists(
- carrierPlmnList, mSatellitePlmnListFromOverlayConfig),
+ carrierPlmnList, mSatellitePlmnListFromOverlayConfig, barredPlmnList),
obtainMessage(EVENT_SET_SATELLITE_PLMN_INFO_DONE));
}
}
@@ -3268,14 +3854,23 @@
* Otherwise, If the carrierPlmnList exist then used it.
*/
private void updatePlmnListPerCarrier(int subId) {
+ plogd("updatePlmnListPerCarrier: subId=" + subId);
synchronized (mSupportedSatelliteServicesLock) {
List<String> carrierPlmnList, entitlementPlmnList;
- entitlementPlmnList = mEntitlementPlmnListPerCarrier.get(subId,
- new ArrayList<>()).stream().toList();
- if (!entitlementPlmnList.isEmpty()) {
- mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList);
- logd("update it using entitlementPlmnList=" + entitlementPlmnList);
- return;
+ if (getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
+ false)) {
+ entitlementPlmnList = mEntitlementPlmnListPerCarrier.get(subId,
+ new ArrayList<>()).stream().toList();
+ plogd("updatePlmnListPerCarrier: entitlementPlmnList="
+ + String.join(",", entitlementPlmnList)
+ + " size=" + entitlementPlmnList.size());
+ if (!entitlementPlmnList.isEmpty()) {
+ mMergedPlmnListPerCarrier.put(subId, entitlementPlmnList);
+ plogd("mMergedPlmnListPerCarrier is updated by Entitlement");
+ mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
+ SatelliteConstants.CONFIG_DATA_SOURCE_ENTITLEMENT);
+ return;
+ }
}
SatelliteConfig satelliteConfig = getSatelliteConfig();
@@ -3284,26 +3879,33 @@
int carrierId = tm.createForSubscriptionId(subId).getSimCarrierId();
List<String> plmnList = satelliteConfig.getAllSatellitePlmnsForCarrier(carrierId);
if (!plmnList.isEmpty()) {
- logd("mMergedPlmnListPerCarrier is updated by ConfigUpdater : " + plmnList);
+ plogd("mMergedPlmnListPerCarrier is updated by ConfigUpdater : "
+ + String.join(",", plmnList));
mMergedPlmnListPerCarrier.put(subId, plmnList);
+ mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
+ SatelliteConstants.CONFIG_DATA_SOURCE_CONFIG_UPDATER);
return;
}
}
- if (mSatelliteServicesSupportedByCarriers.containsKey(subId)) {
+ if (mSatelliteServicesSupportedByCarriers.containsKey(subId)
+ && mSatelliteServicesSupportedByCarriers.get(subId) != null) {
carrierPlmnList =
mSatelliteServicesSupportedByCarriers.get(subId).keySet().stream().toList();
- logd("mMergedPlmnListPerCarrier is updated by carrier config");
+ plogd("mMergedPlmnListPerCarrier is updated by carrier config: "
+ + String.join(",", carrierPlmnList));
+ mCarrierRoamingSatelliteControllerStats.reportConfigDataSource(
+ SatelliteConstants.CONFIG_DATA_SOURCE_CARRIER_CONFIG);
} else {
carrierPlmnList = new ArrayList<>();
+ plogd("Empty mMergedPlmnListPerCarrier");
}
mMergedPlmnListPerCarrier.put(subId, carrierPlmnList);
- logd("update it using carrierPlmnList=" + carrierPlmnList);
}
}
private void updateSupportedSatelliteServices(int subId) {
- logd("updateSupportedSatelliteServices with subId " + subId);
+ plogd("updateSupportedSatelliteServices with subId " + subId);
synchronized (mSupportedSatelliteServicesLock) {
SatelliteConfig satelliteConfig = getSatelliteConfig();
@@ -3315,19 +3917,19 @@
satelliteConfig.getSupportedSatelliteServices(carrierId);
if (!supportedServicesPerPlmn.isEmpty()) {
mSatelliteServicesSupportedByCarriers.put(subId, supportedServicesPerPlmn);
- logd("updateSupportedSatelliteServices using ConfigUpdater, "
- + "supportedServicesPerPlmn = " + supportedServicesPerPlmn);
+ plogd("updateSupportedSatelliteServices using ConfigUpdater, "
+ + "supportedServicesPerPlmn = " + supportedServicesPerPlmn.size());
updatePlmnListPerCarrier(subId);
return;
} else {
- logd("supportedServicesPerPlmn is empty");
+ plogd("supportedServicesPerPlmn is empty");
}
}
mSatelliteServicesSupportedByCarriers.put(
subId, readSupportedSatelliteServicesFromCarrierConfig(subId));
updatePlmnListPerCarrier(subId);
- logd("updateSupportedSatelliteServices using carrier config");
+ plogd("updateSupportedSatelliteServices using carrier config");
}
}
@@ -3345,16 +3947,10 @@
@NonNull
private Map<String, Set<Integer>> readSupportedSatelliteServicesFromCarrierConfig(int subId) {
- synchronized (mCarrierConfigArrayLock) {
- PersistableBundle config = mCarrierConfigArray.get(subId);
- if (config == null) {
- config = getConfigForSubId(subId);
- mCarrierConfigArray.put(subId, config);
- }
- return SatelliteServiceUtils.parseSupportedSatelliteServices(
- config.getPersistableBundle(
- KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE));
- }
+ PersistableBundle config = getPersistableBundle(subId);
+ return SatelliteServiceUtils.parseSupportedSatelliteServices(
+ config.getPersistableBundle(
+ KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE));
}
@NonNull private PersistableBundle getConfigForSubId(int subId) {
@@ -3362,7 +3958,10 @@
KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT,
- KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL);
+ KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL,
+ KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
+ KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL,
+ KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT);
if (config == null || config.isEmpty()) {
config = CarrierConfigManager.getDefaultConfig();
}
@@ -3371,7 +3970,7 @@
private void handleCarrierConfigChanged(int slotIndex, int subId, int carrierId,
int specificCarrierId) {
- logd("handleCarrierConfigChanged(): slotIndex(" + slotIndex + "), subId("
+ plogd("handleCarrierConfigChanged(): slotIndex(" + slotIndex + "), subId("
+ subId + "), carrierId(" + carrierId + "), specificCarrierId("
+ specificCarrierId + ")");
if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
@@ -3382,15 +3981,11 @@
updateEntitlementPlmnListPerCarrier(subId);
updateSupportedSatelliteServicesForActiveSubscriptions();
processNewCarrierConfigData(subId);
+ resetCarrierRoamingSatelliteModeParams(subId);
}
private void processNewCarrierConfigData(int subId) {
configureSatellitePlmnForCarrier(subId);
- synchronized (mIsSatelliteEnabledLock) {
- mSatelliteAttachRestrictionForCarrierArray.clear();
- mIsSatelliteAttachEnabledForCarrierArrayPerSub.clear();
- }
-
setSatelliteAttachEnabledForCarrierOnSimLoaded(subId);
updateRestrictReasonForEntitlementPerCarrier(subId);
}
@@ -3402,26 +3997,28 @@
}
}
- /** If there is no cached entitlement plmn list, read it from the db and use it if it is not an
- * empty list. */
+ /**
+ * If there is no cached entitlement plmn list, read it from the db and use it if it is not an
+ * empty list.
+ */
private void updateEntitlementPlmnListPerCarrier(int subId) {
if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) {
- logd("don't support entitlement");
+ plogd("don't support entitlement");
return;
}
synchronized (mSupportedSatelliteServicesLock) {
if (mEntitlementPlmnListPerCarrier.indexOfKey(subId) < 0) {
- logd("updateEntitlementPlmnListPerCarrier: no correspondent cache, load from "
+ plogd("updateEntitlementPlmnListPerCarrier: no correspondent cache, load from "
+ "persist storage");
List<String> entitlementPlmnList =
mSubscriptionManagerService.getSatelliteEntitlementPlmnList(subId);
if (entitlementPlmnList.isEmpty()) {
- loge("updateEntitlementPlmnListPerCarrier: no data for subId(" + subId + ")");
+ plogd("updateEntitlementPlmnListPerCarrier: read empty list");
return;
}
- logd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList="
- + entitlementPlmnList);
+ plogd("updateEntitlementPlmnListPerCarrier: entitlementPlmnList="
+ + String.join(",", entitlementPlmnList));
mEntitlementPlmnListPerCarrier.put(subId, entitlementPlmnList);
}
}
@@ -3450,7 +4047,7 @@
try {
strArray = mContext.getResources().getStringArray(id);
} catch (Resources.NotFoundException ex) {
- loge("readStringArrayFromOverlayConfig: id= " + id + ", ex=" + ex);
+ ploge("readStringArrayFromOverlayConfig: id= " + id + ", ex=" + ex);
}
if (strArray == null) {
strArray = new String[0];
@@ -3480,7 +4077,7 @@
return !cachedRestrictionSet.contains(
SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER);
} else {
- logd("isSatelliteAttachEnabledForCarrierByUser() no correspondent cache, "
+ plogd("isSatelliteAttachEnabledForCarrierByUser() no correspondent cache, "
+ "load from persist storage");
try {
String enabled =
@@ -3489,13 +4086,13 @@
mContext.getOpPackageName(), mContext.getAttributionTag());
if (enabled == null) {
- loge("isSatelliteAttachEnabledForCarrierByUser: invalid subId, subId="
+ ploge("isSatelliteAttachEnabledForCarrierByUser: invalid subId, subId="
+ subId);
return false;
}
if (enabled.isEmpty()) {
- loge("isSatelliteAttachEnabledForCarrierByUser: no data for subId(" + subId
+ ploge("isSatelliteAttachEnabledForCarrierByUser: no data for subId(" + subId
+ ")");
return false;
}
@@ -3510,7 +4107,7 @@
return result;
}
} catch (IllegalArgumentException | SecurityException ex) {
- loge("isSatelliteAttachEnabledForCarrierByUser: ex=" + ex);
+ ploge("isSatelliteAttachEnabledForCarrierByUser: ex=" + ex);
return false;
}
}
@@ -3533,19 +4130,19 @@
private void updateRestrictReasonForEntitlementPerCarrier(int subId) {
if (!getConfigForSubId(subId).getBoolean(KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, false)) {
- logd("don't support entitlement");
+ plogd("don't support entitlement");
return;
}
IIntegerConsumer callback = new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
- logd("updateRestrictReasonForEntitlementPerCarrier:" + result);
+ plogd("updateRestrictReasonForEntitlementPerCarrier:" + result);
}
};
synchronized (mSupportedSatelliteServicesLock) {
if (mSatelliteEntitlementStatusPerCarrier.indexOfKey(subId) < 0) {
- logd("updateRestrictReasonForEntitlementPerCarrier: no correspondent cache, "
+ plogd("updateRestrictReasonForEntitlementPerCarrier: no correspondent cache, "
+ "load from persist storage");
String entitlementStatus = null;
try {
@@ -3554,17 +4151,17 @@
SATELLITE_ENTITLEMENT_STATUS, mContext.getOpPackageName(),
mContext.getAttributionTag());
} catch (IllegalArgumentException | SecurityException e) {
- loge("updateRestrictReasonForEntitlementPerCarrier, e=" + e);
+ ploge("updateRestrictReasonForEntitlementPerCarrier, e=" + e);
}
if (entitlementStatus == null) {
- loge("updateRestrictReasonForEntitlementPerCarrier: invalid subId, subId="
+ ploge("updateRestrictReasonForEntitlementPerCarrier: invalid subId, subId="
+ subId + " set to default value");
entitlementStatus = "0";
}
if (entitlementStatus.isEmpty()) {
- loge("updateRestrictReasonForEntitlementPerCarrier: no data for subId(" + subId
+ ploge("updateRestrictReasonForEntitlementPerCarrier: no data for subId(" + subId
+ "). set to default value");
entitlementStatus = "0";
}
@@ -3589,9 +4186,9 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected boolean persistSatelliteAttachEnabledForCarrierSetting(int subId) {
- logd("persistSatelliteAttachEnabledForCarrierSetting");
+ plogd("persistSatelliteAttachEnabledForCarrierSetting");
if (!isValidSubscriptionId(subId)) {
- loge("persistSatelliteAttachEnabledForCarrierSetting: subId is not valid,"
+ ploge("persistSatelliteAttachEnabledForCarrierSetting: subId is not valid,"
+ " subId=" + subId);
return false;
}
@@ -3604,7 +4201,7 @@
.contains(SATELLITE_COMMUNICATION_RESTRICTION_REASON_USER)
? "0" : "1");
} catch (IllegalArgumentException | SecurityException ex) {
- loge("persistSatelliteAttachEnabledForCarrierSetting, ex=" + ex);
+ ploge("persistSatelliteAttachEnabledForCarrierSetting, ex=" + ex);
return false;
}
}
@@ -3653,12 +4250,12 @@
private void evaluateEnablingSatelliteForCarrier(int subId, int reason,
@Nullable Consumer<Integer> callback) {
if (callback == null) {
- callback = errorCode -> logd("evaluateEnablingSatelliteForCarrier: "
+ callback = errorCode -> plogd("evaluateEnablingSatelliteForCarrier: "
+ "SetSatelliteAttachEnableForCarrier error code =" + errorCode);
}
if (!isSatelliteSupportedViaCarrier(subId)) {
- logd("Satellite for carrier is not supported. Only user setting is stored");
+ plogd("Satellite for carrier is not supported. Only user setting is stored");
callback.accept(SATELLITE_RESULT_SUCCESS);
return;
}
@@ -3690,17 +4287,17 @@
@SatelliteManager.SatelliteResult private int evaluateOemSatelliteRequestAllowed(
boolean isProvisionRequired) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("oemEnabledSatelliteFlag is disabled");
+ plogd("oemEnabledSatelliteFlag is disabled");
return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
}
if (!mSatelliteModemInterface.isSatelliteServiceSupported()) {
- logd("evaluateOemSatelliteRequestAllowed: satellite service is not supported");
+ plogd("evaluateOemSatelliteRequestAllowed: satellite service is not supported");
return SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED;
}
Boolean satelliteSupported = isSatelliteSupportedViaOemInternal();
if (satelliteSupported == null) {
- logd("evaluateOemSatelliteRequestAllowed: satelliteSupported is null");
+ plogd("evaluateOemSatelliteRequestAllowed: satelliteSupported is null");
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
}
if (!satelliteSupported) {
@@ -3710,7 +4307,7 @@
if (isProvisionRequired) {
Boolean satelliteProvisioned = isSatelliteViaOemProvisioned();
if (satelliteProvisioned == null) {
- logd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null");
+ plogd("evaluateOemSatelliteRequestAllowed: satelliteProvisioned is null");
return SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
}
if (!satelliteProvisioned) {
@@ -3739,10 +4336,12 @@
private void sendErrorAndReportSessionMetrics(@SatelliteManager.SatelliteResult int error,
Consumer<Integer> result) {
result.accept(error);
- SessionMetricsStats.getInstance()
- .setInitializationResult(error)
- .setRadioTechnology(getSupportedNtnRadioTechnology())
+ mSessionMetricsStats.setInitializationResult(error)
+ .setSatelliteTechnology(getSupportedNtnRadioTechnology())
+ .setIsDemoMode(mIsDemoModeEnabled)
.reportSessionMetrics();
+ mSessionStartTimeStamp = 0;
+ mSessionProcessingTimeStamp = 0;
}
private void registerForServiceStateChanged() {
@@ -3761,49 +4360,118 @@
private void handleServiceStateForSatelliteConnectionViaCarrier() {
for (Phone phone : PhoneFactory.getPhones()) {
+ int subId = phone.getSubId();
ServiceState serviceState = phone.getServiceState();
- if (serviceState != null) {
- synchronized (mSatelliteConnectedLock) {
- if (serviceState.isUsingNonTerrestrialNetwork()) {
- mWasSatelliteConnectedViaCarrier.put(phone.getSubId(), true);
- mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.put(
- phone.getSubId(), false);
- } else {
- Boolean connected = mWasSatelliteConnectedViaCarrier.get(phone.getSubId());
- if (connected != null && connected) {
- // The device just got disconnected from a satellite network.
- mLastSatelliteDisconnectedTimesMillis.put(
- phone.getSubId(), getElapsedRealtime());
- mIsSatelliteConnectedViaCarrierHysteresisTimeExpired.put(
- phone.getSubId(), false);
+ if (serviceState == null) {
+ continue;
+ }
+
+ synchronized (mSatelliteConnectedLock) {
+ CarrierRoamingSatelliteSessionStats sessionStats =
+ mCarrierRoamingSatelliteSessionStatsMap.get(subId);
+
+ if (serviceState.isUsingNonTerrestrialNetwork()) {
+ if (sessionStats != null) {
+ sessionStats.onSignalStrength(phone);
+ if (!mWasSatelliteConnectedViaCarrier.get(subId)) {
+ // Log satellite connection start
+ sessionStats.onConnectionStart(phone);
}
- mWasSatelliteConnectedViaCarrier.put(phone.getSubId(), false);
}
+
+ resetCarrierRoamingSatelliteModeParams(subId);
+ mWasSatelliteConnectedViaCarrier.put(subId, true);
+
+ for (NetworkRegistrationInfo nri
+ : serviceState.getNetworkRegistrationInfoList()) {
+ if (nri.isNonTerrestrialNetwork()) {
+ mSatModeCapabilitiesForCarrierRoaming.put(subId,
+ nri.getAvailableServices());
+ }
+ }
+ } else {
+ Boolean connected = mWasSatelliteConnectedViaCarrier.get(subId);
+ if (getWwanIsInService(serviceState)) {
+ resetCarrierRoamingSatelliteModeParams(subId);
+ } else if (connected != null && connected) {
+ // The device just got disconnected from a satellite network
+ // and is not connected to any terrestrial network that has coverage
+ mLastSatelliteDisconnectedTimesMillis.put(subId, getElapsedRealtime());
+
+ plogd("sendMessageDelayed subId:" + subId
+ + " phoneId:" + phone.getPhoneId()
+ + " time:" + getSatelliteConnectionHysteresisTimeMillis(subId));
+ sendMessageDelayed(obtainMessage(EVENT_NOTIFY_NTN_HYSTERESIS_TIMED_OUT,
+ phone.getPhoneId()),
+ getSatelliteConnectionHysteresisTimeMillis(subId));
+
+ if (sessionStats != null) {
+ // Log satellite connection end
+ sessionStats.onConnectionEnd();
+ }
+ }
+ mWasSatelliteConnectedViaCarrier.put(subId, false);
}
+ updateLastNotifiedNtnModeAndNotify(phone);
+ }
+ }
+ }
+
+ private void updateLastNotifiedNtnModeAndNotify(@Nullable Phone phone) {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
+
+ if (phone == null) {
+ return;
+ }
+
+ int subId = phone.getSubId();
+ synchronized (mSatelliteConnectedLock) {
+ boolean initialized = mInitialized.get(subId);
+ boolean lastNotifiedNtnMode = mLastNotifiedNtnMode.get(subId);
+ boolean currNtnMode = isInSatelliteModeForCarrierRoaming(phone);
+ if (!initialized || lastNotifiedNtnMode != currNtnMode) {
+ if (!initialized) mInitialized.put(subId, true);
+ mLastNotifiedNtnMode.put(subId, currNtnMode);
+ phone.notifyCarrierRoamingNtnModeChanged(currNtnMode);
+ logCarrierRoamingSatelliteSessionStats(phone, lastNotifiedNtnMode, currNtnMode);
+ }
+ }
+ }
+
+ private void logCarrierRoamingSatelliteSessionStats(@NonNull Phone phone,
+ boolean lastNotifiedNtnMode, boolean currNtnMode) {
+ synchronized (mSatelliteConnectedLock) {
+ int subId = phone.getSubId();
+ if (!lastNotifiedNtnMode && currNtnMode) {
+ // Log satellite session start
+ CarrierRoamingSatelliteSessionStats sessionStats =
+ CarrierRoamingSatelliteSessionStats.getInstance(subId);
+ sessionStats.onSessionStart(phone.getCarrierId(), phone);
+ mCarrierRoamingSatelliteSessionStatsMap.put(subId, sessionStats);
+ } else if (lastNotifiedNtnMode && !currNtnMode) {
+ // Log satellite session end
+ CarrierRoamingSatelliteSessionStats sessionStats =
+ mCarrierRoamingSatelliteSessionStatsMap.get(subId);
+ sessionStats.onSessionEnd();
+ mCarrierRoamingSatelliteSessionStatsMap.remove(subId);
}
}
}
private long getSatelliteConnectionHysteresisTimeMillis(int subId) {
- synchronized (mCarrierConfigArrayLock) {
- PersistableBundle config = mCarrierConfigArray.get(subId);
- if (config == null) {
- config = getConfigForSubId(subId);
- mCarrierConfigArray.put(subId, config);
- }
- return (config.getInt(
- KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT) * 1000L);
- }
+ PersistableBundle config = getPersistableBundle(subId);
+ return (config.getInt(
+ KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT) * 1000L);
}
private void persistOemEnabledSatelliteProvisionStatus(boolean isProvisioned) {
synchronized (mSatelliteViaOemProvisionLock) {
- logd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
+ plogd("persistOemEnabledSatelliteProvisionStatus: isProvisioned=" + isProvisioned);
if (!loadSatelliteSharedPreferences()) return;
if (mSharedPreferences == null) {
- loge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
+ ploge("persistOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
} else {
mSharedPreferences.edit().putBoolean(
OEM_ENABLED_SATELLITE_PROVISION_STATUS_KEY, isProvisioned).apply();
@@ -3816,7 +4484,7 @@
if (!loadSatelliteSharedPreferences()) return false;
if (mSharedPreferences == null) {
- loge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
+ ploge("getPersistedOemEnabledSatelliteProvisionStatus: mSharedPreferences is null");
return false;
} else {
return mSharedPreferences.getBoolean(
@@ -3832,7 +4500,7 @@
mContext.getSharedPreferences(SATELLITE_SHARED_PREF,
Context.MODE_PRIVATE);
} catch (Exception e) {
- loge("loadSatelliteSharedPreferences: Cannot get default "
+ ploge("loadSatelliteSharedPreferences: Cannot get default "
+ "shared preferences, e=" + e);
return false;
}
@@ -3847,18 +4515,18 @@
boolean isSatelliteProvisionedInModem = false;
if (error == SATELLITE_RESULT_SUCCESS) {
if (ar.result == null) {
- loge("handleIsSatelliteProvisionedDoneEvent: result is null");
+ ploge("handleIsSatelliteProvisionedDoneEvent: result is null");
error = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
} else {
isSatelliteProvisionedInModem = ((int[]) ar.result)[0] == 1;
}
} else if (error == SATELLITE_RESULT_REQUEST_NOT_SUPPORTED) {
- logd("handleIsSatelliteProvisionedDoneEvent: Modem does not support this request");
+ plogd("handleIsSatelliteProvisionedDoneEvent: Modem does not support this request");
isSatelliteProvisionedInModem = true;
}
boolean isSatelliteViaOemProvisioned =
isSatelliteProvisionedInModem && getPersistedOemEnabledSatelliteProvisionStatus();
- logd("isSatelliteProvisionedInModem=" + isSatelliteProvisionedInModem
+ plogd("isSatelliteProvisionedInModem=" + isSatelliteProvisionedInModem
+ ", isSatelliteViaOemProvisioned=" + isSatelliteViaOemProvisioned);
Bundle bundle = new Bundle();
bundle.putBoolean(SatelliteManager.KEY_SATELLITE_PROVISIONED, isSatelliteViaOemProvisioned);
@@ -3877,11 +4545,11 @@
@NonNull RequestSatelliteEnabledArgument argument) {
synchronized (mSatelliteEnabledRequestLock) {
if (hasMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument)) {
- logd("WaitForSatelliteEnablingResponseTimer of request ID "
+ plogd("WaitForSatelliteEnablingResponseTimer of request ID "
+ argument.requestId + " was already started");
return;
}
- logd("Start timer to wait for response of the satellite enabling request ID="
+ plogd("Start timer to wait for response of the satellite enabling request ID="
+ argument.requestId + ", enableSatellite=" + argument.enableSatellite
+ ", mWaitTimeForSatelliteEnablingResponse="
+ mWaitTimeForSatelliteEnablingResponse);
@@ -3893,7 +4561,7 @@
private void stopWaitForSatelliteEnablingResponseTimer(
@NonNull RequestSatelliteEnabledArgument argument) {
synchronized (mSatelliteEnabledRequestLock) {
- logd("Stop timer to wait for response of the satellite enabling request ID="
+ plogd("Stop timer to wait for response of the satellite enabling request ID="
+ argument.requestId + ", enableSatellite=" + argument.enableSatellite);
removeMessages(EVENT_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMED_OUT, argument);
}
@@ -3911,7 +4579,7 @@
private void handleEventWaitForSatelliteEnablingResponseTimedOut(
@NonNull RequestSatelliteEnabledArgument argument) {
- logw("Timed out to wait for response of the satellite enabling request ID="
+ plogw("Timed out to wait for response of the satellite enabling request ID="
+ argument.requestId + ", enableSatellite=" + argument.enableSatellite);
synchronized (mSatelliteEnabledRequestLock) {
@@ -3936,24 +4604,29 @@
IIntegerConsumer callback = new IIntegerConsumer.Stub() {
@Override
public void accept(int result) {
- logd("handleEventWaitForSatelliteEnablingResponseTimedOut: "
+ plogd("handleEventWaitForSatelliteEnablingResponseTimedOut: "
+ "disable satellite result=" + result);
}
};
Consumer<Integer> result =
FunctionalUtils.ignoreRemoteException(callback::accept);
RequestSatelliteEnabledArgument request = new RequestSatelliteEnabledArgument(
- false, false, result);
+ false, false, false, result);
synchronized (mSatelliteEnabledRequestLock) {
mSatelliteEnabledRequest = request;
}
sendRequestAsync(CMD_SET_SATELLITE_ENABLED, request, null);
}
+ notifyEnablementFailedToSatelliteSessionController();
mControllerMetricsStats.reportServiceEnablementFailCount();
- SessionMetricsStats.getInstance()
- .setInitializationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
- .setRadioTechnology(getSupportedNtnRadioTechnology())
+ mSessionMetricsStats.setInitializationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
+ .setSatelliteTechnology(getSupportedNtnRadioTechnology())
+ .setInitializationProcessingTime(
+ System.currentTimeMillis() - mSessionProcessingTimeStamp)
+ .setIsDemoMode(mIsDemoModeEnabled)
.reportSessionMetrics();
+ mSessionStartTimeStamp = 0;
+ mSessionProcessingTimeStamp = 0;
} else {
/*
* Unregister Importance Listener for Pointing UI when Satellite is disabled
@@ -3967,10 +4640,62 @@
mControllerMetricsStats.onSatelliteDisabled();
mWaitingForDisableSatelliteModemResponse = false;
mWaitingForSatelliteModemOff = false;
+ mSessionMetricsStats.setTerminationResult(SATELLITE_RESULT_MODEM_TIMEOUT)
+ .setSatelliteTechnology(getSupportedNtnRadioTechnology())
+ .setTerminationProcessingTime(
+ System.currentTimeMillis() - mSessionProcessingTimeStamp)
+ .setSessionDurationSec(calculateSessionDurationTimeSec())
+ .reportSessionMetrics();
+ mSessionStartTimeStamp = 0;
+ mSessionProcessingTimeStamp = 0;
}
}
}
+ private void handleCmdUpdateNtnSignalStrengthReporting(boolean shouldReport) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ plogd("handleCmdUpdateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
+ + "disabled");
+ return;
+ }
+
+ if (!isSatelliteEnabled()) {
+ plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request, satellite is "
+ + "disabled");
+ return;
+ }
+
+ mLatestRequestedStateForNtnSignalStrengthReport.set(shouldReport);
+ if (mIsModemEnabledReportingNtnSignalStrength.get() == shouldReport) {
+ plogd("handleCmdUpdateNtnSignalStrengthReporting: ignore request. "
+ + "mIsModemEnabledReportingNtnSignalStrength="
+ + mIsModemEnabledReportingNtnSignalStrength.get());
+ return;
+ }
+
+ updateNtnSignalStrengthReporting(shouldReport);
+ }
+
+ private void updateNtnSignalStrengthReporting(boolean shouldReport) {
+ if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
+ plogd("updateNtnSignalStrengthReporting: oemEnabledSatelliteFlag is "
+ + "disabled");
+ return;
+ }
+
+ SatelliteControllerHandlerRequest request = new SatelliteControllerHandlerRequest(
+ shouldReport, SatelliteServiceUtils.getPhone());
+ Message onCompleted = obtainMessage(EVENT_UPDATE_NTN_SIGNAL_STRENGTH_REPORTING_DONE,
+ request);
+ if (shouldReport) {
+ plogd("updateNtnSignalStrengthReporting: startSendingNtnSignalStrength");
+ mSatelliteModemInterface.startSendingNtnSignalStrength(onCompleted);
+ } else {
+ plogd("updateNtnSignalStrengthReporting: stopSendingNtnSignalStrength");
+ mSatelliteModemInterface.stopSendingNtnSignalStrength(onCompleted);
+ }
+ }
+
/**
* This API can be used by only CTS to override the cached value for the device overlay config
* value : config_send_satellite_datagram_to_modem_in_demo_mode, which determines whether
@@ -3983,12 +4708,12 @@
*/
public boolean setShouldSendDatagramToModemInDemoMode(boolean shouldSendToModemInDemoMode) {
if (!mFeatureFlags.oemEnabledSatelliteFlag()) {
- logd("setShouldSendDatagramToModemInDemoMode: oemEnabledSatelliteFlag is disabled");
+ plogd("setShouldSendDatagramToModemInDemoMode: oemEnabledSatelliteFlag is disabled");
return false;
}
if (!isMockModemAllowed()) {
- logd("setShouldSendDatagramToModemInDemoMode: mock modem not allowed.");
+ plogd("setShouldSendDatagramToModemInDemoMode: mock modem not allowed.");
return false;
}
@@ -4025,7 +4750,7 @@
}
private void showSatelliteSystemNotification(int subId) {
- logd("showSatelliteSystemNotification");
+ plogd("showSatelliteSystemNotification");
final NotificationChannel notificationChannel = new NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL,
@@ -4041,20 +4766,37 @@
R.string.satellite_notification_title))
.setContentText(mContext.getResources().getString(
R.string.satellite_notification_summary))
- .setSmallIcon(R.drawable.ic_satellite_alt_24px)
+ .setSmallIcon(R.drawable.ic_android_satellite_24px)
.setChannelId(NOTIFICATION_CHANNEL_ID)
.setAutoCancel(true)
.setColor(mContext.getColor(
com.android.internal.R.color.system_notification_accent_color))
.setVisibility(Notification.VISIBILITY_PUBLIC);
- // Add action to invoke `What to expect` dialog of Messaging application.
- Intent intentOpenMessage = new Intent(Intent.ACTION_VIEW);
- intentOpenMessage.setData(Uri.parse("sms:"));
- // TODO : b/322733285 add putExtra to invoke "What to expect" dialog.
- PendingIntent pendingIntentOpenMessage = PendingIntent.getActivity(mContext, 0,
- intentOpenMessage, PendingIntent.FLAG_IMMUTABLE);
+ // Add action to invoke message application.
+ // getDefaultSmsPackage and getLaunchIntentForPackage are nullable.
+ Optional<Intent> nullableIntent = Optional.ofNullable(
+ Telephony.Sms.getDefaultSmsPackage(mContext))
+ .flatMap(packageName -> {
+ PackageManager pm = mContext.getPackageManager();
+ return Optional.ofNullable(pm.getLaunchIntentForPackage(packageName));
+ });
+ // If nullableIntent is null, create new Intent for most common way to invoke message app.
+ Intent finalIntent = nullableIntent.map(intent -> {
+ // Invoke the home screen of default message application.
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ return intent;
+ }).orElseGet(() -> {
+ ploge("showSatelliteSystemNotification: no default sms package name, Invoke "
+ + "default sms compose window instead");
+ Intent newIntent = new Intent(Intent.ACTION_VIEW);
+ newIntent.setData(Uri.parse("sms:"));
+ return newIntent;
+ });
+ PendingIntent pendingIntentOpenMessage = PendingIntent.getActivity(mContext, 0,
+ finalIntent, PendingIntent.FLAG_IMMUTABLE);
Notification.Action actionOpenMessage = new Notification.Action.Builder(0,
mContext.getResources().getString(R.string.satellite_notification_open_message),
pendingIntentOpenMessage).build();
@@ -4073,6 +4815,108 @@
notificationManager.notifyAsUser(NOTIFICATION_TAG, NOTIFICATION_ID,
notificationBuilder.build(), UserHandle.ALL);
+
+ mCarrierRoamingSatelliteControllerStats.reportCountOfSatelliteNotificationDisplayed();
+ }
+
+ private void resetCarrierRoamingSatelliteModeParams() {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
+
+ for (Phone phone : PhoneFactory.getPhones()) {
+ resetCarrierRoamingSatelliteModeParams(phone.getSubId());
+ }
+ }
+
+ private void resetCarrierRoamingSatelliteModeParams(int subId) {
+ if (!mFeatureFlags.carrierEnabledSatelliteFlag()) return;
+
+ synchronized (mSatelliteConnectedLock) {
+ mLastSatelliteDisconnectedTimesMillis.put(subId, null);
+ mSatModeCapabilitiesForCarrierRoaming.remove(subId);
+ mWasSatelliteConnectedViaCarrier.put(subId, false);
+ }
+ }
+
+ @NonNull
+ private PersistableBundle getPersistableBundle(int subId) {
+ synchronized (mCarrierConfigArrayLock) {
+ PersistableBundle config = mCarrierConfigArray.get(subId);
+ if (config == null) {
+ config = getConfigForSubId(subId);
+ mCarrierConfigArray.put(subId, config);
+ }
+ return config;
+ }
+ }
+
+ // Should be invoked only when session termination done or session termination failed.
+ private int calculateSessionDurationTimeSec() {
+ return (int) (
+ (System.currentTimeMillis() - mSessionStartTimeStamp
+ - mSessionMetricsStats.getSessionInitializationProcessingTimeMillis()
+ - mSessionMetricsStats.getSessionTerminationProcessingTimeMillis()) / 1000);
+ }
+
+ private void notifyEnablementFailedToSatelliteSessionController() {
+ if (mSatelliteSessionController != null) {
+ mSatelliteSessionController.onSatelliteEnablementFailed();
+ } else {
+ ploge("notifyEnablementFailedToSatelliteSessionController: mSatelliteSessionController"
+ + " is not initialized yet");
+ }
+ }
+
+ private long getDemoPointingAlignedDurationMillisFromResources() {
+ long durationMillis = 15000L;
+ try {
+ durationMillis = mContext.getResources().getInteger(
+ R.integer.config_demo_pointing_aligned_duration_millis);
+ } catch (Resources.NotFoundException ex) {
+ loge("getPointingAlignedDurationMillis: ex=" + ex);
+ }
+
+ return durationMillis;
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public long getDemoPointingAlignedDurationMillis() {
+ return mDemoPointingAlignedDurationMillis;
+ }
+
+ private long getDemoPointingNotAlignedDurationMillisFromResources() {
+ long durationMillis = 30000L;
+ try {
+ durationMillis = mContext.getResources().getInteger(
+ R.integer.config_demo_pointing_not_aligned_duration_millis);
+ } catch (Resources.NotFoundException ex) {
+ loge("getPointingNotAlignedDurationMillis: ex=" + ex);
+ }
+
+ return durationMillis;
+ }
+
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public long getDemoPointingNotAlignedDurationMillis() {
+ return mDemoPointingNotAlignedDurationMillis;
+ }
+
+ private boolean getWwanIsInService(ServiceState serviceState) {
+ List<NetworkRegistrationInfo> nriList = serviceState
+ .getNetworkRegistrationInfoListForTransportType(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ for (NetworkRegistrationInfo nri : nriList) {
+ if (nri.isInService()) {
+ logv("getWwanIsInService: return true");
+ return true;
+ }
+ }
+
+ logv("getWwanIsInService: return false");
+ return false;
+ }
+
+ private static void logv(@NonNull String log) {
+ Rlog.v(TAG, log);
}
private static void logd(@NonNull String log) {
@@ -4086,4 +4930,98 @@
private static void loge(@NonNull String log) {
Rlog.e(TAG, log);
}
+
+ private boolean isSatellitePersistentLoggingEnabled(
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (featureFlags.satellitePersistentLogging()) {
+ return true;
+ }
+ try {
+ return context.getResources().getBoolean(
+ R.bool.config_dropboxmanager_persistent_logging_enabled);
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ private void plogd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
+ private void plogw(@NonNull String log) {
+ Rlog.w(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.warn(TAG, log);
+ }
+ }
+
+ private void ploge(@NonNull String log) {
+ Rlog.e(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.error(TAG, log);
+ }
+ }
+
+ private void handlePersistentLoggingOnSessionStart(RequestSatelliteEnabledArgument argument) {
+ if (mPersistentLogger == null) {
+ return;
+ }
+ if (argument.isEmergency) {
+ DropBoxManagerLoggerBackend.getInstance(mContext).setLoggingEnabled(true);
+ }
+ }
+
+ private void handlePersistentLoggingOnSessionEnd(boolean isEmergency) {
+ if (mPersistentLogger == null) {
+ return;
+ }
+ DropBoxManagerLoggerBackend loggerBackend =
+ DropBoxManagerLoggerBackend.getInstance(mContext);
+ // Flush persistent satellite logs on eSOS session end
+ if (isEmergency) {
+ loggerBackend.flushAsync();
+ }
+ // Also turn off persisted logging until new session is started
+ loggerBackend.setLoggingEnabled(false);
+ }
+
+ /**
+ * Set last emergency call time to the current time.
+ */
+ public void setLastEmergencyCallTime() {
+ synchronized (mLock) {
+ mLastEmergencyCallTime = getElapsedRealtime();
+ plogd("mLastEmergencyCallTime=" + mLastEmergencyCallTime);
+ }
+ }
+
+ /**
+ * Check if satellite is in emergency mode.
+ */
+ public boolean isInEmergencyMode() {
+ synchronized (mLock) {
+ if (mLastEmergencyCallTime == 0) return false;
+
+ long currentTime = getElapsedRealtime();
+ if ((currentTime - mLastEmergencyCallTime) <= mSatelliteEmergencyModeDurationMillis) {
+ plogd("Satellite is in emergency mode");
+ return true;
+ }
+ return false;
+ }
+ }
+
+ private long getSatelliteEmergencyModeDurationFromOverlayConfig(@NonNull Context context) {
+ Integer duration = DEFAULT_SATELLITE_EMERGENCY_MODE_DURATION_SECONDS;
+ try {
+ duration = context.getResources().getInteger(com.android.internal.R.integer
+ .config_satellite_emergency_mode_duration);
+ } catch (Resources.NotFoundException ex) {
+ ploge("getSatelliteEmergencyModeDurationFromOverlayConfig: got ex=" + ex);
+ }
+ return TimeUnit.SECONDS.toMillis(duration);
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
index 2f86eea..da4c69b 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteModemInterface.java
@@ -30,8 +30,10 @@
import android.os.Message;
import android.os.RegistrantList;
import android.os.RemoteException;
+import android.telephony.DropBoxManagerLoggerBackend;
import android.telephony.IBooleanConsumer;
import android.telephony.IIntegerConsumer;
+import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
@@ -42,6 +44,7 @@
import android.telephony.satellite.stub.ISatellite;
import android.telephony.satellite.stub.ISatelliteCapabilitiesConsumer;
import android.telephony.satellite.stub.ISatelliteListener;
+import android.telephony.satellite.stub.SatelliteModemState;
import android.telephony.satellite.stub.SatelliteService;
import android.text.TextUtils;
import android.util.Pair;
@@ -49,6 +52,7 @@
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.flags.FeatureFlags;
import java.util.Arrays;
import java.util.List;
@@ -64,6 +68,9 @@
@NonNull private static SatelliteModemInterface sInstance;
@NonNull private final Context mContext;
+ @NonNull private final DemoSimulator mDemoSimulator;
+ @NonNull private final SatelliteListener mVendorListener;
+ @NonNull private final SatelliteListener mDemoListener;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
@NonNull protected final ExponentialBackoff mExponentialBackoff;
@NonNull private final Object mLock = new Object();
@@ -77,6 +84,7 @@
@NonNull private String mVendorSatellitePackageName = "";
private boolean mIsBound;
private boolean mIsBinding;
+ @Nullable private PersistentLogger mPersistentLogger = null;
@NonNull private final RegistrantList mSatelliteProvisionStateChangedRegistrants =
new RegistrantList();
@@ -93,8 +101,17 @@
new RegistrantList();
@NonNull private final RegistrantList mSatelliteCapabilitiesChangedRegistrants =
new RegistrantList();
+ @NonNull private final RegistrantList mSatelliteSupportedStateChangedRegistrants =
+ new RegistrantList();
- @NonNull private final ISatelliteListener mListener = new ISatelliteListener.Stub() {
+ private class SatelliteListener extends ISatelliteListener.Stub {
+
+ private final boolean mIsDemoListener;
+
+ SatelliteListener(boolean isDemoListener) {
+ mIsDemoListener = isDemoListener;
+ }
+
@Override
public void onSatelliteProvisionStateChanged(boolean provisioned) {
mSatelliteProvisionStateChangedRegistrants.notifyResult(provisioned);
@@ -103,15 +120,19 @@
@Override
public void onSatelliteDatagramReceived(
android.telephony.satellite.stub.SatelliteDatagram datagram, int pendingCount) {
- logd("onSatelliteDatagramReceived: pendingCount=" + pendingCount);
- mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>(
- SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount));
+ if (notifyResultIfExpectedListener()) {
+ plogd("onSatelliteDatagramReceived: pendingCount=" + pendingCount);
+ mSatelliteDatagramsReceivedRegistrants.notifyResult(new Pair<>(
+ SatelliteServiceUtils.fromSatelliteDatagram(datagram), pendingCount));
+ }
}
@Override
public void onPendingDatagrams() {
- logd("onPendingDatagrams");
- mPendingDatagramsRegistrants.notifyResult(null);
+ if (notifyResultIfExpectedListener()) {
+ plogd("onPendingDatagrams");
+ mPendingDatagramsRegistrants.notifyResult(null);
+ }
}
@Override
@@ -123,33 +144,39 @@
@Override
public void onSatelliteModemStateChanged(int state) {
- mSatelliteModemStateChangedRegistrants.notifyResult(
- SatelliteServiceUtils.fromSatelliteModemState(state));
- int datagramTransferState = SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN;
- switch (state) {
- case SatelliteManager.SATELLITE_MODEM_STATE_IDLE:
- datagramTransferState = SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
- break;
- case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING:
- datagramTransferState =
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
- break;
- case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING:
- datagramTransferState =
- SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
- break;
- case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING:
- // keep previous state as this could be retrying sending or receiving
- break;
+ if (notifyModemStateChanged(state)) {
+ mSatelliteModemStateChangedRegistrants.notifyResult(
+ SatelliteServiceUtils.fromSatelliteModemState(state));
+ int datagramTransferState =
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN;
+ switch (state) {
+ case SatelliteManager.SATELLITE_MODEM_STATE_IDLE:
+ datagramTransferState =
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+ break;
+ case SatelliteManager.SATELLITE_MODEM_STATE_LISTENING:
+ datagramTransferState =
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
+ break;
+ case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING:
+ datagramTransferState =
+ SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
+ break;
+ case SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING:
+ // keep previous state as this could be retrying sending or receiving
+ break;
+ }
+ mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState);
}
- mDatagramTransferStateChangedRegistrants.notifyResult(datagramTransferState);
}
@Override
public void onNtnSignalStrengthChanged(
android.telephony.satellite.stub.NtnSignalStrength ntnSignalStrength) {
- mNtnSignalStrengthChangedRegistrants.notifyResult(
- SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength));
+ if (notifyResultIfExpectedListener()) {
+ mNtnSignalStrengthChangedRegistrants.notifyResult(
+ SatelliteServiceUtils.fromNtnSignalStrength(ntnSignalStrength));
+ }
}
@Override
@@ -158,7 +185,32 @@
mSatelliteCapabilitiesChangedRegistrants.notifyResult(
SatelliteServiceUtils.fromSatelliteCapabilities(satelliteCapabilities));
}
- };
+
+ @Override
+ public void onSatelliteSupportedStateChanged(boolean supported) {
+ mSatelliteSupportedStateChangedRegistrants.notifyResult(supported);
+ }
+
+ @Override
+ public void onRegistrationFailure(int causeCode) {
+ // TO-DO notify registrants
+ }
+
+ private boolean notifyResultIfExpectedListener() {
+ // Demo listener should notify results only during demo mode
+ // Vendor listener should notify result only during real mode
+ return mIsDemoListener == mSatelliteController.isDemoModeEnabled();
+ }
+
+ private boolean notifyModemStateChanged(int state) {
+ if (notifyResultIfExpectedListener()) {
+ return true;
+ }
+
+ return state == SatelliteModemState.SATELLITE_MODEM_STATE_OFF
+ || state == SatelliteModemState.SATELLITE_MODEM_STATE_UNAVAILABLE;
+ }
+ }
/**
* @return The singleton instance of SatelliteModemInterface.
@@ -174,13 +226,15 @@
* Create the SatelliteModemInterface singleton instance.
* @param context The Context to use to create the SatelliteModemInterface.
* @param satelliteController The singleton instance of SatelliteController.
+ * @param featureFlags The telephony feature flags.
* @return The singleton instance of SatelliteModemInterface.
*/
public static SatelliteModemInterface make(@NonNull Context context,
- SatelliteController satelliteController) {
+ SatelliteController satelliteController,
+ @NonNull FeatureFlags featureFlags) {
if (sInstance == null) {
sInstance = new SatelliteModemInterface(
- context, satelliteController, Looper.getMainLooper());
+ context, satelliteController, Looper.getMainLooper(), featureFlags);
}
return sInstance;
}
@@ -189,12 +243,22 @@
* Create a SatelliteModemInterface to manage connections to the SatelliteService.
*
* @param context The Context for the SatelliteModemInterface.
+ * @param featureFlags The telephony feature flags.
* @param looper The Looper to run binding retry on.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected SatelliteModemInterface(@NonNull Context context,
- SatelliteController satelliteController, @NonNull Looper looper) {
+ SatelliteController satelliteController,
+ @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags) {
+ if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+ mPersistentLogger = new PersistentLogger(
+ DropBoxManagerLoggerBackend.getInstance(context));
+ }
mContext = context;
+ mDemoSimulator = DemoSimulator.make(context, satelliteController);
+ mVendorListener = new SatelliteListener(false);
+ mDemoListener = new SatelliteListener(true);
mIsSatelliteServiceSupported = getSatelliteServiceSupport();
mSatelliteController = satelliteController;
mExponentialBackoff = new ExponentialBackoff(REBIND_INITIAL_DELAY, REBIND_MAXIMUM_DELAY,
@@ -214,7 +278,7 @@
bindService();
});
mExponentialBackoff.start();
- logd("Created SatelliteModemInterface. Attempting to bind to SatelliteService.");
+ plogd("Created SatelliteModemInterface. Attempting to bind to SatelliteService.");
bindService();
}
@@ -247,7 +311,7 @@
}
String packageName = getSatellitePackageName();
if (TextUtils.isEmpty(packageName)) {
- loge("Unable to bind to the satellite service because the package is undefined.");
+ ploge("Unable to bind to the satellite service because the package is undefined.");
// Since the package name comes from static device configs, stop retry because
// rebind will continue to fail without a valid package name.
synchronized (mLock) {
@@ -260,18 +324,18 @@
intent.setPackage(packageName);
mSatelliteServiceConnection = new SatelliteServiceConnection();
- logd("Binding to " + packageName);
+ plogd("Binding to " + packageName);
try {
boolean success = mContext.bindService(
intent, mSatelliteServiceConnection, Context.BIND_AUTO_CREATE);
if (success) {
- logd("Successfully bound to the satellite service.");
+ plogd("Successfully bound to the satellite service.");
} else {
synchronized (mLock) {
mIsBinding = false;
}
mExponentialBackoff.notifyFailed();
- loge("Error binding to the satellite service. Retrying in "
+ ploge("Error binding to the satellite service. Retrying in "
+ mExponentialBackoff.getCurrentDelay() + " ms.");
}
} catch (Exception e) {
@@ -279,7 +343,7 @@
mIsBinding = false;
}
mExponentialBackoff.notifyFailed();
- loge("Exception binding to the satellite service. Retrying in "
+ ploge("Exception binding to the satellite service. Retrying in "
+ mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e);
}
}
@@ -299,7 +363,7 @@
private class SatelliteServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- logd("onServiceConnected: ComponentName=" + name);
+ plogd("onServiceConnected: ComponentName=" + name);
synchronized (mLock) {
mIsBound = true;
mIsBinding = false;
@@ -307,17 +371,18 @@
mSatelliteService = ISatellite.Stub.asInterface(service);
mExponentialBackoff.stop();
try {
- mSatelliteService.setSatelliteListener(mListener);
+ mSatelliteService.setSatelliteListener(mVendorListener);
+ mDemoSimulator.setSatelliteListener(mDemoListener);
} catch (RemoteException e) {
// TODO: Retry setSatelliteListener
- logd("setSatelliteListener: RemoteException " + e);
+ plogd("setSatelliteListener: RemoteException " + e);
}
mSatelliteController.onSatelliteServiceConnected();
}
@Override
public void onServiceDisconnected(ComponentName name) {
- loge("onServiceDisconnected: Waiting for reconnect.");
+ ploge("onServiceDisconnected: Waiting for reconnect.");
synchronized (mLock) {
mIsBinding = false;
}
@@ -327,7 +392,7 @@
@Override
public void onBindingDied(ComponentName name) {
- loge("onBindingDied: Unbinding and rebinding service.");
+ ploge("onBindingDied: Unbinding and rebinding service.");
synchronized (mLock) {
mIsBound = false;
mIsBinding = false;
@@ -505,6 +570,27 @@
}
/**
+ * Registers for the satellite supported state changed.
+ *
+ * @param h Handler for notification message.
+ * @param what User-defined message code.
+ * @param obj User object.
+ */
+ public void registerForSatelliteSupportedStateChanged(
+ @NonNull Handler h, int what, @Nullable Object obj) {
+ mSatelliteSupportedStateChangedRegistrants.add(h, what, obj);
+ }
+
+ /**
+ * Unregisters for the satellite supported state changed.
+ *
+ * @param h Handler to be removed from the registrant list.
+ */
+ public void unregisterForSatelliteSupportedStateChanged(@NonNull Handler h) {
+ mSatelliteSupportedStateChangedRegistrants.remove(h);
+ }
+
+ /**
* Request to enable or disable the satellite service listening mode.
* Listening mode allows the satellite service to listen for incoming pages.
*
@@ -522,7 +608,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestSatelliteListeningEnabled: " + error);
+ plogd("requestSatelliteListeningEnabled: " + error);
Binder.withCleanCallingIdentity(() -> {
if (message != null) {
sendMessageWithResult(message, null, error);
@@ -531,14 +617,14 @@
}
});
} catch (RemoteException e) {
- loge("requestSatelliteListeningEnabled: RemoteException " + e);
+ ploge("requestSatelliteListeningEnabled: RemoteException " + e);
if (message != null) {
sendMessageWithResult(
message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
}
} else {
- loge("requestSatelliteListeningEnabled: Satellite service is unavailable.");
+ ploge("requestSatelliteListeningEnabled: Satellite service is unavailable.");
if (message != null) {
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -556,28 +642,35 @@
@Nullable Message message) {
if (mSatelliteService != null) {
try {
- mSatelliteService.enableCellularModemWhileSatelliteModeIsOn(enabled,
- new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("enableCellularModemWhileSatelliteModeIsOn: " + error);
- Binder.withCleanCallingIdentity(() -> {
- if (message != null) {
- sendMessageWithResult(message, null, error);
- }
- });
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ int error = SatelliteServiceUtils.fromSatelliteError(result);
+ plogd("enableCellularModemWhileSatelliteModeIsOn: " + error);
+ Binder.withCleanCallingIdentity(() -> {
+ if (message != null) {
+ sendMessageWithResult(message, null, error);
}
});
+ }
+ };
+
+ if (mSatelliteController.isDemoModeEnabled()) {
+ mDemoSimulator.enableCellularModemWhileSatelliteModeIsOn(
+ enabled, errorCallback);
+ } else {
+ mSatelliteService.enableCellularModemWhileSatelliteModeIsOn(
+ enabled, errorCallback);
+ }
} catch (RemoteException e) {
- loge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
+ ploge("enableCellularModemWhileSatelliteModeIsOn: RemoteException " + e);
if (message != null) {
sendMessageWithResult(
message, null, SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
}
} else {
- loge("enableCellularModemWhileSatelliteModeIsOn: Satellite service is unavailable.");
+ ploge("enableCellularModemWhileSatelliteModeIsOn: Satellite service is unavailable.");
if (message != null) {
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -591,29 +684,30 @@
*
* @param enableSatellite True to enable the satellite modem and false to disable.
* @param enableDemoMode True to enable demo mode and false to disable.
+ * @param isEmergency {@code true} to enable emergency mode, {@code false} otherwise.
* @param message The Message to send to result of the operation to.
*/
public void requestSatelliteEnabled(boolean enableSatellite, boolean enableDemoMode,
- @NonNull Message message) {
+ boolean isEmergency, @NonNull Message message) {
if (mSatelliteService != null) {
try {
mSatelliteService.requestSatelliteEnabled(enableSatellite, enableDemoMode,
- new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("setSatelliteEnabled: " + error);
- Binder.withCleanCallingIdentity(() ->
+ isEmergency, new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ int error = SatelliteServiceUtils.fromSatelliteError(result);
+ plogd("setSatelliteEnabled: " + error);
+ Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("setSatelliteEnabled: RemoteException " + e);
+ ploge("setSatelliteEnabled: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("setSatelliteEnabled: Satellite service is unavailable.");
+ ploge("setSatelliteEnabled: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -631,7 +725,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestIsSatelliteEnabled: " + error);
+ plogd("requestIsSatelliteEnabled: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
@@ -641,18 +735,18 @@
// Convert for compatibility with SatelliteResponse
// TODO: This should just report result instead.
int[] enabled = new int[] {result ? 1 : 0};
- logd("requestIsSatelliteEnabled: " + Arrays.toString(enabled));
+ plogd("requestIsSatelliteEnabled: " + Arrays.toString(enabled));
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, enabled, SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
});
} catch (RemoteException e) {
- loge("requestIsSatelliteEnabled: RemoteException " + e);
+ ploge("requestIsSatelliteEnabled: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestIsSatelliteEnabled: Satellite service is unavailable.");
+ ploge("requestIsSatelliteEnabled: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -670,25 +764,25 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestIsSatelliteSupported: " + error);
+ plogd("requestIsSatelliteSupported: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
}, new IBooleanConsumer.Stub() {
@Override
public void accept(boolean result) {
- logd("requestIsSatelliteSupported: " + result);
+ plogd("requestIsSatelliteSupported: " + result);
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, result, SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
});
} catch (RemoteException e) {
- loge("requestIsSatelliteSupported: RemoteException " + e);
+ ploge("requestIsSatelliteSupported: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestIsSatelliteSupported: Satellite service is unavailable.");
+ ploge("requestIsSatelliteSupported: Satellite service is unavailable.");
sendMessageWithResult(
message, null, SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -706,7 +800,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestSatelliteCapabilities: " + error);
+ plogd("requestSatelliteCapabilities: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
@@ -716,18 +810,18 @@
result) {
SatelliteCapabilities capabilities =
SatelliteServiceUtils.fromSatelliteCapabilities(result);
- logd("requestSatelliteCapabilities: " + capabilities);
+ plogd("requestSatelliteCapabilities: " + capabilities);
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, capabilities, SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
});
} catch (RemoteException e) {
- loge("requestSatelliteCapabilities: RemoteException " + e);
+ ploge("requestSatelliteCapabilities: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestSatelliteCapabilities: Satellite service is unavailable.");
+ ploge("requestSatelliteCapabilities: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -747,18 +841,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("startSendingSatellitePointingInfo: " + error);
+ plogd("startSendingSatellitePointingInfo: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("startSendingSatellitePointingInfo: RemoteException " + e);
+ ploge("startSendingSatellitePointingInfo: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("startSendingSatellitePointingInfo: Satellite service is unavailable.");
+ ploge("startSendingSatellitePointingInfo: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -777,18 +871,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("stopSendingSatellitePointingInfo: " + error);
+ plogd("stopSendingSatellitePointingInfo: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("stopSendingSatellitePointingInfo: RemoteException " + e);
+ ploge("stopSendingSatellitePointingInfo: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("stopSendingSatellitePointingInfo: Satellite service is unavailable.");
+ ploge("stopSendingSatellitePointingInfo: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -813,18 +907,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("provisionSatelliteService: " + error);
+ plogd("provisionSatelliteService: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("provisionSatelliteService: RemoteException " + e);
+ ploge("provisionSatelliteService: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("provisionSatelliteService: Satellite service is unavailable.");
+ ploge("provisionSatelliteService: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -845,18 +939,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("deprovisionSatelliteService: " + error);
+ plogd("deprovisionSatelliteService: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("deprovisionSatelliteService: RemoteException " + e);
+ ploge("deprovisionSatelliteService: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("deprovisionSatelliteService: Satellite service is unavailable.");
+ ploge("deprovisionSatelliteService: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -874,7 +968,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestIsSatelliteProvisioned: " + error);
+ plogd("requestIsSatelliteProvisioned: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
@@ -884,18 +978,18 @@
// Convert for compatibility with SatelliteResponse
// TODO: This should just report result instead.
int[] provisioned = new int[] {result ? 1 : 0};
- logd("requestIsSatelliteProvisioned: " + Arrays.toString(provisioned));
+ plogd("requestIsSatelliteProvisioned: " + Arrays.toString(provisioned));
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, provisioned, SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
});
} catch (RemoteException e) {
- loge("requestIsSatelliteProvisioned: RemoteException " + e);
+ ploge("requestIsSatelliteProvisioned: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestIsSatelliteProvisioned: Satellite service is unavailable.");
+ ploge("requestIsSatelliteProvisioned: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -915,18 +1009,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("pollPendingDatagrams: " + error);
+ plogd("pollPendingDatagrams: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("pollPendingDatagrams: RemoteException " + e);
+ ploge("pollPendingDatagrams: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("pollPendingDatagrams: Satellite service is unavailable.");
+ ploge("pollPendingDatagrams: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -951,18 +1045,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("sendDatagram: " + error);
+ plogd("sendDatagram: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("sendDatagram: RemoteException " + e);
+ ploge("sendDatagram: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("sendDatagram: Satellite service is unavailable.");
+ ploge("sendDatagram: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -982,7 +1076,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestSatelliteModemState: " + error);
+ plogd("requestSatelliteModemState: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
@@ -991,60 +1085,18 @@
public void accept(int result) {
// Convert SatelliteModemState from service to frameworks definition.
int modemState = SatelliteServiceUtils.fromSatelliteModemState(result);
- logd("requestSatelliteModemState: " + modemState);
+ plogd("requestSatelliteModemState: " + modemState);
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, modemState, SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
});
} catch (RemoteException e) {
- loge("requestSatelliteModemState: RemoteException " + e);
+ ploge("requestSatelliteModemState: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestSatelliteModemState: Satellite service is unavailable.");
- sendMessageWithResult(message, null,
- SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
- }
- }
-
- /**
- * Request to get whether satellite communication is allowed for the current location.
- *
- * @param message The Message to send to result of the operation to.
- */
- public void requestIsSatelliteCommunicationAllowedForCurrentLocation(@NonNull Message message) {
- if (mSatelliteService != null) {
- try {
- mSatelliteService.requestIsSatelliteCommunicationAllowedForCurrentLocation(
- new IIntegerConsumer.Stub() {
- @Override
- public void accept(int result) {
- int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestIsCommunicationAllowedForCurrentLocation: "
- + error);
- Binder.withCleanCallingIdentity(() ->
- sendMessageWithResult(message, null, error));
- }
- }, new IBooleanConsumer.Stub() {
- @Override
- public void accept(boolean result) {
- logd("requestIsCommunicationAllowedForCurrentLocation: "
- + result);
- Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
- message, result,
- SatelliteManager.SATELLITE_RESULT_SUCCESS));
- }
- });
- } catch (RemoteException e) {
- loge("requestIsCommunicationAllowedForCurrentLocation: RemoteException "
- + e);
- sendMessageWithResult(message, null,
- SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
- }
- } else {
- loge("requestIsCommunicationAllowedForCurrentLocation: "
- + "Satellite service is unavailable.");
+ ploge("requestSatelliteModemState: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1065,7 +1117,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestTimeForNextSatelliteVisibility: " + error);
+ plogd("requestTimeForNextSatelliteVisibility: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
@@ -1075,19 +1127,19 @@
// Convert for compatibility with SatelliteResponse
// TODO: This should just report result instead.
int[] time = new int[] {result};
- logd("requestTimeForNextSatelliteVisibility: "
+ plogd("requestTimeForNextSatelliteVisibility: "
+ Arrays.toString(time));
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, time, SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
});
} catch (RemoteException e) {
- loge("requestTimeForNextSatelliteVisibility: RemoteException " + e);
+ ploge("requestTimeForNextSatelliteVisibility: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestTimeForNextSatelliteVisibility: Satellite service is unavailable.");
+ ploge("requestTimeForNextSatelliteVisibility: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1120,18 +1172,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("setSatellitePlmn: " + error);
+ plogd("setSatellitePlmn: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("setSatellitePlmn: RemoteException " + e);
+ ploge("setSatellitePlmn: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("setSatellitePlmn: Satellite service is unavailable.");
+ ploge("setSatellitePlmn: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1155,18 +1207,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestSetSatelliteEnabledForCarrier: " + error);
+ plogd("requestSetSatelliteEnabledForCarrier: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("requestSetSatelliteEnabledForCarrier: RemoteException " + e);
+ ploge("requestSetSatelliteEnabledForCarrier: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestSetSatelliteEnabledForCarrier: Satellite service is unavailable.");
+ ploge("requestSetSatelliteEnabledForCarrier: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED);
}
@@ -1188,7 +1240,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestIsSatelliteEnabledForCarrier: " + error);
+ plogd("requestIsSatelliteEnabledForCarrier: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
@@ -1198,7 +1250,7 @@
// Convert for compatibility with SatelliteResponse
// TODO: This should just report result instead.
int[] enabled = new int[] {result ? 1 : 0};
- logd("requestIsSatelliteEnabledForCarrier: "
+ plogd("requestIsSatelliteEnabledForCarrier: "
+ Arrays.toString(enabled));
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, enabled,
@@ -1206,12 +1258,12 @@
}
});
} catch (RemoteException e) {
- loge("requestIsSatelliteEnabledForCarrier: RemoteException " + e);
+ ploge("requestIsSatelliteEnabledForCarrier: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestIsSatelliteEnabledForCarrier: Satellite service is unavailable.");
+ ploge("requestIsSatelliteEnabledForCarrier: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1230,7 +1282,7 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("requestNtnSignalStrength: " + error);
+ plogd("requestNtnSignalStrength: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
@@ -1240,19 +1292,19 @@
android.telephony.satellite.stub.NtnSignalStrength result) {
NtnSignalStrength ntnSignalStrength =
SatelliteServiceUtils.fromNtnSignalStrength(result);
- logd("requestNtnSignalStrength: " + ntnSignalStrength);
+ plogd("requestNtnSignalStrength: " + ntnSignalStrength);
Binder.withCleanCallingIdentity(() -> sendMessageWithResult(
message, ntnSignalStrength,
SatelliteManager.SATELLITE_RESULT_SUCCESS));
}
});
} catch (RemoteException e) {
- loge("requestNtnSignalStrength: RemoteException " + e);
+ ploge("requestNtnSignalStrength: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("requestNtnSignalStrength: Satellite service is unavailable.");
+ ploge("requestNtnSignalStrength: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1271,18 +1323,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("startSendingNtnSignalStrength: " + error);
+ plogd("startSendingNtnSignalStrength: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("startSendingNtnSignalStrength: RemoteException " + e);
+ ploge("startSendingNtnSignalStrength: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("startSendingNtnSignalStrength: Satellite service is unavailable.");
+ ploge("startSendingNtnSignalStrength: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1300,18 +1352,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("stopSendingNtnSignalStrength: " + error);
+ plogd("stopSendingNtnSignalStrength: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("stopSendingNtnSignalStrength: RemoteException " + e);
+ ploge("stopSendingNtnSignalStrength: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("stopSendingNtnSignalStrength: Satellite service is unavailable.");
+ ploge("stopSendingNtnSignalStrength: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1329,18 +1381,18 @@
@Override
public void accept(int result) {
int error = SatelliteServiceUtils.fromSatelliteError(result);
- logd("abortSendingSatelliteDatagrams: " + error);
+ plogd("abortSendingSatelliteDatagrams: " + error);
Binder.withCleanCallingIdentity(() ->
sendMessageWithResult(message, null, error));
}
});
} catch (RemoteException e) {
- loge("abortSendingSatelliteDatagrams: RemoteException " + e);
+ ploge("abortSendingSatelliteDatagrams: RemoteException " + e);
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
}
} else {
- loge("abortSendingSatelliteDatagrams: Satellite service is unavailable.");
+ ploge("abortSendingSatelliteDatagrams: Satellite service is unavailable.");
sendMessageWithResult(message, null,
SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
}
@@ -1366,7 +1418,7 @@
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public void setSatelliteServicePackageName(@Nullable String servicePackageName) {
- logd("setSatelliteServicePackageName: config_satellite_service_package is "
+ plogd("setSatelliteServicePackageName: config_satellite_service_package is "
+ "updated, new packageName=" + servicePackageName);
mExponentialBackoff.stop();
if (mSatelliteServiceConnection != null) {
@@ -1403,4 +1455,31 @@
private static void loge(@NonNull String log) {
Rlog.e(TAG, log);
}
+
+ private boolean isSatellitePersistentLoggingEnabled(
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (featureFlags.satellitePersistentLogging()) {
+ return true;
+ }
+ try {
+ return context.getResources().getBoolean(
+ R.bool.config_dropboxmanager_persistent_logging_enabled);
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ private void plogd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
+ private void ploge(@NonNull String log) {
+ Rlog.e(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.error(TAG, log);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
index c491476..3fe2970 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommender.java
@@ -24,6 +24,7 @@
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911;
+import static com.android.internal.telephony.flags.Flags.satellitePersistentLogging;
import static com.android.internal.telephony.satellite.SatelliteController.INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
import android.annotation.NonNull;
@@ -33,6 +34,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -41,6 +43,10 @@
import android.os.SystemProperties;
import android.provider.DeviceConfig;
import android.telecom.Connection;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -64,6 +70,7 @@
import com.android.internal.telephony.SmsApplication;
import com.android.internal.telephony.metrics.SatelliteStats;
+import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -99,7 +106,8 @@
private boolean mIsSatelliteAllowedForCurrentLocation = false;
@GuardedBy("mLock")
private boolean mCheckingAccessRestrictionInProgress = false;
- private final long mTimeoutMillis;
+ protected long mTimeoutMillis = 0;
+ private final long mOemEnabledTimeoutMillis;
private final AtomicBoolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime =
new AtomicBoolean(false);
@GuardedBy("mLock")
@@ -107,15 +115,17 @@
protected int mCountOfTimerStarted = 0;
private final Object mLock = new Object();
+ @Nullable private PersistentLogger mPersistentLogger = null;
+
/**
* Create an instance of SatelliteSOSMessageRecommender.
*
* @param context The Context for the SatelliteSOSMessageRecommender.
* @param looper The looper used with the handler of this class.
*/
- public SatelliteSOSMessageRecommender(@NonNull Context context, @NonNull Looper looper) {
- this(context, looper, SatelliteController.getInstance(), null,
- getEmergencyCallWaitForConnectionTimeoutMillis(context));
+ public SatelliteSOSMessageRecommender(@NonNull Context context,
+ @NonNull Looper looper) {
+ this(context, looper, SatelliteController.getInstance(), null);
}
/**
@@ -127,21 +137,25 @@
* @param satelliteController The SatelliteController singleton instance.
* @param imsManager The ImsManager instance associated with the phone, which is used for making
* the emergency call. This argument is not null only in unit tests.
- * @param timeoutMillis The timeout duration of the timer.
*/
@VisibleForTesting
protected SatelliteSOSMessageRecommender(@NonNull Context context, @NonNull Looper looper,
- @NonNull SatelliteController satelliteController, ImsManager imsManager,
- long timeoutMillis) {
+ @NonNull SatelliteController satelliteController,
+ ImsManager imsManager) {
super(looper);
+ if (isSatellitePersistentLoggingEnabled(context)) {
+ mPersistentLogger = new PersistentLogger(
+ DropBoxManagerLoggerBackend.getInstance(context));
+ }
mContext = context;
mSatelliteController = satelliteController;
mImsManager = imsManager;
- mTimeoutMillis = timeoutMillis;
+ mOemEnabledTimeoutMillis =
+ getOemEnabledEmergencyCallWaitForConnectionTimeoutMillis(context);
mISatelliteProvisionStateCallback = new ISatelliteProvisionStateCallback.Stub() {
@Override
public void onSatelliteProvisionStateChanged(boolean provisioned) {
- logd("onSatelliteProvisionStateChanged: provisioned=" + provisioned);
+ plogd("onSatelliteProvisionStateChanged: provisioned=" + provisioned);
sendMessage(obtainMessage(EVENT_SATELLITE_PROVISIONED_STATE_CHANGED, provisioned));
}
};
@@ -172,7 +186,7 @@
handleSatelliteAccessRestrictionCheckingResult((boolean) msg.obj);
break;
default:
- logd("handleMessage: unexpected message code: " + msg.what);
+ plogd("handleMessage: unexpected message code: " + msg.what);
break;
}
}
@@ -184,9 +198,13 @@
* call.
*/
public void onEmergencyCallStarted(@NonNull Connection connection) {
- if (!mSatelliteController.isSatelliteSupportedViaOem()
- && !mSatelliteController.isSatelliteSupportedViaCarrier()) {
- logd("onEmergencyCallStarted: satellite is not supported");
+ if (!isSatelliteSupported()) {
+ plogd("onEmergencyCallStarted: satellite is not supported");
+ return;
+ }
+
+ if (hasMessages(EVENT_EMERGENCY_CALL_STARTED)) {
+ logd("onEmergencyCallStarted: Ignoring due to ongoing event:");
return;
}
@@ -210,10 +228,9 @@
*/
public void onEmergencyCallConnectionStateChanged(
String callId, @Connection.ConnectionState int state) {
- logd("callId=" + callId + ", state=" + state);
- if (!mSatelliteController.isSatelliteSupportedViaOem()
- && !mSatelliteController.isSatelliteSupportedViaCarrier()) {
- logd("onEmergencyCallConnectionStateChanged: satellite is not supported");
+ plogd("callId=" + callId + ", state=" + state);
+ if (!isSatelliteSupported()) {
+ plogd("onEmergencyCallConnectionStateChanged: satellite is not supported");
return;
}
Pair<String, Integer> argument = new Pair<>(callId, state);
@@ -222,13 +239,17 @@
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected ComponentName getDefaultSmsApp() {
- return SmsApplication.getDefaultSmsApplication(mContext, false);
+ return SmsApplication.getDefaultSendToApplication(mContext, false);
}
private void handleEmergencyCallStartedEvent(@NonNull Connection connection) {
+ mSatelliteController.setLastEmergencyCallTime();
+
if (sendEventDisplayEmergencyMessageForcefully(connection)) {
return;
}
+
+ selectEmergencyCallWaitForConnectionTimeoutDuration();
if (mEmergencyConnection == null) {
handleStateChangedEventForHysteresisTimer();
registerForInterestedStateChangedEvents();
@@ -256,12 +277,12 @@
private void evaluateSendingConnectionEventDisplayEmergencyMessage() {
synchronized (mLock) {
if (mEmergencyConnection == null) {
- loge("No emergency call is ongoing...");
+ ploge("No emergency call is ongoing...");
return;
}
if (!mIsTimerTimedOut || mCheckingAccessRestrictionInProgress) {
- logd("mIsTimerTimedOut=" + mIsTimerTimedOut
+ plogd("mIsTimerTimedOut=" + mIsTimerTimedOut
+ ", mCheckingAccessRestrictionInProgress="
+ mCheckingAccessRestrictionInProgress);
return;
@@ -275,18 +296,18 @@
updateSatelliteViaCarrierAvailability();
boolean isDialerNotified = false;
- if (!isImsRegistered() && !isCellularAvailable()
+ if (!isCellularAvailable()
&& isSatelliteAllowed()
&& (isSatelliteViaOemAvailable() || isSatelliteViaCarrierAvailable())
&& shouldTrackCall(mEmergencyConnection.getState())) {
- logd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
+ plogd("handleTimeoutEvent: Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer");
Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
mEmergencyConnection.sendConnectionEvent(
TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
isDialerNotified = true;
}
- logd("handleTimeoutEvent: isImsRegistered=" + isImsRegistered()
+ plogd("handleTimeoutEvent: isImsRegistered=" + isImsRegistered()
+ ", isCellularAvailable=" + isCellularAvailable()
+ ", isSatelliteAllowed=" + isSatelliteAllowed()
+ ", shouldTrackCall=" + shouldTrackCall(mEmergencyConnection.getState()));
@@ -325,6 +346,7 @@
private void handleEmergencyCallConnectionStateChangedEvent(
@NonNull Pair<String, Integer> arg) {
+ mSatelliteController.setLastEmergencyCallTime();
if (mEmergencyConnection == null) {
// Either the call was not created or the timer already timed out.
return;
@@ -333,7 +355,7 @@
String callId = arg.first;
int state = arg.second;
if (!mEmergencyConnection.getTelecomCallId().equals(callId)) {
- loge("handleEmergencyCallConnectionStateChangedEvent: unexpected state changed event "
+ ploge("handleEmergencyCallConnectionStateChangedEvent: unexpected state changed event "
+ ", mEmergencyConnection=" + mEmergencyConnection + ", callId=" + callId
+ ", state=" + state);
/*
@@ -402,7 +424,7 @@
imsManager.addRegistrationCallback(
getOrCreateImsRegistrationCallback(phone.getPhoneId()), this::post);
} catch (ImsException ex) {
- loge("registerForImsRegistrationStateChanged: ex=" + ex);
+ ploge("registerForImsRegistrationStateChanged: ex=" + ex);
}
}
@@ -423,7 +445,7 @@
imsManager.removeRegistrationListener(
mImsRegistrationCallbacks.get(phone.getPhoneId()));
} else {
- loge("Phone ID=" + phone.getPhoneId() + " was not registered with ImsManager");
+ ploge("Phone ID=" + phone.getPhoneId() + " was not registered with ImsManager");
}
}
@@ -432,12 +454,43 @@
ServiceState serviceState = phone.getServiceState();
if (serviceState != null) {
int state = serviceState.getState();
- if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY)
- && !serviceState.isUsingNonTerrestrialNetwork()) {
+ if ((state == STATE_IN_SERVICE || state == STATE_EMERGENCY_ONLY
+ || serviceState.isEmergencyOnly())
+ && !isSatellitePlmn(phone.getSubId(), serviceState)) {
+ logv("isCellularAvailable true");
return true;
}
}
}
+ logv("isCellularAvailable false");
+ return false;
+ }
+
+ private boolean isSatellitePlmn(int subId, @NonNull ServiceState serviceState) {
+ List<String> satellitePlmnList =
+ mSatelliteController.getSatellitePlmnsForCarrier(subId);
+ if (satellitePlmnList.isEmpty()) {
+ logv("isSatellitePlmn: satellitePlmnList is empty");
+ return false;
+ }
+
+ for (NetworkRegistrationInfo nri :
+ serviceState.getNetworkRegistrationInfoListForTransportType(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN)) {
+ String registeredPlmn = nri.getRegisteredPlmn();
+ String mccmnc = nri.getCellIdentity().getMccString()
+ + nri.getCellIdentity().getMncString();
+ for (String satellitePlmn : satellitePlmnList) {
+ if (TextUtils.equals(satellitePlmn, registeredPlmn)
+ || TextUtils.equals(satellitePlmn, mccmnc)) {
+ logv("isSatellitePlmn: return true, satellitePlmn:" + satellitePlmn
+ + " registeredPlmn:" + registeredPlmn + " mccmnc:" + mccmnc);
+ return true;
+ }
+ }
+ }
+
+ logv("isSatellitePlmn: return false");
return false;
}
@@ -472,9 +525,10 @@
}
private synchronized void handleStateChangedEventForHysteresisTimer() {
- if (!isImsRegistered() && !isCellularAvailable()) {
+ if (!isCellularAvailable()) {
startTimer();
} else {
+ logv("handleStateChangedEventForHysteresisTimer stopTimer");
stopTimer();
}
}
@@ -487,6 +541,7 @@
sendMessageDelayed(obtainMessage(EVENT_TIME_OUT), mTimeoutMillis);
mCountOfTimerStarted++;
mIsTimerTimedOut = false;
+ logd("startTimer mCountOfTimerStarted=" + mCountOfTimerStarted);
}
}
@@ -504,7 +559,18 @@
}
}
- private static long getEmergencyCallWaitForConnectionTimeoutMillis(@NonNull Context context) {
+ private void selectEmergencyCallWaitForConnectionTimeoutDuration() {
+ if (mSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier()) {
+ mTimeoutMillis =
+ mSatelliteController.getCarrierEmergencyCallWaitForConnectionTimeoutMillis();
+ } else {
+ mTimeoutMillis = mOemEnabledTimeoutMillis;
+ }
+ plogd("mTimeoutMillis = " + mTimeoutMillis);
+ }
+
+ private static long getOemEnabledEmergencyCallWaitForConnectionTimeoutMillis(
+ @NonNull Context context) {
return context.getResources().getInteger(
R.integer.config_emergency_call_wait_for_connection_timeout_millis);
}
@@ -608,21 +674,34 @@
packageName = defaultSmsAppComponent.getPackageName();
className = defaultSmsAppComponent.getClassName();
}
- logd("EVENT_DISPLAY_EMERGENCY_MESSAGE: handoverType=" + handoverType + ", packageName="
+ plogd("EVENT_DISPLAY_EMERGENCY_MESSAGE: handoverType=" + handoverType + ", packageName="
+ packageName + ", className=" + className + ", action=" + action);
Bundle result = new Bundle();
result.putInt(EXTRA_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE, handoverType);
if (!TextUtils.isEmpty(packageName) && !TextUtils.isEmpty(className)) {
result.putParcelable(EXTRA_EMERGENCY_CALL_TO_SATELLITE_LAUNCH_INTENT,
- createHandoverAppLaunchPendingIntent(packageName, className, action));
+ createHandoverAppLaunchPendingIntent(
+ handoverType, packageName, className, action));
}
return result;
}
- @NonNull private PendingIntent createHandoverAppLaunchPendingIntent(
+ @NonNull private PendingIntent createHandoverAppLaunchPendingIntent(int handoverType,
@NonNull String packageName, @NonNull String className, @Nullable String action) {
- Intent intent = new Intent(action);
+ Intent intent;
+ if (handoverType == EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911) {
+ String emergencyNumber = "911";
+ if (mEmergencyConnection != null) {
+ emergencyNumber = mEmergencyConnection.getAddress().getSchemeSpecificPart();
+ }
+ plogd("emergencyNumber=" + emergencyNumber);
+
+ Uri uri = Uri.parse("smsto:" + emergencyNumber);
+ intent = new Intent(Intent.ACTION_SENDTO, uri);
+ } else {
+ intent = new Intent(action);
+ }
intent.setComponent(new ComponentName(packageName, className));
return PendingIntent.getActivity(mContext, 0, intent,
PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_IMMUTABLE);
@@ -648,15 +727,17 @@
private void handleCmdSendEventDisplayEmergencyMessageForcefully(
@NonNull Connection connection) {
- logd("Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer forcefully.");
+ plogd("Sent EVENT_DISPLAY_EMERGENCY_MESSAGE to Dialer forcefully.");
+ mEmergencyConnection = connection;
Bundle extras = createExtraBundleForEventDisplayEmergencyMessage();
connection.sendConnectionEvent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE, extras);
+ mEmergencyConnection = null;
}
private boolean isMultiSim() {
TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
if (telephonyManager == null) {
- loge("isMultiSim: telephonyManager is null");
+ ploge("isMultiSim: telephonyManager is null");
return false;
}
return telephonyManager.isMultiSimEnabled();
@@ -673,7 +754,7 @@
private void requestIsSatelliteAllowedForCurrentLocation() {
synchronized (mLock) {
if (mCheckingAccessRestrictionInProgress) {
- logd("requestIsSatelliteCommunicationAllowedForCurrentLocation was already sent");
+ plogd("requestIsSatelliteCommunicationAllowedForCurrentLocation was already sent");
return;
}
mCheckingAccessRestrictionInProgress = true;
@@ -683,14 +764,14 @@
new OutcomeReceiver<>() {
@Override
public void onResult(Boolean result) {
- logd("requestIsSatelliteAllowedForCurrentLocation: result=" + result);
+ plogd("requestIsSatelliteAllowedForCurrentLocation: result=" + result);
sendMessage(obtainMessage(
EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT, result));
}
@Override
public void onError(SatelliteManager.SatelliteException ex) {
- logd("requestIsSatelliteAllowedForCurrentLocation: onError, ex=" + ex);
+ plogd("requestIsSatelliteAllowedForCurrentLocation: onError, ex=" + ex);
sendMessage(obtainMessage(
EVENT_SATELLITE_ACCESS_RESTRICTION_CHECKING_RESULT, false));
}
@@ -711,6 +792,23 @@
|| SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false));
}
+ private boolean isSatelliteSupported() {
+ if (mSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier()) return true;
+ if (mSatelliteController.isSatelliteSupportedViaOem() && isSatelliteViaOemProvisioned()) {
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isSatelliteViaOemProvisioned() {
+ Boolean provisioned = mSatelliteController.isSatelliteViaOemProvisioned();
+ return (provisioned != null) && provisioned;
+ }
+
+ private static void logv(@NonNull String log) {
+ Rlog.v(TAG, log);
+ }
+
private static void logd(@NonNull String log) {
Rlog.d(TAG, log);
}
@@ -718,4 +816,31 @@
private static void loge(@NonNull String log) {
Rlog.e(TAG, log);
}
+
+ private boolean isSatellitePersistentLoggingEnabled(
+ @NonNull Context context) {
+ if (satellitePersistentLogging()) {
+ return true;
+ }
+ try {
+ return context.getResources().getBoolean(
+ R.bool.config_dropboxmanager_persistent_logging_enabled);
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ private void plogd(@NonNull String log) {
+ Rlog.d(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
+ private void ploge(@NonNull String log) {
+ Rlog.e(TAG, log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.error(TAG, log);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
index 0e6f706..d33fd73 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteServiceUtils.java
@@ -16,9 +16,6 @@
package com.android.internal.telephony.satellite;
-import static android.telephony.NetworkRegistrationInfo.FIRST_SERVICE_TYPE;
-import static android.telephony.NetworkRegistrationInfo.LAST_SERVICE_TYPE;
-
import static java.util.stream.Collectors.joining;
import android.annotation.NonNull;
@@ -43,6 +40,7 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
+import com.android.internal.telephony.util.TelephonyUtils;
import java.util.Arrays;
import java.util.HashMap;
@@ -302,19 +300,23 @@
}
for (String plmn : supportedServicesBundle.keySet()) {
- Set<Integer> supportedServicesSet = new HashSet<>();
- for (int serviceType : supportedServicesBundle.getIntArray(plmn)) {
- if (isServiceTypeValid(serviceType)) {
- supportedServicesSet.add(serviceType);
- } else {
- loge("parseSupportedSatelliteServices: invalid service type=" + serviceType
- + " for plmn=" + plmn);
+ if (TelephonyUtils.isValidPlmn(plmn)) {
+ Set<Integer> supportedServicesSet = new HashSet<>();
+ for (int serviceType : supportedServicesBundle.getIntArray(plmn)) {
+ if (TelephonyUtils.isValidService(serviceType)) {
+ supportedServicesSet.add(serviceType);
+ } else {
+ loge("parseSupportedSatelliteServices: invalid service type=" + serviceType
+ + " for plmn=" + plmn);
+ }
}
+ logd("parseSupportedSatelliteServices: plmn=" + plmn + ", supportedServicesSet="
+ + supportedServicesSet.stream().map(String::valueOf).collect(
+ joining(",")));
+ supportedServicesMap.put(plmn, supportedServicesSet);
+ } else {
+ loge("parseSupportedSatelliteServices: invalid plmn=" + plmn);
}
- logd("parseSupportedSatelliteServices: plmn=" + plmn + ", supportedServicesSet="
- + supportedServicesSet.stream().map(String::valueOf).collect(
- joining(",")));
- supportedServicesMap.put(plmn, supportedServicesSet);
}
return supportedServicesMap;
}
@@ -330,8 +332,39 @@
return mergedStrSet.stream().toList();
}
- private static boolean isServiceTypeValid(int serviceType) {
- return (serviceType >= FIRST_SERVICE_TYPE && serviceType <= LAST_SERVICE_TYPE);
+ /**
+ * Merge three string lists into one such that the result list does not have any duplicate
+ * items.
+ */
+ @NonNull
+ public static List<String> mergeStrLists(List<String> strList1, List<String> strList2,
+ List<String> strList3) {
+ Set<String> mergedStrSet = new HashSet<>();
+ mergedStrSet.addAll(strList1);
+ mergedStrSet.addAll(strList2);
+ mergedStrSet.addAll(strList3);
+ return mergedStrSet.stream().toList();
+ }
+
+ /**
+ * Check if the datagramType is the sos message (DATAGRAM_TYPE_SOS_MESSAGE,
+ * DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP,
+ * DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED) or not
+ */
+ public static boolean isSosMessage(int datagramType) {
+ return datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE
+ || datagramType == SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP
+ || datagramType == SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED;
+ }
+
+ /**
+ * Check if the datagramType is the last sos message
+ * (DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP or
+ * DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED) or not
+ */
+ public static boolean isLastSosMessage(int datagramType) {
+ return datagramType == SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP
+ || datagramType == SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED;
}
/**
@@ -349,7 +382,7 @@
* @return phone associated with {@code subId} or {@code null} if it doesn't exist.
*/
public static @Nullable Phone getPhone(int subId) {
- return PhoneFactory.getPhone(subId);
+ return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
}
private static void logd(@NonNull String log) {
diff --git a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
index 5c79c28..dde10a0 100644
--- a/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
+++ b/src/java/com/android/internal/telephony/satellite/SatelliteSessionController.java
@@ -39,6 +39,8 @@
import android.os.Message;
import android.os.RemoteException;
import android.os.SystemProperties;
+import android.telephony.DropBoxManagerLoggerBackend;
+import android.telephony.PersistentLogger;
import android.telephony.Rlog;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.SatelliteManager;
@@ -51,6 +53,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ExponentialBackoff;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -101,6 +104,8 @@
private static final int EVENT_SATELLITE_MODEM_STATE_CHANGED = 4;
private static final int EVENT_DISABLE_CELLULAR_MODEM_WHILE_SATELLITE_MODE_IS_ON_DONE = 5;
protected static final int EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT = 6;
+ private static final int EVENT_SATELLITE_ENABLEMENT_STARTED = 7;
+ private static final int EVENT_SATELLITE_ENABLEMENT_FAILED = 8;
private static final long REBIND_INITIAL_DELAY = 2 * 1000; // 2 seconds
private static final long REBIND_MAXIMUM_DELAY = 64 * 1000; // 1 minute
@@ -120,6 +125,8 @@
@NonNull private final SatelliteModemInterface mSatelliteModemInterface;
@NonNull private final UnavailableState mUnavailableState = new UnavailableState();
@NonNull private final PowerOffState mPowerOffState = new PowerOffState();
+ @NonNull private final EnablingState mEnablingState = new EnablingState();
+ @NonNull private final DisablingState mDisablingState = new DisablingState();
@NonNull private final IdleState mIdleState = new IdleState();
@NonNull private final TransferringState mTransferringState = new TransferringState();
@NonNull private final ListeningState mListeningState = new ListeningState();
@@ -138,6 +145,8 @@
@NonNull private boolean mIsDisableCellularModemInProgress = false;
@NonNull private final SatelliteController mSatelliteController;
@NonNull private final DatagramController mDatagramController;
+ @Nullable private PersistentLogger mPersistentLogger = null;
+
/**
* @return The singleton instance of SatelliteSessionController.
@@ -154,20 +163,22 @@
*
* @param context The Context for the SatelliteSessionController.
* @param looper The looper associated with the handler of this class.
+ * @param featureFlags The telephony feature flags.
* @param isSatelliteSupported Whether satellite is supported on the device.
* @return The singleton instance of SatelliteSessionController.
*/
public static SatelliteSessionController make(
- @NonNull Context context, @NonNull Looper looper, boolean isSatelliteSupported) {
- if (sInstance == null) {
- sInstance = new SatelliteSessionController(context, looper, isSatelliteSupported,
+ @NonNull Context context,
+ @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
+ boolean isSatelliteSupported) {
+ if (sInstance == null || isSatelliteSupported != sInstance.mIsSatelliteSupported) {
+ sInstance = new SatelliteSessionController(
+ context,
+ looper,
+ featureFlags,
+ isSatelliteSupported,
SatelliteModemInterface.getInstance());
- } else {
- if (isSatelliteSupported != sInstance.mIsSatelliteSupported) {
- Rlog.e(TAG, "New satellite support state " + isSatelliteSupported
- + " is different from existing state " + sInstance.mIsSatelliteSupported
- + ". Ignore the new state.");
- }
}
return sInstance;
}
@@ -177,15 +188,22 @@
*
* @param context The Context for the SatelliteSessionController.
* @param looper The looper associated with the handler of this class.
+ * @param featureFlags The telephony feature flags.
* @param isSatelliteSupported Whether satellite is supported on the device.
* @param satelliteModemInterface The singleton of SatelliteModemInterface.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
protected SatelliteSessionController(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
boolean isSatelliteSupported,
@NonNull SatelliteModemInterface satelliteModemInterface) {
super(TAG, looper);
+ if (isSatellitePersistentLoggingEnabled(context, featureFlags)) {
+ mPersistentLogger = new PersistentLogger(
+ DropBoxManagerLoggerBackend.getInstance(context));
+ }
+
mContext = context;
mSatelliteModemInterface = satelliteModemInterface;
mSatelliteController = SatelliteController.getInstance();
@@ -218,9 +236,11 @@
addState(mUnavailableState);
addState(mPowerOffState);
+ addState(mEnablingState);
+ addState(mDisablingState);
addState(mIdleState);
addState(mTransferringState);
- addState(mListeningState, mTransferringState);
+ addState(mListeningState);
addState(mNotConnectedState);
addState(mConnectedState);
setInitialState(isSatelliteSupported);
@@ -258,6 +278,26 @@
/**
* {@link SatelliteController} uses this function to notify {@link SatelliteSessionController}
+ * that the satellite enablement has just started.
+ *
+ * @param enabled {@code true} means being enabled and {@code false} means being disabled.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void onSatelliteEnablementStarted(boolean enabled) {
+ sendMessage(EVENT_SATELLITE_ENABLEMENT_STARTED, enabled);
+ }
+
+ /**
+ * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController}
+ * that the satellite enablement has just failed.
+ */
+ @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+ public void onSatelliteEnablementFailed() {
+ sendMessage(EVENT_SATELLITE_ENABLEMENT_FAILED);
+ }
+
+ /**
+ * {@link SatelliteController} uses this function to notify {@link SatelliteSessionController}
* that the satellite modem state has changed.
*
* @param state The current state of the satellite modem.
@@ -278,7 +318,7 @@
callback.onSatelliteModemStateChanged(mCurrentState);
mListeners.put(callback.asBinder(), callback);
} catch (RemoteException ex) {
- loge("registerForSatelliteModemStateChanged: Got RemoteException ex=" + ex);
+ ploge("registerForSatelliteModemStateChanged: Got RemoteException ex=" + ex);
}
}
@@ -304,11 +344,11 @@
*/
boolean setSatelliteListeningTimeoutDuration(long timeoutMillis) {
if (!isMockModemAllowed()) {
- loge("Updating listening timeout duration is not allowed");
+ ploge("Updating listening timeout duration is not allowed");
return false;
}
- logd("setSatelliteListeningTimeoutDuration: timeoutMillis=" + timeoutMillis);
+ plogd("setSatelliteListeningTimeoutDuration: timeoutMillis=" + timeoutMillis);
if (timeoutMillis == 0) {
mSatelliteStayAtListeningFromSendingMillis =
getSatelliteStayAtListeningFromSendingMillis();
@@ -334,12 +374,12 @@
*/
boolean setSatelliteGatewayServicePackageName(@Nullable String servicePackageName) {
if (!isMockModemAllowed()) {
- loge("setSatelliteGatewayServicePackageName: modifying satellite gateway service "
+ ploge("setSatelliteGatewayServicePackageName: modifying satellite gateway service "
+ "package name is not allowed");
return false;
}
- logd("setSatelliteGatewayServicePackageName: config_satellite_gateway_service_package is "
+ plogd("setSatelliteGatewayServicePackageName: config_satellite_gateway_service_package is "
+ "updated, new packageName=" + servicePackageName);
if (servicePackageName == null || servicePackageName.equals("null")) {
@@ -372,6 +412,16 @@
mIsDemoMode = isDemoMode;
}
+ /**
+ * Get whether state machine is in enabling state.
+ *
+ * @return {@code true} if state machine is in enabling state and {@code false} otherwise.
+ */
+ public boolean isInEnablingState() {
+ if (DBG) plogd("isInEnablingState: getCurrentState=" + getCurrentState());
+ return getCurrentState() == mEnablingState;
+ }
+
private boolean isDemoMode() {
return mIsDemoMode;
}
@@ -390,14 +440,14 @@
private class UnavailableState extends State {
@Override
public void enter() {
- if (DBG) logd("Entering UnavailableState");
+ if (DBG) plogd("Entering UnavailableState");
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE);
}
@Override
public boolean processMessage(Message msg) {
- loge("UnavailableState: receive msg " + getWhatToString(msg.what) + " unexpectedly");
+ ploge("UnavailableState: receive msg " + getWhatToString(msg.what) + " unexpectedly");
return HANDLED;
}
}
@@ -405,7 +455,7 @@
private class PowerOffState extends State {
@Override
public void enter() {
- if (DBG) logd("Entering PowerOffState");
+ if (DBG) plogd("Entering PowerOffState");
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_OFF;
mIsSendingTriggeredDuringTransferringState.set(false);
@@ -414,23 +464,65 @@
}
unbindService();
stopNbIotInactivityTimer();
+ DemoSimulator.getInstance().onSatelliteModeOff();
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_OFF);
}
@Override
public void exit() {
- if (DBG) logd("Exiting PowerOffState");
- logd("Attempting to bind to SatelliteGatewayService.");
+ if (DBG) plogd("Exiting PowerOffState");
+ plogd("Attempting to bind to SatelliteGatewayService.");
bindService();
}
@Override
public boolean processMessage(Message msg) {
- if (DBG) log("PowerOffState: processing " + getWhatToString(msg.what));
+ if (DBG) plogd("PowerOffState: processing " + getWhatToString(msg.what));
+ switch (msg.what) {
+ case EVENT_SATELLITE_ENABLEMENT_STARTED:
+ handleSatelliteEnablementStarted((boolean) msg.obj);
+ break;
+ }
+ // Ignore all unexpected events.
+ return HANDLED;
+ }
+
+ private void handleSatelliteEnablementStarted(boolean enabled) {
+ if (enabled) {
+ transitionTo(mEnablingState);
+ } else {
+ plogw("Unexpected satellite disablement started in PowerOff state");
+ }
+ }
+ }
+
+ private class EnablingState extends State {
+ @Override
+ public void enter() {
+ if (DBG) plogd("Entering EnablingState");
+
+ mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE;
+ notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE);
+ }
+
+ @Override
+ public void exit() {
+ if (DBG) plogd("Exiting EnablingState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) plogd("EnablingState: processing " + getWhatToString(msg.what));
switch (msg.what) {
case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
handleSatelliteEnabledStateChanged((boolean) msg.obj);
break;
+ case EVENT_SATELLITE_ENABLEMENT_FAILED:
+ transitionTo(mPowerOffState);
+ break;
+ case EVENT_SATELLITE_MODEM_STATE_CHANGED:
+ deferMessage(msg);
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -443,6 +535,51 @@
} else {
transitionTo(mIdleState);
}
+ DemoSimulator.getInstance().onSatelliteModeOn();
+ } else {
+ /*
+ * During the state transition from ENABLING to NOT_CONNECTED, modem might be
+ * reset. In such cases, we need to remove all deferred
+ * EVENT_SATELLITE_MODEM_STATE_CHANGED events so that they will not mess up our
+ * state machine later.
+ */
+ removeDeferredMessages(EVENT_SATELLITE_MODEM_STATE_CHANGED);
+ transitionTo(mPowerOffState);
+ }
+ }
+ }
+
+ private class DisablingState extends State {
+ @Override
+ public void enter() {
+ if (DBG) plogd("Entering DisablingState");
+
+ mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE;
+ notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE);
+ }
+
+ @Override
+ public void exit() {
+ if (DBG) plogd("Exiting DisablingState");
+ }
+
+ @Override
+ public boolean processMessage(Message msg) {
+ if (DBG) plogd("DisablingState: processing " + getWhatToString(msg.what));
+ switch (msg.what) {
+ case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
+ handleSatelliteEnabledStateChanged((boolean) msg.obj);
+ break;
+ }
+ // Ignore all unexpected events.
+ return HANDLED;
+ }
+
+ private void handleSatelliteEnabledStateChanged(boolean on) {
+ if (on) {
+ plogw("Unexpected power on event while disabling satellite");
+ } else {
+ transitionTo(mPowerOffState);
}
}
}
@@ -450,7 +587,7 @@
private class IdleState extends State {
@Override
public void enter() {
- if (DBG) logd("Entering IdleState");
+ if (DBG) plogd("Entering IdleState");
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_IDLE;
mIsSendingTriggeredDuringTransferringState.set(false);
stopNbIotInactivityTimer();
@@ -461,7 +598,7 @@
@Override
public boolean processMessage(Message msg) {
- if (DBG) log("IdleState: processing " + getWhatToString(msg.what));
+ if (DBG) plogd("IdleState: processing " + getWhatToString(msg.what));
switch (msg.what) {
case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED:
handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj);
@@ -473,6 +610,9 @@
handleEventDisableCellularModemWhileSatelliteModeIsOnDone(
(AsyncResult) msg.obj);
break;
+ case EVENT_SATELLITE_ENABLEMENT_STARTED:
+ handleSatelliteEnablementStarted((boolean) msg.obj);
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -484,7 +624,7 @@
|| (datagramTransferState.receiveState
== SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING)) {
if (mSatelliteController.isSatelliteAttachRequired()) {
- loge("Unexpected transferring state received for NB-IOT NTN");
+ ploge("Unexpected transferring state received for NB-IOT NTN");
} else {
transitionTo(mTransferringState);
}
@@ -495,7 +635,7 @@
if (mSatelliteController.isSatelliteAttachRequired()) {
disableCellularModemWhileSatelliteModeIsOn();
} else {
- loge("Unexpected transferring state received for non-NB-IOT NTN");
+ ploge("Unexpected transferring state received for non-NB-IOT NTN");
}
}
}
@@ -511,7 +651,7 @@
}
mIsDisableCellularModemInProgress = false;
} else {
- loge("DisableCellularModemWhileSatelliteModeIsOn is not in progress");
+ ploge("DisableCellularModemWhileSatelliteModeIsOn is not in progress");
}
}
}
@@ -519,7 +659,7 @@
private void disableCellularModemWhileSatelliteModeIsOn() {
synchronized (mLock) {
if (mIsDisableCellularModemInProgress) {
- logd("Cellular scanning is already being disabled");
+ plogd("Cellular scanning is already being disabled");
return;
}
@@ -533,7 +673,7 @@
@Override
public void exit() {
- if (DBG) logd("Exiting IdleState");
+ if (DBG) plogd("Exiting IdleState");
if (!mSatelliteController.isSatelliteAttachRequired()) {
// Disable cellular modem scanning
mSatelliteModemInterface.enableCellularModemWhileSatelliteModeIsOn(false, null);
@@ -544,7 +684,7 @@
private class TransferringState extends State {
@Override
public void enter() {
- if (DBG) logd("Entering TransferringState");
+ if (DBG) plogd("Entering TransferringState");
stopNbIotInactivityTimer();
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
@@ -552,7 +692,7 @@
@Override
public boolean processMessage(Message msg) {
- if (DBG) log("TransferringState: processing " + getWhatToString(msg.what));
+ if (DBG) plogd("TransferringState: processing " + getWhatToString(msg.what));
switch (msg.what) {
case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED:
handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj);
@@ -563,6 +703,9 @@
case EVENT_SATELLITE_MODEM_STATE_CHANGED:
handleEventSatelliteModemStateChange(msg.arg1);
break;
+ case EVENT_SATELLITE_ENABLEMENT_STARTED:
+ handleSatelliteEnablementStarted((boolean) msg.obj);
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -600,7 +743,7 @@
private class ListeningState extends State {
@Override
public void enter() {
- if (DBG) logd("Entering ListeningState");
+ if (DBG) plogd("Entering ListeningState");
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_LISTENING;
long timeoutMillis = updateListeningMode(true);
@@ -611,7 +754,7 @@
@Override
public void exit() {
- if (DBG) logd("Exiting ListeningState");
+ if (DBG) plogd("Exiting ListeningState");
removeMessages(EVENT_LISTENING_TIMER_TIMEOUT);
updateListeningMode(false);
@@ -619,7 +762,7 @@
@Override
public boolean processMessage(Message msg) {
- if (DBG) log("ListeningState: processing " + getWhatToString(msg.what));
+ if (DBG) plogd("ListeningState: processing " + getWhatToString(msg.what));
switch (msg.what) {
case EVENT_LISTENING_TIMER_TIMEOUT:
transitionTo(mIdleState);
@@ -630,6 +773,9 @@
case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
handleSatelliteEnabledStateChanged(!(boolean) msg.obj, "ListeningState");
break;
+ case EVENT_SATELLITE_ENABLEMENT_STARTED:
+ handleSatelliteEnablementStarted((boolean) msg.obj);
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -660,7 +806,7 @@
private class NotConnectedState extends State {
@Override
public void enter() {
- if (DBG) logd("Entering NotConnectedState");
+ if (DBG) plogd("Entering NotConnectedState");
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
@@ -669,12 +815,12 @@
@Override
public void exit() {
- if (DBG) logd("Exiting NotConnectedState");
+ if (DBG) plogd("Exiting NotConnectedState");
}
@Override
public boolean processMessage(Message msg) {
- if (DBG) log("NotConnectedState: processing " + getWhatToString(msg.what));
+ if (DBG) plogd("NotConnectedState: processing " + getWhatToString(msg.what));
switch (msg.what) {
case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
handleSatelliteEnabledStateChanged(
@@ -689,6 +835,9 @@
case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED:
handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj);
break;
+ case EVENT_SATELLITE_ENABLEMENT_STARTED:
+ handleSatelliteEnablementStarted((boolean) msg.obj);
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -722,7 +871,7 @@
private class ConnectedState extends State {
@Override
public void enter() {
- if (DBG) logd("Entering ConnectedState");
+ if (DBG) plogd("Entering ConnectedState");
mCurrentState = SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED;
notifyStateChangedEvent(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
@@ -731,12 +880,12 @@
@Override
public void exit() {
- if (DBG) logd("Exiting ConnectedState");
+ if (DBG) plogd("Exiting ConnectedState");
}
@Override
public boolean processMessage(Message msg) {
- if (DBG) log("ConnectedState: processing " + getWhatToString(msg.what));
+ if (DBG) plogd("ConnectedState: processing " + getWhatToString(msg.what));
switch (msg.what) {
case EVENT_SATELLITE_ENABLED_STATE_CHANGED:
handleSatelliteEnabledStateChanged(
@@ -751,6 +900,9 @@
case EVENT_DATAGRAM_TRANSFER_STATE_CHANGED:
handleEventDatagramTransferStateChanged((DatagramTransferState) msg.obj);
break;
+ case EVENT_SATELLITE_ENABLEMENT_STARTED:
+ handleSatelliteEnablementStarted((boolean) msg.obj);
+ break;
}
// Ignore all unexpected events.
return HANDLED;
@@ -797,6 +949,12 @@
case EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT:
whatString = "EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT";
break;
+ case EVENT_SATELLITE_ENABLEMENT_STARTED:
+ whatString = "EVENT_SATELLITE_ENABLEMENT_STARTED";
+ break;
+ case EVENT_SATELLITE_ENABLEMENT_FAILED:
+ whatString = "EVENT_SATELLITE_ENABLEMENT_FAILED";
+ break;
default:
whatString = "UNKNOWN EVENT " + what;
}
@@ -819,7 +977,7 @@
try {
listener.onSatelliteModemStateChanged(state);
} catch (RemoteException e) {
- logd("notifyStateChangedEvent RemoteException: " + e);
+ plogd("notifyStateChangedEvent RemoteException: " + e);
toBeRemoved.add(listener);
}
});
@@ -833,7 +991,7 @@
if (off) {
transitionTo(mPowerOffState);
} else {
- loge(caller + ": Unexpected satellite radio powered-on state changed event");
+ ploge(caller + ": Unexpected satellite radio powered-on state changed event");
}
}
@@ -866,7 +1024,7 @@
String packageName = getSatelliteGatewayPackageName();
if (TextUtils.isEmpty(packageName)) {
- loge("Unable to bind to the satellite gateway service because the package is"
+ ploge("Unable to bind to the satellite gateway service because the package is"
+ " undefined.");
// Since the package name comes from static device configs, stop retry because
// rebind will continue to fail without a valid package name.
@@ -884,13 +1042,13 @@
boolean success = mContext.bindService(
intent, mSatelliteGatewayServiceConnection, Context.BIND_AUTO_CREATE);
if (success) {
- logd("Successfully bound to the satellite gateway service.");
+ plogd("Successfully bound to the satellite gateway service.");
} else {
synchronized (mLock) {
mIsBinding = false;
}
mExponentialBackoff.notifyFailed();
- loge("Error binding to the satellite gateway service. Retrying in "
+ ploge("Error binding to the satellite gateway service. Retrying in "
+ mExponentialBackoff.getCurrentDelay() + " ms.");
}
} catch (Exception e) {
@@ -898,13 +1056,13 @@
mIsBinding = false;
}
mExponentialBackoff.notifyFailed();
- loge("Exception binding to the satellite gateway service. Retrying in "
+ ploge("Exception binding to the satellite gateway service. Retrying in "
+ mExponentialBackoff.getCurrentDelay() + " ms. Exception: " + e);
}
}
private void unbindService() {
- logd("unbindService");
+ plogd("unbindService");
mExponentialBackoff.stop();
mSatelliteGatewayService = null;
synchronized (mLock) {
@@ -919,7 +1077,7 @@
private class SatelliteGatewayServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
- logd("onServiceConnected: ComponentName=" + name);
+ plogd("onServiceConnected: ComponentName=" + name);
synchronized (mLock) {
mIsBound = true;
mIsBinding = false;
@@ -930,7 +1088,7 @@
@Override
public void onServiceDisconnected(ComponentName name) {
- loge("onServiceDisconnected: Waiting for reconnect.");
+ ploge("onServiceDisconnected: Waiting for reconnect.");
synchronized (mLock) {
mIsBinding = false;
mIsBound = false;
@@ -940,7 +1098,7 @@
@Override
public void onBindingDied(ComponentName name) {
- loge("onBindingDied: Unbinding and rebinding service.");
+ ploge("onBindingDied: Unbinding and rebinding service.");
synchronized (mLock) {
mIsBound = false;
mIsBinding = false;
@@ -950,6 +1108,12 @@
}
}
+ private void handleSatelliteEnablementStarted(boolean enabled) {
+ if (!enabled) {
+ transitionTo(mDisablingState);
+ }
+ }
+
private boolean isMockModemAllowed() {
return (DEBUG || SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false));
}
@@ -973,8 +1137,13 @@
}
private long getSatelliteNbIotInactivityTimeoutMillis() {
- return mContext.getResources().getInteger(
- R.integer.config_satellite_nb_iot_inactivity_timeout_millis);
+ if (isDemoMode()) {
+ return mContext.getResources().getInteger(
+ R.integer.config_satellite_demo_mode_nb_iot_inactivity_timeout_millis);
+ } else {
+ return mContext.getResources().getInteger(
+ R.integer.config_satellite_nb_iot_inactivity_timeout_millis);
+ }
}
private void restartNbIotInactivityTimer() {
@@ -984,7 +1153,7 @@
private void startNbIotInactivityTimer() {
if (isNbIotInactivityTimerStarted()) {
- logd("NB IOT inactivity timer is already started");
+ plogd("NB IOT inactivity timer is already started");
return;
}
@@ -1004,4 +1173,38 @@
private boolean isNbIotInactivityTimerStarted() {
return hasMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
}
+
+ private boolean isSatellitePersistentLoggingEnabled(
+ @NonNull Context context, @NonNull FeatureFlags featureFlags) {
+ if (featureFlags.satellitePersistentLogging()) {
+ return true;
+ }
+ try {
+ return context.getResources().getBoolean(
+ R.bool.config_dropboxmanager_persistent_logging_enabled);
+ } catch (RuntimeException e) {
+ return false;
+ }
+ }
+
+ private void plogd(@NonNull String log) {
+ logd(log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.debug(TAG, log);
+ }
+ }
+
+ private void plogw(@NonNull String log) {
+ logw(log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.warn(TAG, log);
+ }
+ }
+
+ private void ploge(@NonNull String log) {
+ loge(log);
+ if (mPersistentLogger != null) {
+ mPersistentLogger.error(TAG, log);
+ }
+ }
}
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/AccessControllerMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/AccessControllerMetricsStats.java
new file mode 100644
index 0000000..13ba709
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/metrics/AccessControllerMetricsStats.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.telephony.satellite.metrics;
+
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import static com.android.internal.telephony.satellite.SatelliteConstants.CONFIG_DATA_SOURCE_UNKNOWN;
+
+import android.annotation.NonNull;
+import android.telephony.satellite.SatelliteManager;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.satellite.SatelliteConstants;
+
+import java.util.Arrays;
+import java.util.List;
+public class AccessControllerMetricsStats {
+ private static final String TAG = AccessControllerMetricsStats.class.getSimpleName();
+ private static AccessControllerMetricsStats sInstance = null;
+
+ private @SatelliteConstants.AccessControlType int mAccessControlType;
+ private long mLocationQueryTimeMillis;
+ private long mOnDeviceLookupTimeMillis;
+ private long mTotalCheckingTimeMillis;
+ private Boolean mIsAllowed;
+ private Boolean mIsEmergency;
+ private @SatelliteManager.SatelliteResult int mResultCode;
+ private String[] mCountryCodes;
+ private @SatelliteConstants.ConfigDataSource int mConfigDataSource;
+ private AccessControllerMetricsStats() {
+ initializeAccessControllerMetricsParam();
+ }
+
+ /**
+ * Returns the Singleton instance of AccessControllerMetricsStats class.
+ * If an instance of the Singleton class has not been created,
+ * it creates a new instance and returns it. Otherwise, it returns
+ * the existing instance.
+ * @return the Singleton instance of AccessControllerMetricsStats.
+ */
+ public static AccessControllerMetricsStats getInstance() {
+ if (sInstance == null) {
+ loge("create new AccessControllerMetricsStats.");
+ sInstance = new AccessControllerMetricsStats();
+ }
+ return sInstance;
+ }
+ private void initializeAccessControllerMetricsParam() {
+ mAccessControlType = SatelliteConstants.ACCESS_CONTROL_TYPE_UNKNOWN;
+ mLocationQueryTimeMillis = 0;
+ mOnDeviceLookupTimeMillis = 0;
+ mTotalCheckingTimeMillis = 0;
+ mIsAllowed = null;
+ mIsEmergency = null;
+ mResultCode = SATELLITE_RESULT_SUCCESS;
+ mCountryCodes = new String[0];
+ mConfigDataSource = CONFIG_DATA_SOURCE_UNKNOWN;
+ }
+ /**
+ * Sets the Access Control Type for current satellite enablement.
+ * @param accessControlType access control type of location query is attempted.
+ */
+ public AccessControllerMetricsStats setAccessControlType(
+ @SatelliteConstants.AccessControlType int accessControlType) {
+ mAccessControlType = accessControlType;
+ logd("setAccessControlType: access control type = " + mAccessControlType);
+ return this;
+ }
+ /**
+ * Sets the location query time for current satellite enablement.
+ * @param queryStartTime the time location query is attempted.
+ */
+ public AccessControllerMetricsStats setLocationQueryTime(long queryStartTime) {
+ mLocationQueryTimeMillis =
+ (queryStartTime > 0) ? (getCurrentTime() - queryStartTime) : 0;
+ logd("setLocationQueryTimeMillis: location query time = " + mLocationQueryTimeMillis);
+ return this;
+ }
+ /**
+ * Sets the on device lookup time for current satellite enablement.
+ * @param onDeviceLookupStartTime the time on device lookup is attempted.
+ */
+ public AccessControllerMetricsStats setOnDeviceLookupTime(long onDeviceLookupStartTime) {
+ mOnDeviceLookupTimeMillis =
+ (onDeviceLookupStartTime > 0) ? (getCurrentTime() - onDeviceLookupStartTime) : 0;
+ logd("setLocationQueryTime: on device lookup time = " + mOnDeviceLookupTimeMillis);
+ return this;
+ }
+ /**
+ * Sets the total checking time for current satellite enablement.
+ * @param queryStartTime the time location query is attempted.
+ */
+ public AccessControllerMetricsStats setTotalCheckingTime(long queryStartTime) {
+ mTotalCheckingTimeMillis =
+ (queryStartTime > 0) ? (getCurrentTime() - queryStartTime) : 0;
+ logd("setTotalCheckingTime: location query time = " + mTotalCheckingTimeMillis);
+ return this;
+ }
+ /**
+ * Sets whether the satellite communication is allowed from current location.
+ * @param isAllowed {@code true} if satellite communication is allowed from current location
+ * {@code false} otherwise.
+ */
+ public AccessControllerMetricsStats setIsAllowed(boolean isAllowed) {
+ mIsAllowed = isAllowed;
+ logd("setIsAllowed: allowed=" + mIsAllowed);
+ return this;
+ }
+ /**
+ * Sets whether the current satellite enablement is for emergency or not.
+ * @param isEmergency {@code true} if current satellite enablement is for emergency SOS message
+ * {@code false} otherwise.
+ */
+ public AccessControllerMetricsStats setIsEmergency(boolean isEmergency) {
+ mIsEmergency = isEmergency;
+ logd("setIsEmergency: emergency =" + mIsEmergency);
+ return this;
+ }
+ /**
+ * Sets the result code for checking whether satellite service is allowed from current
+ * location.
+ * @param result result code for checking process.
+ */
+ public AccessControllerMetricsStats setResult(@SatelliteManager.SatelliteResult int result) {
+ mResultCode = result;
+ logd("setResult: result = " + mResultCode);
+ return this;
+ }
+ /**
+ * Sets the country code for current location while attempting satellite enablement.
+ * @param countryCodes Country code the user is located in
+ */
+ public AccessControllerMetricsStats setCountryCodes(List<String> countryCodes) {
+ mCountryCodes = countryCodes.stream().toArray(String[]::new);
+ logd("setCountryCodes: country code is " + Arrays.toString(mCountryCodes));
+ return this;
+ }
+ /**
+ * Sets the config data source for checking whether satellite service is allowed from current
+ * location.
+ * @param configDatasource configuration data source.
+ */
+ public AccessControllerMetricsStats setConfigDataSource(
+ @SatelliteConstants.ConfigDataSource int configDatasource) {
+ mConfigDataSource = configDatasource;
+ logd("setConfigDataSource: config data source = " + mConfigDataSource);
+ return this;
+ }
+ /** Report the access controller metrics atoms to PersistAtomsStorage in telephony. */
+ public void reportAccessControllerMetrics() {
+ SatelliteStats.SatelliteAccessControllerParams accessControllerParams =
+ new SatelliteStats.SatelliteAccessControllerParams.Builder()
+ .setAccessControlType(mAccessControlType)
+ .setLocationQueryTime(mLocationQueryTimeMillis)
+ .setOnDeviceLookupTime(mOnDeviceLookupTimeMillis)
+ .setTotalCheckingTime(mTotalCheckingTimeMillis)
+ .setIsAllowed(mIsAllowed)
+ .setIsEmergency(mIsEmergency)
+ .setResult(mResultCode)
+ .setCountryCodes(mCountryCodes)
+ .setConfigDatasource(mConfigDataSource)
+ .build();
+ logd("reportAccessControllerMetrics: " + accessControllerParams.toString());
+ SatelliteStats.getInstance().onSatelliteAccessControllerMetrics(accessControllerParams);
+ initializeAccessControllerMetricsParam();
+ }
+ @VisibleForTesting
+ public long getCurrentTime() {
+ return System.currentTimeMillis();
+ }
+ private static void logd(@NonNull String log) {
+ Log.d(TAG, log);
+ }
+ private static void loge(@NonNull String log) {
+ Log.e(TAG, log);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
new file mode 100644
index 0000000..9524b75
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteControllerStats.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite.metrics;
+
+import android.annotation.NonNull;
+import android.util.Log;
+
+import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.satellite.SatelliteConstants;
+
+public class CarrierRoamingSatelliteControllerStats {
+ private static final String TAG = CarrierRoamingSatelliteControllerStats.class.getSimpleName();
+ private static CarrierRoamingSatelliteControllerStats sInstance = null;
+ private static final int ADD_COUNT = 1;
+
+ private SatelliteStats mSatelliteStats;
+
+ private CarrierRoamingSatelliteControllerStats() {
+ mSatelliteStats = SatelliteStats.getInstance();
+ }
+
+ /**
+ * Returns the Singleton instance of CarrierRoamingSatelliteControllerStats class.
+ * If an instance of the Singleton class has not been created,
+ * it creates a new instance and returns it. Otherwise, it returns
+ * the existing instance.
+ * @return the Singleton instance of CarrierRoamingSatelliteControllerStats
+ */
+ public static CarrierRoamingSatelliteControllerStats getOrCreateInstance() {
+ if (sInstance == null) {
+ logd("Create new CarrierRoamingSatelliteControllerStats.");
+ sInstance = new CarrierRoamingSatelliteControllerStats();
+ }
+ return sInstance;
+ }
+
+ /** Report config data source */
+ public void reportConfigDataSource(@SatelliteConstants.ConfigDataSource int configDataSource) {
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+ new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setConfigDataSource(configDataSource)
+ .build());
+ }
+
+ /** Report count of entitlement status query request */
+ public void reportCountOfEntitlementStatusQueryRequest() {
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+ new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setCountOfEntitlementStatusQueryRequest(ADD_COUNT)
+ .build());
+ }
+
+ /** Report count of satellite config update request */
+ public void reportCountOfSatelliteConfigUpdateRequest() {
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+ new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setCountOfSatelliteConfigUpdateRequest(ADD_COUNT)
+ .build());
+ }
+
+ /** Report count of satellite notification displayed */
+ public void reportCountOfSatelliteNotificationDisplayed() {
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(
+ new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setCountOfSatelliteNotificationDisplayed(ADD_COUNT)
+ .build());
+ }
+
+ private static void logd(@NonNull String log) {
+ Log.d(TAG, log);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
new file mode 100644
index 0000000..771432e
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/metrics/CarrierRoamingSatelliteSessionStats.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite.metrics;
+
+import android.annotation.NonNull;
+import android.telephony.CellInfo;
+import android.telephony.CellSignalStrength;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.NetworkRegistrationInfo;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.telephony.MccTable;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
+import com.android.internal.telephony.subscription.SubscriptionManagerService;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class CarrierRoamingSatelliteSessionStats {
+ private static final String TAG = CarrierRoamingSatelliteSessionStats.class.getSimpleName();
+ private static final SparseArray<CarrierRoamingSatelliteSessionStats>
+ sCarrierRoamingSatelliteSessionStats = new SparseArray<>();
+ @NonNull private final SubscriptionManagerService mSubscriptionManagerService;
+ private int mCarrierId;
+ private boolean mIsNtnRoamingInHomeCountry;
+ private int mCountOfIncomingSms;
+ private int mCountOfOutgoingSms;
+ private int mCountOfIncomingMms;
+ private int mCountOfOutgoingMms;
+ private long mIncomingMessageId;
+
+ private int mSessionStartTimeSec;
+ private List<Long> mConnectionStartTimeList;
+ private List<Long> mConnectionEndTimeList;
+ private List<Integer> mRsrpList;
+ private List<Integer> mRssnrList;
+
+ public CarrierRoamingSatelliteSessionStats(int subId) {
+ logd("Create new CarrierRoamingSatelliteSessionStats. subId=" + subId);
+ initializeParams();
+ mSubscriptionManagerService = SubscriptionManagerService.getInstance();
+ }
+
+ /** Gets a CarrierRoamingSatelliteSessionStats instance. */
+ public static CarrierRoamingSatelliteSessionStats getInstance(int subId) {
+ synchronized (sCarrierRoamingSatelliteSessionStats) {
+ if (sCarrierRoamingSatelliteSessionStats.get(subId) == null) {
+ sCarrierRoamingSatelliteSessionStats.put(subId,
+ new CarrierRoamingSatelliteSessionStats(subId));
+ }
+ return sCarrierRoamingSatelliteSessionStats.get(subId);
+ }
+ }
+
+ /** Log carrier roaming satellite session start */
+ public void onSessionStart(int carrierId, Phone phone) {
+ mCarrierId = carrierId;
+ mSessionStartTimeSec = getCurrentTimeInSec();
+ mIsNtnRoamingInHomeCountry = false;
+ onConnectionStart(phone);
+ }
+
+ /** Log carrier roaming satellite connection start */
+ public void onConnectionStart(Phone phone) {
+ mConnectionStartTimeList.add(getCurrentTime());
+ updateNtnRoamingInHomeCountry(phone);
+ }
+
+ /** Log carrier roaming satellite session end */
+ public void onSessionEnd() {
+ onConnectionEnd();
+ reportMetrics();
+ mIsNtnRoamingInHomeCountry = false;
+ }
+
+ /** Log carrier roaming satellite connection end */
+ public void onConnectionEnd() {
+ mConnectionEndTimeList.add(getCurrentTime());
+ }
+
+ /** Log rsrp and rssnr when occurred the service state change with NTN is connected. */
+ public void onSignalStrength(Phone phone) {
+ CellSignalStrengthLte cellSignalStrengthLte = getCellSignalStrengthLte(phone);
+ int rsrp = cellSignalStrengthLte.getRsrp();
+ int rssnr = cellSignalStrengthLte.getRssnr();
+ if (rsrp == CellInfo.UNAVAILABLE) {
+ logd("onSignalStrength: rsrp unavailable");
+ return;
+ }
+ if (rssnr == CellInfo.UNAVAILABLE) {
+ logd("onSignalStrength: rssnr unavailable");
+ return;
+ }
+ mRsrpList.add(rsrp);
+ mRssnrList.add(rssnr);
+ logd("onSignalStrength : rsrp=" + rsrp + ", rssnr=" + rssnr);
+ }
+
+ /** Log incoming sms success case */
+ public void onIncomingSms(int subId) {
+ if (!isNtnConnected()) {
+ return;
+ }
+ mCountOfIncomingSms += 1;
+ logd("onIncomingSms: subId=" + subId + ", count=" + mCountOfIncomingSms);
+ }
+
+ /** Log outgoing sms success case */
+ public void onOutgoingSms(int subId) {
+ if (!isNtnConnected()) {
+ return;
+ }
+ mCountOfOutgoingSms += 1;
+ logd("onOutgoingSms: subId=" + subId + ", count=" + mCountOfOutgoingSms);
+ }
+
+ /** Log incoming or outgoing mms success case */
+ public void onMms(boolean isIncomingMms, long messageId) {
+ if (!isNtnConnected()) {
+ return;
+ }
+ if (isIncomingMms) {
+ mIncomingMessageId = messageId;
+ mCountOfIncomingMms += 1;
+ logd("onMms: messageId=" + messageId + ", countOfIncomingMms=" + mCountOfIncomingMms);
+ } else {
+ if (mIncomingMessageId == messageId) {
+ logd("onMms: NotifyResponse ignore it.");
+ mIncomingMessageId = 0;
+ return;
+ }
+ mCountOfOutgoingMms += 1;
+ logd("onMms: countOfOutgoingMms=" + mCountOfOutgoingMms);
+ }
+ }
+
+ private void reportMetrics() {
+ int totalSatelliteModeTimeSec = mSessionStartTimeSec > 0
+ ? getCurrentTimeInSec() - mSessionStartTimeSec : 0;
+ int numberOfSatelliteConnections = getNumberOfSatelliteConnections();
+ int avgDurationOfSatelliteConnectionSec = getAvgDurationOfSatelliteConnection(
+ numberOfSatelliteConnections);
+
+ List<Integer> connectionGapList = getSatelliteConnectionGapList(
+ numberOfSatelliteConnections);
+ int satelliteConnectionGapMinSec = 0;
+ int satelliteConnectionGapMaxSec = 0;
+ if (!connectionGapList.isEmpty()) {
+ satelliteConnectionGapMinSec = Collections.min(connectionGapList);
+ satelliteConnectionGapMaxSec = Collections.max(connectionGapList);
+ }
+
+ SatelliteStats.CarrierRoamingSatelliteSessionParams params =
+ new SatelliteStats.CarrierRoamingSatelliteSessionParams.Builder()
+ .setCarrierId(mCarrierId)
+ .setIsNtnRoamingInHomeCountry(mIsNtnRoamingInHomeCountry)
+ .setTotalSatelliteModeTimeSec(totalSatelliteModeTimeSec)
+ .setNumberOfSatelliteConnections(numberOfSatelliteConnections)
+ .setAvgDurationOfSatelliteConnectionSec(avgDurationOfSatelliteConnectionSec)
+ .setSatelliteConnectionGapMinSec(satelliteConnectionGapMinSec)
+ .setSatelliteConnectionGapAvgSec(getAvg(connectionGapList))
+ .setSatelliteConnectionGapMaxSec(satelliteConnectionGapMaxSec)
+ .setRsrpAvg(getAvg(mRsrpList))
+ .setRsrpMedian(getMedian(mRsrpList))
+ .setRssnrAvg(getAvg(mRssnrList))
+ .setRssnrMedian(getMedian(mRssnrList))
+ .setCountOfIncomingSms(mCountOfIncomingSms)
+ .setCountOfOutgoingSms(mCountOfOutgoingSms)
+ .setCountOfIncomingMms(mCountOfIncomingMms)
+ .setCountOfOutgoingMms(mCountOfOutgoingMms)
+ .build();
+ SatelliteStats.getInstance().onCarrierRoamingSatelliteSessionMetrics(params);
+ logd("reportMetrics: " + params);
+ initializeParams();
+ }
+
+ private void initializeParams() {
+ mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+ mIsNtnRoamingInHomeCountry = false;
+ mCountOfIncomingSms = 0;
+ mCountOfOutgoingSms = 0;
+ mCountOfIncomingMms = 0;
+ mCountOfOutgoingMms = 0;
+ mIncomingMessageId = 0;
+
+ mSessionStartTimeSec = 0;
+ mConnectionStartTimeList = new ArrayList<>();
+ mConnectionEndTimeList = new ArrayList<>();
+ mRsrpList = new ArrayList<>();
+ mRssnrList = new ArrayList<>();
+ logd("initializeParams");
+ }
+
+ private CellSignalStrengthLte getCellSignalStrengthLte(Phone phone) {
+ SignalStrength signalStrength = phone.getSignalStrength();
+ List<CellSignalStrength> cellSignalStrengths = signalStrength.getCellSignalStrengths();
+ for (CellSignalStrength cellSignalStrength : cellSignalStrengths) {
+ if (cellSignalStrength instanceof CellSignalStrengthLte) {
+ return (CellSignalStrengthLte) cellSignalStrength;
+ }
+ }
+
+ return new CellSignalStrengthLte();
+ }
+
+ private int getNumberOfSatelliteConnections() {
+ return Math.min(mConnectionStartTimeList.size(), mConnectionEndTimeList.size());
+ }
+
+ private int getAvgDurationOfSatelliteConnection(int numberOfSatelliteConnections) {
+ if (numberOfSatelliteConnections == 0) {
+ return 0;
+ }
+
+ long totalConnectionsDuration = 0;
+ for (int i = 0; i < numberOfSatelliteConnections; i++) {
+ long endTime = mConnectionEndTimeList.get(i);
+ long startTime = mConnectionStartTimeList.get(i);
+ if (endTime >= startTime && startTime > 0) {
+ totalConnectionsDuration += endTime - startTime;
+ }
+ }
+
+ long avgConnectionDuration = totalConnectionsDuration / numberOfSatelliteConnections;
+ return (int) (avgConnectionDuration / 1000L);
+ }
+
+ private List<Integer> getSatelliteConnectionGapList(int numberOfSatelliteConnections) {
+ if (numberOfSatelliteConnections == 0) {
+ return new ArrayList<>();
+ }
+
+ List<Integer> connectionGapList = new ArrayList<>();
+ for (int i = 1; i < numberOfSatelliteConnections; i++) {
+ long prevConnectionEndTime = mConnectionEndTimeList.get(i - 1);
+ long currentConnectionStartTime = mConnectionStartTimeList.get(i);
+ if (currentConnectionStartTime > prevConnectionEndTime && prevConnectionEndTime > 0) {
+ connectionGapList.add((int) (
+ (currentConnectionStartTime - prevConnectionEndTime) / 1000));
+ }
+ }
+ return connectionGapList;
+ }
+
+ private int getAvg(@NonNull List<Integer> list) {
+ if (list.isEmpty()) {
+ return 0;
+ }
+
+ int total = 0;
+ for (int num : list) {
+ total += num;
+ }
+
+ return total / list.size();
+ }
+
+ private int getMedian(@NonNull List<Integer> list) {
+ if (list.isEmpty()) {
+ return 0;
+ }
+ int size = list.size();
+ if (size == 1) {
+ return list.get(0);
+ }
+
+ Collections.sort(list);
+ return size % 2 == 0 ? (list.get(size / 2 - 1) + list.get(size / 2)) / 2
+ : list.get(size / 2);
+ }
+
+ private int getCurrentTimeInSec() {
+ return (int) (System.currentTimeMillis() / 1000);
+ }
+
+ private long getCurrentTime() {
+ return System.currentTimeMillis();
+ }
+
+ private boolean isNtnConnected() {
+ return mSessionStartTimeSec != 0;
+ }
+
+ private void updateNtnRoamingInHomeCountry(Phone phone) {
+ int subId = phone.getSubId();
+ ServiceState serviceState = phone.getServiceState();
+ if (serviceState == null) {
+ logd("ServiceState is null");
+ return;
+ }
+
+ String satelliteRegisteredPlmn = "";
+ for (NetworkRegistrationInfo nri
+ : serviceState.getNetworkRegistrationInfoList()) {
+ if (nri.isNonTerrestrialNetwork()) {
+ satelliteRegisteredPlmn = nri.getRegisteredPlmn();
+ }
+ }
+
+ SubscriptionInfoInternal subscriptionInfoInternal =
+ mSubscriptionManagerService.getSubscriptionInfoInternal(subId);
+ if (subscriptionInfoInternal == null) {
+ logd("SubscriptionInfoInternal is null");
+ return;
+ }
+ String simCountry = MccTable.countryCodeForMcc(subscriptionInfoInternal.getMcc());
+ String satelliteRegisteredCountry = MccTable.countryCodeForMcc(
+ satelliteRegisteredPlmn.substring(0, 3));
+ if (simCountry.equalsIgnoreCase(satelliteRegisteredCountry)) {
+ mIsNtnRoamingInHomeCountry = false;
+ } else {
+ // If device is connected to roaming non-terrestrial network, update to true.
+ mIsNtnRoamingInHomeCountry = true;
+ }
+ logd("updateNtnRoamingInHomeCountry: mIsNtnRoamingInHomeCountry="
+ + mIsNtnRoamingInHomeCountry);
+ }
+
+ private void logd(@NonNull String log) {
+ Log.d(TAG, log);
+ }
+
+ private void loge(@NonNull String log) {
+ Log.e(TAG, log);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/ConfigUpdaterMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ConfigUpdaterMetricsStats.java
new file mode 100644
index 0000000..c379b83
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/metrics/ConfigUpdaterMetricsStats.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite.metrics;
+
+import android.annotation.NonNull;
+import android.util.Log;
+
+import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.satellite.SatelliteConstants;
+
+public class ConfigUpdaterMetricsStats {
+ private static final String TAG = ConfigUpdaterMetricsStats.class.getSimpleName();
+ private static ConfigUpdaterMetricsStats sInstance = null;
+
+ private int mConfigVersion;
+ private int mOemConfigResult;
+ private int mCarrierConfigResult;
+
+ private ConfigUpdaterMetricsStats() {
+ initializeConfigUpdaterParams();
+ }
+
+ /**
+ * Returns the Singleton instance of ConfigUpdaterMetricsStats class.
+ * If an instance of the Singleton class has not been created,
+ * it creates a new instance and returns it. Otherwise, it returns
+ * the existing instance.
+ * @return the Singleton instance of ConfigUpdaterMetricsStats
+ */
+ public static ConfigUpdaterMetricsStats getOrCreateInstance() {
+ if (sInstance == null) {
+ logd("Create new ConfigUpdaterMetricsStats.");
+ sInstance = new ConfigUpdaterMetricsStats();
+ }
+ return sInstance;
+ }
+
+ /** Set config version for config updater metrics */
+ public ConfigUpdaterMetricsStats setConfigVersion(int configVersion) {
+ mConfigVersion = configVersion;
+ return this;
+ }
+
+ /** Set oem config result for config updater metrics */
+ public ConfigUpdaterMetricsStats setOemConfigResult(int oemConfigResult) {
+ mOemConfigResult = oemConfigResult;
+ return this;
+ }
+
+ /** Set carrier config result for config updater metrics */
+ public ConfigUpdaterMetricsStats setCarrierConfigResult(int carrierConfigResult) {
+ mCarrierConfigResult = carrierConfigResult;
+ return this;
+ }
+
+ /** Report metrics on oem config update error */
+ public void reportOemConfigError(int error) {
+ mOemConfigResult = error;
+ reportConfigUpdaterMetrics();
+ }
+
+ /** Report metrics on carrier config update error */
+ public void reportCarrierConfigError(int error) {
+ mCarrierConfigResult = error;
+ reportConfigUpdaterMetrics();
+ }
+
+ /** Report metrics on config update error */
+ public void reportOemAndCarrierConfigError(int error) {
+ mOemConfigResult = error;
+ mCarrierConfigResult = error;
+ reportConfigUpdaterMetrics();
+ }
+
+ /** Report metrics on config update success */
+ public void reportConfigUpdateSuccess() {
+ mOemConfigResult = SatelliteConstants.CONFIG_UPDATE_RESULT_SUCCESS;
+ mCarrierConfigResult = SatelliteConstants.CONFIG_UPDATE_RESULT_SUCCESS;
+ reportConfigUpdaterMetrics();
+ }
+
+
+ /** Report config updater metrics atom to PersistAtomsStorage in telephony */
+ private void reportConfigUpdaterMetrics() {
+ SatelliteStats.SatelliteConfigUpdaterParams configUpdaterParams =
+ new SatelliteStats.SatelliteConfigUpdaterParams.Builder()
+ .setConfigVersion(mConfigVersion)
+ .setOemConfigResult(mOemConfigResult)
+ .setCarrierConfigResult(mCarrierConfigResult)
+ .setCount(1)
+ .build();
+ SatelliteStats.getInstance().onSatelliteConfigUpdaterMetrics(configUpdaterParams);
+ logd("reportConfigUpdaterMetrics: " + configUpdaterParams);
+
+ CarrierRoamingSatelliteControllerStats.getOrCreateInstance()
+ .reportCountOfSatelliteConfigUpdateRequest();
+
+ initializeConfigUpdaterParams();
+ }
+
+ private void initializeConfigUpdaterParams() {
+ mConfigVersion = -1;
+ mOemConfigResult = SatelliteConstants.CONFIG_UPDATE_RESULT_UNKNOWN;
+ mCarrierConfigResult = SatelliteConstants.CONFIG_UPDATE_RESULT_UNKNOWN;
+ }
+
+ private static void logd(@NonNull String log) {
+ Log.d(TAG, log);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
index 0c18fac..7dff2e6 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/ControllerMetricsStats.java
@@ -27,6 +27,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.satellite.SatelliteServiceUtils;
/**
* Stats to log to satellite metrics
@@ -132,63 +133,73 @@
/** Report a counter when an attempt for outgoing datagram is successfully done */
public void reportOutgoingDatagramSuccessCount(
- @NonNull @SatelliteManager.DatagramType int datagramType) {
- SatelliteStats.SatelliteControllerParams controllerParam;
- if (datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
- controllerParam = new SatelliteStats.SatelliteControllerParams.Builder()
- .setCountOfOutgoingDatagramSuccess(ADD_COUNT)
- .setCountOfDatagramTypeSosSmsSuccess(ADD_COUNT)
- .build();
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
- controllerParam = new SatelliteStats.SatelliteControllerParams.Builder()
- .setCountOfOutgoingDatagramSuccess(ADD_COUNT)
- .setCountOfDatagramTypeLocationSharingSuccess(ADD_COUNT)
- .build();
- } else { // datagramType == SatelliteManager.DATAGRAM_TYPE_UNKNOWN
- controllerParam = new SatelliteStats.SatelliteControllerParams.Builder()
- .setCountOfOutgoingDatagramSuccess(ADD_COUNT)
- .build();
+ @NonNull @SatelliteManager.DatagramType int datagramType, boolean isDemoMode) {
+ SatelliteStats.SatelliteControllerParams.Builder builder =
+ new SatelliteStats.SatelliteControllerParams.Builder();
+
+ if (isDemoMode) {
+ builder.setCountOfDemoModeOutgoingDatagramSuccess(ADD_COUNT);
+ } else {
+ builder.setCountOfOutgoingDatagramSuccess(ADD_COUNT);
}
+
+ if (SatelliteServiceUtils.isSosMessage(datagramType)) {
+ builder.setCountOfDatagramTypeSosSmsSuccess(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
+ builder.setCountOfDatagramTypeLocationSharingSuccess(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ builder.setCountOfDatagramTypeKeepAliveSuccess(ADD_COUNT).build();
+ }
+
+ SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
logd("reportServiceEnablementSuccessCount(): " + controllerParam);
mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
}
/** Report a counter when an attempt for outgoing datagram is failed */
public void reportOutgoingDatagramFailCount(
- @NonNull @SatelliteManager.DatagramType int datagramType) {
- SatelliteStats.SatelliteControllerParams controllerParam;
- if (datagramType == SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE) {
- controllerParam = new SatelliteStats.SatelliteControllerParams.Builder()
- .setCountOfOutgoingDatagramFail(ADD_COUNT)
- .setCountOfDatagramTypeSosSmsFail(ADD_COUNT)
- .build();
- } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
- controllerParam = new SatelliteStats.SatelliteControllerParams.Builder()
- .setCountOfOutgoingDatagramFail(ADD_COUNT)
- .setCountOfDatagramTypeLocationSharingFail(ADD_COUNT)
- .build();
- } else { // datagramType == SatelliteManager.DATAGRAM_TYPE_UNKNOWN
- controllerParam = new SatelliteStats.SatelliteControllerParams.Builder()
- .setCountOfOutgoingDatagramFail(ADD_COUNT)
- .build();
+ @NonNull @SatelliteManager.DatagramType int datagramType, boolean isDemoMode) {
+ SatelliteStats.SatelliteControllerParams.Builder builder =
+ new SatelliteStats.SatelliteControllerParams.Builder();
+
+ if (isDemoMode) {
+ builder.setCountOfDemoModeOutgoingDatagramFail(ADD_COUNT);
+ } else {
+ builder.setCountOfOutgoingDatagramFail(ADD_COUNT);
}
+
+ if (SatelliteServiceUtils.isSosMessage(datagramType)) {
+ builder.setCountOfDatagramTypeSosSmsFail(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING) {
+ builder.setCountOfDatagramTypeLocationSharingFail(ADD_COUNT);
+ } else if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ builder.setCountOfDatagramTypeKeepAliveFail(ADD_COUNT);
+ }
+
+ SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
logd("reportOutgoingDatagramFailCount(): " + controllerParam);
mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
}
/** Report a counter when an attempt for incoming datagram is failed */
public void reportIncomingDatagramCount(
- @NonNull @SatelliteManager.SatelliteResult int result) {
- SatelliteStats.SatelliteControllerParams controllerParam;
- if (result == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
- controllerParam = new SatelliteStats.SatelliteControllerParams.Builder()
- .setCountOfIncomingDatagramSuccess(ADD_COUNT)
- .build();
+ @NonNull @SatelliteManager.SatelliteResult int result, boolean isDemoMode) {
+ SatelliteStats.SatelliteControllerParams.Builder builder =
+ new SatelliteStats.SatelliteControllerParams.Builder();
+ if (isDemoMode) {
+ if (result == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ builder.setCountOfDemoModeIncomingDatagramSuccess(ADD_COUNT);
+ } else {
+ builder.setCountOfDemoModeIncomingDatagramFail(ADD_COUNT);
+ }
} else {
- controllerParam = new SatelliteStats.SatelliteControllerParams.Builder()
- .setCountOfIncomingDatagramFail(ADD_COUNT)
- .build();
+ if (result == SatelliteManager.SATELLITE_RESULT_SUCCESS) {
+ builder.setCountOfIncomingDatagramSuccess(ADD_COUNT);
+ } else {
+ builder.setCountOfIncomingDatagramFail(ADD_COUNT);
+ }
}
+ SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
logd("reportIncomingDatagramCount(): " + controllerParam);
mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
}
@@ -225,6 +236,36 @@
mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
}
+ /**
+ * Report a counter when checking result whether satellite communication is allowed or not for
+ * current location.
+ */
+ public void reportAllowedSatelliteAccessCount(boolean isAllowed) {
+ SatelliteStats.SatelliteControllerParams.Builder builder;
+ if (isAllowed) {
+ builder = new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfAllowedSatelliteAccess(ADD_COUNT);
+ } else {
+ builder = new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfDisallowedSatelliteAccess(ADD_COUNT);
+ }
+ SatelliteStats.SatelliteControllerParams controllerParam = builder.build();
+ logd("reportAllowedSatelliteAccessCount:" + controllerParam);
+ mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
+ }
+
+ /**
+ * Report a counter when checking whether satellite communication for current location is
+ * allowed has failed.
+ */
+ public void reportFailedSatelliteAccessCheckCount() {
+ SatelliteStats.SatelliteControllerParams controllerParam =
+ new SatelliteStats.SatelliteControllerParams.Builder()
+ .setCountOfSatelliteAccessCheckFail(ADD_COUNT).build();
+ logd("reportFailedSatelliteAccessCheckCount:" + controllerParam);
+ mSatelliteStats.onSatelliteControllerMetrics(controllerParam);
+ }
+
/** Return the total service up time for satellite service */
@VisibleForTesting
public int captureTotalServiceUpTimeSec() {
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java
new file mode 100644
index 0000000..4862188
--- /dev/null
+++ b/src/java/com/android/internal/telephony/satellite/metrics/EntitlementMetricsStats.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite.metrics;
+
+import android.annotation.NonNull;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.util.Log;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.PhoneFactory;
+import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.satellite.SatelliteConstants;
+
+public class EntitlementMetricsStats {
+ private static final String TAG = EntitlementMetricsStats.class.getSimpleName();
+ private static EntitlementMetricsStats sInstance = null;
+ private static final int RESULT_SUCCESS = 200;
+
+ private int mSubId;
+ private int mResult;
+ private int mEntitlementStatus;
+ private boolean mIsRetry;
+
+ private EntitlementMetricsStats() {}
+
+ /**
+ * Returns the Singleton instance of EntitlementMetricsStats class.
+ * If an instance of the Singleton class has not been created,
+ * it creates a new instance and returns it. Otherwise, it returns
+ * the existing instance.
+ * @return the Singleton instance of EntitlementMetricsStats
+ */
+ public static EntitlementMetricsStats getOrCreateInstance() {
+ if (sInstance == null) {
+ logd("Create new EntitlementMetricsStats.");
+ sInstance = new EntitlementMetricsStats();
+ }
+ return sInstance;
+ }
+
+ /** Report metrics on entitlement query request success */
+ public void reportSuccess(int subId,
+ @SatelliteConstants.SatelliteEntitlementStatus int entitlementStatus,
+ boolean isRetry) {
+ mSubId = subId;
+ mResult = RESULT_SUCCESS;
+ mEntitlementStatus = entitlementStatus;
+ mIsRetry = isRetry;
+ reportEntitlementMetrics();
+ }
+
+ /** Report metrics on entitlement query request error */
+ public void reportError(int subId, int result, boolean isRetry) {
+ mSubId = subId;
+ mResult = result;
+ mIsRetry = isRetry;
+ mEntitlementStatus = SatelliteConstants.SATELLITE_ENTITLEMENT_STATUS_UNKNOWN;
+ reportEntitlementMetrics();
+ }
+
+ /** Report entitlement metrics atom to PersistAtomsStorage in telephony */
+ private void reportEntitlementMetrics() {
+ SatelliteStats.SatelliteEntitlementParams entitlementParams =
+ new SatelliteStats.SatelliteEntitlementParams.Builder()
+ .setCarrierId(getCarrierId(mSubId))
+ .setResult(mResult)
+ .setEntitlementStatus(mEntitlementStatus)
+ .setIsRetry(mIsRetry)
+ .setCount(1)
+ .build();
+ SatelliteStats.getInstance().onSatelliteEntitlementMetrics(entitlementParams);
+ logd("reportEntitlementMetrics: " + entitlementParams);
+
+ CarrierRoamingSatelliteControllerStats.getOrCreateInstance()
+ .reportCountOfEntitlementStatusQueryRequest();
+ }
+
+ /** Returns the carrier ID of the given subscription id. */
+ private int getCarrierId(int subId) {
+ int phoneId = SubscriptionManager.getPhoneId(subId);
+ Phone phone = PhoneFactory.getPhone(phoneId);
+ return phone != null ? phone.getCarrierId() : TelephonyManager.UNKNOWN_CARRIER_ID;
+ }
+
+ private static void logd(@NonNull String log) {
+ Log.d(TAG, log);
+ }
+}
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/ProvisionMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/ProvisionMetricsStats.java
index d48c488..0647231 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/ProvisionMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/ProvisionMetricsStats.java
@@ -91,7 +91,7 @@
.setIsCanceled(mIsCanceled)
.build();
SatelliteStats.getInstance().onSatelliteProvisionMetrics(provisionParams);
- logd(provisionParams.toString());
+ logd("reportProvisionMetrics: " + provisionParams.toString());
initializeProvisionParams();
}
diff --git a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
index 6585bec..65181c0 100644
--- a/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
+++ b/src/java/com/android/internal/telephony/satellite/metrics/SessionMetricsStats.java
@@ -16,11 +16,19 @@
package com.android.internal.telephony.satellite.metrics;
+import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_NONE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
import android.annotation.NonNull;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteManager;
+import android.telephony.satellite.SatelliteSessionStats;
import android.util.Log;
import com.android.internal.telephony.metrics.SatelliteStats;
+import com.android.internal.telephony.satellite.DatagramDispatcher;
/**
* Stats to log to satellite session metrics
@@ -32,6 +40,18 @@
private static SessionMetricsStats sInstance = null;
private @SatelliteManager.SatelliteResult int mInitializationResult;
private @SatelliteManager.NTRadioTechnology int mRadioTechnology;
+ private @SatelliteManager.SatelliteResult int mTerminationResult;
+ private long mInitializationProcessingTimeMillis;
+ private long mTerminationProcessingTimeMillis;
+ private int mSessionDurationSec;
+ private int mCountOfSuccessfulOutgoingDatagram;
+ private int mCountOfFailedOutgoingDatagram;
+ private int mCountOfTimedOutUserMessagesWaitingForConnection;
+ private int mCountOfTimedOutUserMessagesWaitingForAck;
+ private int mCountOfSuccessfulIncomingDatagram;
+ private int mCountOfIncomingDatagramFailed;
+ private boolean mIsDemoMode;
+ private @NtnSignalStrength.NtnSignalStrengthLevel int mMaxNtnSignalStrengthLevel;
private SessionMetricsStats() {
initializeSessionMetricsParam();
@@ -42,7 +62,7 @@
* If an instance of the Singleton class has not been created,
* it creates a new instance and returns it. Otherwise, it returns
* the existing instance.
- * @return the Singleton instance of SessionMetricsStats
+ * @return the Singleton instance of SessionMetricsStats.
*/
public static SessionMetricsStats getInstance() {
if (sInstance == null) {
@@ -52,7 +72,7 @@
return sInstance;
}
- /** Sets the satellite initialization result */
+ /** Sets the satellite initialization result. */
public SessionMetricsStats setInitializationResult(
@SatelliteManager.SatelliteResult int result) {
logd("setInitializationResult(" + result + ")");
@@ -60,29 +80,203 @@
return this;
}
- /** Sets the satellite ratio technology */
- public SessionMetricsStats setRadioTechnology(
+ /** Sets the satellite ratio technology. */
+ public SessionMetricsStats setSatelliteTechnology(
@SatelliteManager.NTRadioTechnology int radioTechnology) {
- logd("setRadioTechnology(" + radioTechnology + ")");
+ logd("setSatelliteTechnology(" + radioTechnology + ")");
mRadioTechnology = radioTechnology;
return this;
}
- /** Report the session metrics atoms to PersistAtomsStorage in telephony */
+ /** Sets the satellite de-initialization result. */
+ public SessionMetricsStats setTerminationResult(
+ @SatelliteManager.SatelliteResult int result) {
+ logd("setTerminationResult(" + result + ")");
+ mTerminationResult = result;
+ return this;
+ }
+
+ /** Sets the satellite initialization processing time. */
+ public SessionMetricsStats setInitializationProcessingTime(long processingTime) {
+ logd("setInitializationProcessingTime(" + processingTime + ")");
+ mInitializationProcessingTimeMillis = processingTime;
+ return this;
+ }
+
+ /** Sets the satellite de-initialization processing time. */
+ public SessionMetricsStats setTerminationProcessingTime(long processingTime) {
+ logd("setTerminationProcessingTime(" + processingTime + ")");
+ mTerminationProcessingTimeMillis = processingTime;
+ return this;
+ }
+
+ /** Sets the total enabled time for the satellite session. */
+ public SessionMetricsStats setSessionDurationSec(int sessionDurationSec) {
+ logd("setSessionDuration(" + sessionDurationSec + ")");
+ mSessionDurationSec = sessionDurationSec;
+ return this;
+ }
+
+ /** Increase the count of successful outgoing datagram transmission. */
+ public SessionMetricsStats addCountOfSuccessfulOutgoingDatagram(
+ @NonNull @SatelliteManager.DatagramType int datagramType) {
+ if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ // Ignore KEEP_ALIVE messages
+ return this;
+ }
+
+ mCountOfSuccessfulOutgoingDatagram++;
+ logd("addCountOfSuccessfulOutgoingDatagram: current count="
+ + mCountOfSuccessfulOutgoingDatagram);
+ return this;
+ }
+
+ /** Increase the count of failed outgoing datagram transmission. */
+ public SessionMetricsStats addCountOfFailedOutgoingDatagram(
+ @NonNull @SatelliteManager.DatagramType int datagramType,
+ @NonNull @SatelliteManager.SatelliteResult int resultCode) {
+ if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ // Ignore KEEP_ALIVE messages
+ return this;
+ }
+
+ mCountOfFailedOutgoingDatagram++;
+ logd("addCountOfFailedOutgoingDatagram: current count=" + mCountOfFailedOutgoingDatagram);
+
+ if (resultCode == SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE) {
+ addCountOfTimedOutUserMessagesWaitingForConnection(datagramType);
+ } else if (resultCode == SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT) {
+ addCountOfTimedOutUserMessagesWaitingForAck(datagramType);
+ }
+
+ return this;
+ }
+
+ /** Increase the count of user messages that timed out waiting for connection. */
+ private SessionMetricsStats addCountOfTimedOutUserMessagesWaitingForConnection(
+ @NonNull @SatelliteManager.DatagramType int datagramType) {
+ if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ // Ignore KEEP_ALIVE messages
+ return this;
+ }
+
+ mCountOfTimedOutUserMessagesWaitingForConnection++;
+ logd("addCountOfTimedOutUserMessagesWaitingForConnection: current count="
+ + mCountOfTimedOutUserMessagesWaitingForConnection);
+ return this;
+ }
+
+ /** Increase the count of user messages that timed out waiting for ack. */
+ private SessionMetricsStats addCountOfTimedOutUserMessagesWaitingForAck(
+ @NonNull @SatelliteManager.DatagramType int datagramType) {
+ if (datagramType == SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE) {
+ // Ignore KEEP_ALIVE messages
+ return this;
+ }
+
+ mCountOfTimedOutUserMessagesWaitingForAck++;
+ logd("addCountOfTimedOutUserMessagesWaitingForAck: current count="
+ + mCountOfTimedOutUserMessagesWaitingForAck);
+ return this;
+ }
+
+ /** Increase the count of successful incoming datagram transmission. */
+ public SessionMetricsStats addCountOfSuccessfulIncomingDatagram() {
+ mCountOfSuccessfulIncomingDatagram++;
+ logd("addCountOfSuccessfulIncomingDatagram: current count="
+ + mCountOfSuccessfulIncomingDatagram);
+ return this;
+ }
+
+ /** Increase the count of failed incoming datagram transmission. */
+ public SessionMetricsStats addCountOfFailedIncomingDatagram() {
+ mCountOfIncomingDatagramFailed++;
+ logd("addCountOfFailedIncomingDatagram: current count=" + mCountOfIncomingDatagramFailed);
+ return this;
+ }
+
+ /** Sets whether the session is enabled for demo mode or not. */
+ public SessionMetricsStats setIsDemoMode(boolean isDemoMode) {
+ mIsDemoMode = isDemoMode;
+ logd("setIsDemoMode(" + mIsDemoMode + ")");
+ return this;
+ }
+
+ /** Updates the max Ntn signal strength level for the session. */
+ public SessionMetricsStats updateMaxNtnSignalStrengthLevel(
+ @NtnSignalStrength.NtnSignalStrengthLevel int latestNtnSignalStrengthLevel) {
+ if (latestNtnSignalStrengthLevel > mMaxNtnSignalStrengthLevel) {
+ mMaxNtnSignalStrengthLevel = latestNtnSignalStrengthLevel;
+ }
+ logd("updateMaxNtnSignalsStrength: latest signal strength=" + latestNtnSignalStrengthLevel
+ + ", max signal strength=" + mMaxNtnSignalStrengthLevel);
+ return this;
+ }
+
+ /** Report the session metrics atoms to PersistAtomsStorage in telephony. */
public void reportSessionMetrics() {
SatelliteStats.SatelliteSessionParams sessionParams =
new SatelliteStats.SatelliteSessionParams.Builder()
.setSatelliteServiceInitializationResult(mInitializationResult)
.setSatelliteTechnology(mRadioTechnology)
+ .setTerminationResult(mTerminationResult)
+ .setInitializationProcessingTime(mInitializationProcessingTimeMillis)
+ .setTerminationProcessingTime(mTerminationProcessingTimeMillis)
+ .setSessionDuration(mSessionDurationSec)
+ .setCountOfOutgoingDatagramSuccess(mCountOfSuccessfulOutgoingDatagram)
+ .setCountOfOutgoingDatagramFailed(mCountOfFailedOutgoingDatagram)
+ .setCountOfIncomingDatagramSuccess(mCountOfSuccessfulIncomingDatagram)
+ .setCountOfIncomingDatagramFailed(mCountOfIncomingDatagramFailed)
+ .setIsDemoMode(mIsDemoMode)
+ .setMaxNtnSignalStrengthLevel(mMaxNtnSignalStrengthLevel)
.build();
- logd(sessionParams.toString());
+ logd("reportSessionMetrics: " + sessionParams.toString());
SatelliteStats.getInstance().onSatelliteSessionMetrics(sessionParams);
initializeSessionMetricsParam();
}
+ /** Returns {@link SatelliteSessionStats} of the satellite service. */
+ public void requestSatelliteSessionStats(int subId, @NonNull ResultReceiver result) {
+ Bundle bundle = new Bundle();
+ SatelliteSessionStats sessionStats = new SatelliteSessionStats.Builder()
+ .setCountOfSuccessfulUserMessages(mCountOfSuccessfulOutgoingDatagram)
+ .setCountOfUnsuccessfulUserMessages(mCountOfFailedOutgoingDatagram)
+ .setCountOfTimedOutUserMessagesWaitingForConnection(
+ mCountOfTimedOutUserMessagesWaitingForConnection)
+ .setCountOfTimedOutUserMessagesWaitingForAck(
+ mCountOfTimedOutUserMessagesWaitingForAck)
+ .setCountOfUserMessagesInQueueToBeSent(
+ DatagramDispatcher.getInstance().getPendingUserMessagesCount())
+ .build();
+ bundle.putParcelable(SatelliteManager.KEY_SESSION_STATS, sessionStats);
+ result.send(SATELLITE_RESULT_SUCCESS, bundle);
+ }
+
+ /** Returns the processing time for satellite session initialization. */
+ public long getSessionInitializationProcessingTimeMillis() {
+ return mInitializationProcessingTimeMillis;
+ }
+
+ /** Returns the processing time for satellite session termination. */
+ public long getSessionTerminationProcessingTimeMillis() {
+ return mTerminationProcessingTimeMillis;
+ }
+
private void initializeSessionMetricsParam() {
mInitializationResult = SatelliteManager.SATELLITE_RESULT_SUCCESS;
mRadioTechnology = SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN;
+ mTerminationResult = SatelliteManager.SATELLITE_RESULT_SUCCESS;
+ mInitializationProcessingTimeMillis = 0;
+ mTerminationProcessingTimeMillis = 0;
+ mSessionDurationSec = 0;
+ mCountOfSuccessfulOutgoingDatagram = 0;
+ mCountOfFailedOutgoingDatagram = 0;
+ mCountOfTimedOutUserMessagesWaitingForConnection = 0;
+ mCountOfTimedOutUserMessagesWaitingForAck = 0;
+ mCountOfSuccessfulIncomingDatagram = 0;
+ mCountOfIncomingDatagramFailed = 0;
+ mIsDemoMode = false;
+ mMaxNtnSignalStrengthLevel = NTN_SIGNAL_STRENGTH_NONE;
}
private static void logd(@NonNull String log) {
diff --git a/src/java/com/android/internal/telephony/security/CellularNetworkSecuritySafetySource.java b/src/java/com/android/internal/telephony/security/CellularNetworkSecuritySafetySource.java
index 34f26e3..2d4776c 100644
--- a/src/java/com/android/internal/telephony/security/CellularNetworkSecuritySafetySource.java
+++ b/src/java/com/android/internal/telephony/security/CellularNetworkSecuritySafetySource.java
@@ -25,11 +25,14 @@
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Resources;
+import android.net.Uri;
import android.safetycenter.SafetyCenterManager;
import android.safetycenter.SafetyEvent;
import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceIssue;
import android.safetycenter.SafetySourceStatus;
+import android.text.format.DateFormat;
import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -39,8 +42,10 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.Instant;
-import java.util.Date;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;
@@ -62,10 +67,6 @@
private static final Intent CELLULAR_NETWORK_SECURITY_SETTINGS_INTENT =
new Intent("android.settings.CELLULAR_NETWORK_SECURITY");
- // TODO(b/321999913): direct to a help page URL e.g.
- // new Intent(Intent.ACTION_VIEW, Uri.parse("https://..."));
- private static final Intent LEARN_MORE_INTENT = new Intent();
-
static final int NULL_CIPHER_STATE_ENCRYPTED = 0;
static final int NULL_CIPHER_STATE_NOTIFY_ENCRYPTED = 1;
static final int NULL_CIPHER_STATE_NOTIFY_NON_ENCRYPTED = 2;
@@ -123,6 +124,13 @@
}
/**
+ * Clears issue state for the identified subscription
+ */
+ public synchronized void clearNullCipherState(Context context, int subId) {
+ mNullCipherStates.remove(subId);
+ updateSafetyCenter(context);
+ }
+ /**
* Enables or disables the identifier disclosure issue and clears any current issues if the
* enable state is changed.
*/
@@ -209,6 +217,7 @@
SubscriptionInfoInternal subInfo =
mSubscriptionManagerService.getSubscriptionInfoInternal(subId);
final SafetySourceIssue.Builder builder;
+ final SafetySourceIssue.Notification customNotification;
switch (state) {
case NULL_CIPHER_STATE_ENCRYPTED:
return Optional.empty();
@@ -216,43 +225,70 @@
builder = new SafetySourceIssue.Builder(
NULL_CIPHER_ISSUE_NON_ENCRYPTED_ID + "_" + subId,
context.getString(
- R.string.scNullCipherIssueNonEncryptedTitle, subInfo.getDisplayName()),
- context.getString(R.string.scNullCipherIssueNonEncryptedSummary),
+ R.string.scNullCipherIssueNonEncryptedTitle),
+ context.getString(
+ R.string.scNullCipherIssueNonEncryptedSummary,
+ subInfo.getDisplayName()),
SEVERITY_LEVEL_RECOMMENDATION,
NULL_CIPHER_ISSUE_NON_ENCRYPTED_ID);
+ customNotification =
+ new SafetySourceIssue.Notification.Builder(
+ context.getString(R.string.scNullCipherIssueNonEncryptedTitle),
+ context.getString(
+ R.string.scNullCipherIssueNonEncryptedSummaryNotification,
+ subInfo.getDisplayName()))
+ .build();
break;
case NULL_CIPHER_STATE_NOTIFY_ENCRYPTED:
builder = new SafetySourceIssue.Builder(
NULL_CIPHER_ISSUE_NON_ENCRYPTED_ID + "_" + subId,
context.getString(
- R.string.scNullCipherIssueEncryptedTitle, subInfo.getDisplayName()),
- context.getString(R.string.scNullCipherIssueEncryptedSummary),
+ R.string.scNullCipherIssueEncryptedTitle,
+ subInfo.getDisplayName()),
+ context.getString(
+ R.string.scNullCipherIssueEncryptedSummary,
+ subInfo.getDisplayName()),
SEVERITY_LEVEL_INFORMATION,
NULL_CIPHER_ISSUE_ENCRYPTED_ID);
+ customNotification =
+ new SafetySourceIssue.Notification.Builder(
+ context.getString(
+ R.string.scNullCipherIssueEncryptedTitle,
+ subInfo.getDisplayName()),
+ context.getString(
+ R.string.scNullCipherIssueEncryptedSummary,
+ subInfo.getDisplayName()))
+ .build();
break;
default:
throw new AssertionError();
}
-
- return Optional.of(
- builder
- .setNotificationBehavior(SafetySourceIssue.NOTIFICATION_BEHAVIOR_IMMEDIATELY)
- .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
- .addAction(
+ builder
+ .setNotificationBehavior(
+ SafetySourceIssue.NOTIFICATION_BEHAVIOR_IMMEDIATELY)
+ .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DATA)
+ .setCustomNotification(customNotification)
+ .addAction(
new SafetySourceIssue.Action.Builder(
NULL_CIPHER_ACTION_SETTINGS_ID,
context.getString(R.string.scNullCipherIssueActionSettings),
mSafetyCenterManagerWrapper.getActivityPendingIntent(
context, CELLULAR_NETWORK_SECURITY_SETTINGS_INTENT))
- .build())
- .addAction(
- new SafetySourceIssue.Action.Builder(
- NULL_CIPHER_ACTION_LEARN_MORE_ID,
- context.getString(R.string.scNullCipherIssueActionLearnMore),
- mSafetyCenterManagerWrapper.getActivityPendingIntent(
- context, LEARN_MORE_INTENT))
- .build())
- .build());
+ .build());
+
+ Intent learnMoreIntent = getLearnMoreIntent(context);
+ if (learnMoreIntent != null) {
+ builder.addAction(
+ new SafetySourceIssue.Action.Builder(
+ NULL_CIPHER_ACTION_LEARN_MORE_ID,
+ context.getString(
+ R.string.scNullCipherIssueActionLearnMore),
+ mSafetyCenterManagerWrapper.getActivityPendingIntent(
+ context, learnMoreIntent))
+ .build());
+ }
+
+ return Optional.of(builder.build());
}
/** Builds the identity disclosure issue if it's enabled and there are disclosures to report. */
@@ -264,35 +300,77 @@
SubscriptionInfoInternal subInfo =
mSubscriptionManagerService.getSubscriptionInfoInternal(subId);
- return Optional.of(
+
+ // Notifications have no buttons
+ final SafetySourceIssue.Notification customNotification =
+ new SafetySourceIssue.Notification.Builder(
+ context.getString(R.string.scIdentifierDisclosureIssueTitle),
+ context.getString(
+ R.string.scIdentifierDisclosureIssueSummaryNotification,
+ getCurrentTime(),
+ subInfo.getDisplayName())).build();
+ SafetySourceIssue.Builder builder =
new SafetySourceIssue.Builder(
IDENTIFIER_DISCLOSURE_ISSUE_ID + "_" + subId,
context.getString(R.string.scIdentifierDisclosureIssueTitle),
context.getString(
R.string.scIdentifierDisclosureIssueSummary,
- disclosure.getDisclosureCount(),
- Date.from(disclosure.getWindowStart()),
- Date.from(disclosure.getWindowEnd()),
+ getCurrentTime(),
subInfo.getDisplayName()),
SEVERITY_LEVEL_RECOMMENDATION,
IDENTIFIER_DISCLOSURE_ISSUE_ID)
- .setNotificationBehavior(SafetySourceIssue.NOTIFICATION_BEHAVIOR_IMMEDIATELY)
- .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DEVICE)
- .addAction(
- new SafetySourceIssue.Action.Builder(
- NULL_CIPHER_ACTION_SETTINGS_ID,
- context.getString(R.string.scNullCipherIssueActionSettings),
- mSafetyCenterManagerWrapper.getActivityPendingIntent(
- context, CELLULAR_NETWORK_SECURITY_SETTINGS_INTENT))
- .build())
- .addAction(
- new SafetySourceIssue.Action.Builder(
- NULL_CIPHER_ACTION_LEARN_MORE_ID,
- context.getString(R.string.scNullCipherIssueActionLearnMore),
- mSafetyCenterManagerWrapper.getActivityPendingIntent(
- context, LEARN_MORE_INTENT))
- .build())
- .build());
+ .setNotificationBehavior(
+ SafetySourceIssue.NOTIFICATION_BEHAVIOR_IMMEDIATELY)
+ .setIssueCategory(SafetySourceIssue.ISSUE_CATEGORY_DATA)
+ .setCustomNotification(customNotification)
+ .addAction(
+ new SafetySourceIssue.Action.Builder(
+ NULL_CIPHER_ACTION_SETTINGS_ID,
+ context.getString(
+ R.string.scNullCipherIssueActionSettings),
+ mSafetyCenterManagerWrapper.getActivityPendingIntent(
+ context,
+ CELLULAR_NETWORK_SECURITY_SETTINGS_INTENT))
+ .build());
+
+ Intent learnMoreIntent = getLearnMoreIntent(context);
+ if (learnMoreIntent != null) {
+ builder.addAction(
+ new SafetySourceIssue.Action.Builder(
+ NULL_CIPHER_ACTION_LEARN_MORE_ID,
+ context.getString(R.string.scNullCipherIssueActionLearnMore),
+ mSafetyCenterManagerWrapper.getActivityPendingIntent(
+ context, learnMoreIntent)).build()
+ );
+ }
+
+ return Optional.of(builder.build());
+ }
+
+ private String getCurrentTime() {
+ String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), "hh:mm");
+ return Instant.now().atZone(ZoneId.systemDefault())
+ .format(DateTimeFormatter.ofPattern(pattern)).toString();
+ }
+
+ /**
+ * Return Intent for learn more action, or null if resource associated with the Intent
+ * uri is
+ * missing or empty.
+ */
+ private Intent getLearnMoreIntent(Context context) {
+ String learnMoreUri;
+ try {
+ learnMoreUri = context.getString(R.string.scCellularNetworkSecurityLearnMore);
+ } catch (Resources.NotFoundException e) {
+ return null;
+ }
+
+ if (learnMoreUri.isEmpty()) {
+ return null;
+ }
+
+ return new Intent(Intent.ACTION_VIEW, Uri.parse(learnMoreUri));
}
/** A wrapper around {@link SafetyCenterManager} that can be instrumented in tests. */
@@ -337,7 +415,7 @@
private IdentifierDisclosure(int count, Instant start, Instant end) {
mDisclosureCount = count;
mWindowStart = start;
- mWindowEnd = end;
+ mWindowEnd = end;
}
private int getDisclosureCount() {
diff --git a/src/java/com/android/internal/telephony/security/NullCipherNotifier.java b/src/java/com/android/internal/telephony/security/NullCipherNotifier.java
index 3ece701..e13c5b0 100644
--- a/src/java/com/android/internal/telephony/security/NullCipherNotifier.java
+++ b/src/java/com/android/internal/telephony/security/NullCipherNotifier.java
@@ -56,6 +56,7 @@
private final CellularNetworkSecuritySafetySource mSafetySource;
private final HashMap<Integer, SubscriptionState> mSubscriptionState = new HashMap<>();
+ private final HashMap<Integer, Integer> mActiveSubscriptions = new HashMap<>();
private final Object mEnabledLock = new Object();
@GuardedBy("mEnabledLock")
@@ -90,31 +91,78 @@
* Adds a security algorithm update. If appropriate, this will trigger a user notification.
*/
public void onSecurityAlgorithmUpdate(
- Context context, int subId, SecurityAlgorithmUpdate update) {
+ Context context, int phoneId, int subId, SecurityAlgorithmUpdate update) {
Rlog.d(TAG, "Security algorithm update: subId = " + subId + " " + update);
if (shouldIgnoreUpdate(update)) {
return;
}
+ if (!isEnabled()) {
+ Rlog.i(TAG, "Ignoring onSecurityAlgorithmUpdate. Notifier is disabled.");
+ return;
+ }
+
try {
mSerializedWorkQueue.execute(() -> {
- SubscriptionState subState = mSubscriptionState.get(subId);
- if (subState == null) {
- subState = new SubscriptionState();
- mSubscriptionState.put(subId, subState);
- }
+ try {
+ maybeUpdateSubscriptionMapping(context, phoneId, subId);
+ SubscriptionState subState = mSubscriptionState.get(subId);
+ if (subState == null) {
+ subState = new SubscriptionState();
+ mSubscriptionState.put(subId, subState);
+ }
- @CellularNetworkSecuritySafetySource.NullCipherState int nullCipherState =
- subState.update(update);
- mSafetySource.setNullCipherState(context, subId, nullCipherState);
+ @CellularNetworkSecuritySafetySource.NullCipherState int nullCipherState =
+ subState.update(update);
+ mSafetySource.setNullCipherState(context, subId, nullCipherState);
+ } catch (Throwable t) {
+ Rlog.e(TAG, "Failed to execute onSecurityAlgorithmUpdate " + t.getMessage());
+ }
});
} catch (RejectedExecutionException e) {
- Rlog.e(TAG, "Failed to schedule onEnableNotifier: " + e.getMessage());
+ Rlog.e(TAG, "Failed to schedule onSecurityAlgorithmUpdate: " + e.getMessage());
}
}
/**
+ * Set or update the current phoneId to subId mapping. When a new subId is mapped to a phoneId,
+ * we update the safety source to clear state of the old subId.
+ */
+ public void setSubscriptionMapping(Context context, int phoneId, int subId) {
+
+ if (!isEnabled()) {
+ Rlog.i(TAG, "Ignoring setSubscriptionMapping. Notifier is disabled.");
+ }
+
+ try {
+ mSerializedWorkQueue.execute(() -> {
+ try {
+ maybeUpdateSubscriptionMapping(context, phoneId, subId);
+ } catch (Throwable t) {
+ Rlog.e(TAG, "Failed to update subId mapping. phoneId: " + phoneId + " subId: "
+ + subId + ". " + t.getMessage());
+ }
+ });
+
+ } catch (RejectedExecutionException e) {
+ Rlog.e(TAG, "Failed to schedule setSubscriptionMapping: " + e.getMessage());
+ }
+ }
+
+ private void maybeUpdateSubscriptionMapping(Context context, int phoneId, int subId) {
+ final Integer oldSubId = mActiveSubscriptions.put(phoneId, subId);
+ if (oldSubId == null || oldSubId == subId) {
+ return;
+ }
+
+ // Our subId was updated for this phone, we should clear this subId's state.
+ mSubscriptionState.remove(oldSubId);
+ mSafetySource.clearNullCipherState(context, oldSubId);
+ }
+
+
+ /**
* Enables null cipher notification; {@code onSecurityAlgorithmUpdate} will start handling
* security algorithm updates and send notifications to the user when required.
*/
@@ -285,7 +333,7 @@
/** The state of security algorithms for a network connection. */
private static final class ConnectionState {
private static final ConnectionState UNKNOWN =
- new ConnectionState(SECURITY_ALGORITHM_UNKNOWN, SECURITY_ALGORITHM_UNKNOWN);
+ new ConnectionState(SECURITY_ALGORITHM_UNKNOWN, SECURITY_ALGORITHM_UNKNOWN);
private final @SecurityAlgorithm int mEncryption;
private final @SecurityAlgorithm int mIntegrity;
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
index 3d07d47..7596754 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionDatabaseManager.java
@@ -1044,7 +1044,7 @@
throw new IllegalArgumentException("updateSubscription: subscription does not "
+ "exist. subId=" + subId);
}
- if (oldSubInfo.equals(newSubInfo)) return;
+ if (oldSubInfo.equalsDbItemsOnly(newSubInfo)) return;
if (updateDatabase(subId, createDeltaContentValues(oldSubInfo, newSubInfo)) > 0) {
mAllSubscriptionInfoInternalCache.put(subId, newSubInfo);
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
index 82af4e8..c6dee7c 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionInfoInternal.java
@@ -454,12 +454,13 @@
*/
private final int mIsOnlyNonTerrestrialNetwork;
- // Below are the fields that do not exist in the SimInfo table.
+ // This field does not exist in the SimInfo table.
/**
* The card ID of the SIM card. This maps uniquely to {@link #mCardString}.
*/
private final int mCardId;
+ // This field does not exist in the SimInfo table.
/**
* Whether group of the subscription is disabled. This is only useful if it's a grouped
* opportunistic subscription. In this case, if all primary (non-opportunistic) subscriptions
@@ -1217,7 +1218,22 @@
* @return {@code true} if the subscription is visible to the user.
*/
public boolean isVisible() {
- return !isOpportunistic() || TextUtils.isEmpty(mGroupUuid);
+ // Provisioning profile
+ if (getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING) {
+ return false;
+ }
+
+ // Satellite profile
+ if (getOnlyNonTerrestrialNetwork() == 1) {
+ return false;
+ }
+
+ // Opportunistic profile
+ if (isOpportunistic() && !TextUtils.isEmpty(mGroupUuid)) {
+ return false;
+ }
+
+ return true;
}
/**
@@ -1355,11 +1371,14 @@
+ "]";
}
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- SubscriptionInfoInternal that = (SubscriptionInfoInternal) o;
+ /**
+ * Campare only the columns existing in the SimInfo table and the mapped variables to see if
+ * they are equal.
+ *
+ * @param that SubscriptionInfoInternal to be compared
+ * @return {@code true} if equals.
+ */
+ public boolean equalsDbItemsOnly(@NonNull SubscriptionInfoInternal that) {
return mId == that.mId && mSimSlotIndex == that.mSimSlotIndex
&& mDisplayNameSource == that.mDisplayNameSource && mIconTint == that.mIconTint
&& mDataRoaming == that.mDataRoaming && mIsEmbedded == that.mIsEmbedded
@@ -1392,7 +1411,6 @@
&& mPortIndex == that.mPortIndex && mUsageSetting == that.mUsageSetting
&& mLastUsedTPMessageReference == that.mLastUsedTPMessageReference
&& mUserId == that.mUserId && mIsSatelliteEnabled == that.mIsSatelliteEnabled
- && mCardId == that.mCardId && mIsGroupDisabled == that.mIsGroupDisabled
&& mIccId.equals(that.mIccId) && mDisplayName.equals(that.mDisplayName)
&& mCarrierName.equals(that.mCarrierName) && mNumber.equals(that.mNumber)
&& mMcc.equals(that.mMcc) && mMnc.equals(that.mMnc) && mEhplmns.equals(
@@ -1416,6 +1434,15 @@
}
@Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SubscriptionInfoInternal that = (SubscriptionInfoInternal) o;
+ return equalsDbItemsOnly(that)
+ && mCardId == that.mCardId && mIsGroupDisabled == that.mIsGroupDisabled;
+ }
+
+ @Override
public int hashCode() {
int result = Objects.hash(mId, mIccId, mSimSlotIndex, mDisplayName, mCarrierName,
mDisplayNameSource, mIconTint, mNumber, mDataRoaming, mMcc, mMnc, mEhplmns, mHplmns,
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index 5e066e1..0e98a9e 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -42,6 +42,7 @@
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.CountDownTimer;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -104,6 +105,7 @@
import com.android.internal.telephony.euicc.EuiccController;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.flags.Flags;
+import com.android.internal.telephony.satellite.SatelliteController;
import com.android.internal.telephony.subscription.SubscriptionDatabaseManager.SubscriptionDatabaseManagerCallback;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.IccUtils;
@@ -124,6 +126,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.UUID;
@@ -142,6 +145,9 @@
private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem";
private static final String BOOT_ALLOW_MOCK_MODEM_PROPERTY = "ro.boot.radio.allow_mock_modem";
+ private static final int CHECK_BOOTSTRAP_TIMER_IN_MS = 20 * 60 * 1000; // 20 minutes
+ private static CountDownTimer bootstrapProvisioningTimer;
+
/** Whether enabling verbose debugging message or not. */
private static final boolean VDBG = false;
@@ -937,9 +943,13 @@
*
* @param subId Subscription id.
* @param groupOwner The group owner to assign to the subscription
+ *
+ * @throws SecurityException if the caller does not have required permissions.
*/
+ @Override
+ @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setGroupOwner(int subId, @NonNull String groupOwner) {
- // This can throw IllegalArgumentException if the subscription does not exist.
+ enforcePermissions("setGroupOwner", Manifest.permission.MODIFY_PHONE_STATE);
try {
mSubscriptionDatabaseManager.setGroupOwner(
subId,
@@ -1171,7 +1181,7 @@
SubscriptionManager.INVALID_SIM_SLOT_INDEX,
null, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
mSubscriptionDatabaseManager.setDisplayName(subId, mContext.getResources()
- .getString(R.string.default_card_name, subId));
+ .getString(R.string.default_card_name, getCardNumber(subId)));
subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId);
}
@@ -1414,27 +1424,39 @@
}
if (simState == TelephonyManager.SIM_STATE_ABSENT) {
- // Re-enable the pSIM when it's removed, so it will be in enabled state when it gets
- // re-inserted again. (pre-U behavior)
- List<String> iccIds = getIccIdsOfInsertedPhysicalSims();
- mSubscriptionDatabaseManager.getAllSubscriptions().stream()
- // All the removed pSIMs (Note this could include some erased eSIM that has
- // embedded bit removed).
- .filter(subInfo -> !iccIds.contains(subInfo.getIccId())
- && !subInfo.isEmbedded())
- .forEach(subInfo -> {
- int subId = subInfo.getSubscriptionId();
- log("updateSubscription: Re-enable Uicc application on sub " + subId);
- mSubscriptionDatabaseManager.setUiccApplicationsEnabled(subId, true);
- // When sim is absent, set the port index to invalid port index.
- // (pre-U behavior)
- mSubscriptionDatabaseManager.setPortIndex(subId,
- TelephonyManager.INVALID_PORT_INDEX);
- });
+ SatelliteController satelliteController = SatelliteController.getInstance();
+ boolean isSatelliteEnabledOrBeingEnabled = false;
+ if (satelliteController != null) {
+ isSatelliteEnabledOrBeingEnabled = satelliteController.isSatelliteEnabled()
+ || satelliteController.isSatelliteBeingEnabled();
+ }
+
+ if (!isSatelliteEnabledOrBeingEnabled) {
+ // Re-enable the pSIM when it's removed, so it will be in enabled state when it gets
+ // re-inserted again. (pre-U behavior)
+ List<String> iccIds = getIccIdsOfInsertedPhysicalSims();
+ mSubscriptionDatabaseManager.getAllSubscriptions().stream()
+ .filter(subInfo -> !iccIds.contains(subInfo.getIccId())
+ && !subInfo.isEmbedded())
+ .forEach(subInfo -> {
+ int subId = subInfo.getSubscriptionId();
+ log("updateSubscription: Re-enable Uicc application on sub " + subId);
+ mSubscriptionDatabaseManager.setUiccApplicationsEnabled(subId, true);
+ // When sim is absent, set the port index to invalid port index.
+ // (pre-U behavior)
+ mSubscriptionDatabaseManager.setPortIndex(subId,
+ TelephonyManager.INVALID_PORT_INDEX);
+ });
+ }
if (mSlotIndexToSubId.containsKey(phoneId)) {
markSubscriptionsInactive(phoneId);
}
+
+ if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) {
+ // Clear the cached Ims phone number
+ setNumberFromIms(getSubId(phoneId), new String(""));
+ }
} else if (simState == TelephonyManager.SIM_STATE_NOT_READY) {
// Check if this is the final state. Only update the subscription if NOT_READY is a
// final state.
@@ -1447,6 +1469,11 @@
} else {
logl("updateSubscription: UICC app disabled on slot " + phoneId);
markSubscriptionsInactive(phoneId);
+
+ if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) {
+ // Clear the cached Ims phone number
+ setNumberFromIms(getSubId(phoneId), new String(""));
+ }
}
} else {
String iccId = getIccId(phoneId);
@@ -1478,7 +1505,8 @@
subId = insertSubscriptionInfo(iccId, phoneId, null,
SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
mSubscriptionDatabaseManager.setDisplayName(subId,
- mContext.getResources().getString(R.string.default_card_name, subId));
+ mContext.getResources().getString(R.string.default_card_name,
+ getCardNumber(subId)));
} else {
subId = subInfo.getSubscriptionId();
log("updateSubscription: Found existing subscription. subId= " + subId
@@ -1554,12 +1582,6 @@
loge("updateSubscription: ICC card is not available.");
}
- if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) {
- // Clear the cached Ims phone number
- // before proceeding with Ims Registration
- setNumberFromIms(subId, new String(""));
- }
-
// Attempt to restore SIM specific settings when SIM is loaded.
Bundle result = mContext.getContentResolver().call(
SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI,
@@ -1569,6 +1591,10 @@
SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED)) {
logl("Sim specific settings changed the database.");
mSubscriptionDatabaseManager.reloadDatabaseSync();
+ if (mFeatureFlags.backupAndRestoreForEnable2g()) {
+ PhoneFactory.getPhone(phoneId)
+ .loadAllowedNetworksFromSubscriptionDatabase();
+ }
}
}
@@ -1588,6 +1614,43 @@
updateGroupDisabled();
updateDefaultSubId();
+
+ if (mSlotIndexToSubId.containsKey(phoneId) &&
+ isEsimBootStrapProvisioningActiveForSubId(mSlotIndexToSubId.get(phoneId))) {
+ startEsimBootstrapTimer();
+ } else {
+ cancelEsimBootstrapTimer();
+ }
+ }
+
+ private void cancelEsimBootstrapTimer() {
+ if (bootstrapProvisioningTimer != null) {
+ bootstrapProvisioningTimer.cancel();
+ bootstrapProvisioningTimer = null;
+ log("bootstrapProvisioningTimer timer cancelled.");
+ }
+ }
+
+ private void startEsimBootstrapTimer() {
+ if (bootstrapProvisioningTimer == null) {
+ bootstrapProvisioningTimer = new CountDownTimer(CHECK_BOOTSTRAP_TIMER_IN_MS,
+ CHECK_BOOTSTRAP_TIMER_IN_MS) {
+ @Override
+ public void onTick(long millisUntilFinished) {
+ // Do nothing
+ }
+
+ @Override
+ public void onFinish() {
+ AnomalyReporter.reportAnomaly(UUID.fromString("40587b0f-27c9-4b39-b94d"
+ + "-71fc9771f354"), "eSim bootstrap has been active for too "
+ + "long.");
+ log("bootstrapProvisioningTimer: timer finished esim was not disabled.");
+ cancelEsimBootstrapTimer();
+ }
+ }.start();
+ log("bootstrapProvisioningTimer timer started.");
+ }
}
/**
@@ -3716,42 +3779,114 @@
"carrier privileges",
})
public String getPhoneNumber(int subId, @PhoneNumberSource int source,
- @NonNull String callingPackage, @Nullable String callingFeatureId) {
+ @NonNull String callingPackage, @Nullable String callingFeatureId /* unused */) {
TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges(
mContext, subId, Binder.getCallingUid(), "getPhoneNumber",
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
-
enforceTelephonyFeatureWithException(callingPackage, "getPhoneNumber");
- final long identity = Binder.clearCallingIdentity();
+ if (mFeatureFlags.saferGetPhoneNumber()) {
+ checkPhoneNumberSource(source);
+ subId = checkAndGetSubId(subId);
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return "";
- SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return getPhoneNumberFromSourceInternal(subId, source);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ } else {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
+ .getSubscriptionInfoInternal(subId);
+
+ if (subInfo == null) {
+ loge("Invalid sub id " + subId + ", callingPackage=" + callingPackage);
+ return "";
+ }
+
+ switch(source) {
+ case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
+ Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
+ if (phone != null) {
+ return TextUtils.emptyIfNull(phone.getLine1Number());
+ } else {
+ return subInfo.getNumber();
+ }
+ case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER:
+ return subInfo.getNumberFromCarrier();
+ case SubscriptionManager.PHONE_NUMBER_SOURCE_IMS:
+ return subInfo.getNumberFromIms();
+ default:
+ throw new IllegalArgumentException("Invalid number source " + source);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ /**
+ * Get a resolved subId based on what the user passed in.
+ *
+ * Only use this before clearing the calling binder. Used for compatibility (only).
+ * Do not use this behavior for new methods.
+ *
+ * @param subId the subId passed in by the user.
+ */
+ private int checkAndGetSubId(int subId) {
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ // for historical reasons, INVALID_SUB_ID fails gracefully
+ return subId;
+ } else if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ return getDefaultSubId();
+ } else if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ throw new IllegalArgumentException("Invalid SubId=" + subId);
+ } else {
+ return subId;
+ }
+ }
+
+ private void checkPhoneNumberSource(int source) {
+ if (source == SubscriptionManager.PHONE_NUMBER_SOURCE_UICC
+ || source == SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER
+ || source == SubscriptionManager.PHONE_NUMBER_SOURCE_IMS) {
+ return;
+ }
+
+ throw new IllegalArgumentException("Invalid number source " + source);
+ }
+
+ private @NonNull String getPhoneNumberFromSourceInternal(
+ int subId,
+ @PhoneNumberSource int source) {
+
+ final SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
.getSubscriptionInfoInternal(subId);
if (subInfo == null) {
- loge("Invalid sub id " + subId + ", callingPackage=" + callingPackage);
+ loge("No SubscriptionInfo found for subId=" + subId);
return "";
}
- try {
- switch(source) {
- case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
- Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
- if (phone != null) {
- return TextUtils.emptyIfNull(phone.getLine1Number());
- } else {
- return subInfo.getNumber();
- }
- case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER:
- return subInfo.getNumberFromCarrier();
- case SubscriptionManager.PHONE_NUMBER_SOURCE_IMS:
- return subInfo.getNumberFromIms();
- default:
- throw new IllegalArgumentException("Invalid number source " + source);
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
+ switch(source) {
+ case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC:
+ final Phone phone = PhoneFactory.getPhone(getSlotIndex(subId));
+ if (phone != null) {
+ return TextUtils.emptyIfNull(phone.getLine1Number());
+ } else {
+ return subInfo.getNumber();
+ }
+ case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER:
+ return subInfo.getNumberFromCarrier();
+ case SubscriptionManager.PHONE_NUMBER_SOURCE_IMS:
+ return subInfo.getNumberFromIms();
+ default:
+ loge("No SubscriptionInfo found for subId=" + subId);
+ return "";
}
}
@@ -3787,25 +3922,51 @@
enforceTelephonyFeatureWithException(callingPackage,
"getPhoneNumberFromFirstAvailableSource");
- String numberFromCarrier = getPhoneNumber(subId,
- SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, callingPackage,
- callingFeatureId);
- if (!TextUtils.isEmpty(numberFromCarrier)) {
- return numberFromCarrier;
+ if (mFeatureFlags.saferGetPhoneNumber()) {
+ subId = checkAndGetSubId(subId);
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return "";
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ String number;
+ number = getPhoneNumberFromSourceInternal(
+ subId,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER);
+ if (!TextUtils.isEmpty(number)) return number;
+
+ number = getPhoneNumberFromSourceInternal(
+ subId,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_UICC);
+ if (!TextUtils.isEmpty(number)) return number;
+
+ number = getPhoneNumberFromSourceInternal(
+ subId,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_IMS);
+ return TextUtils.emptyIfNull(number);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ } else {
+ String numberFromCarrier = getPhoneNumber(subId,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, callingPackage,
+ callingFeatureId);
+ if (!TextUtils.isEmpty(numberFromCarrier)) {
+ return numberFromCarrier;
+ }
+ String numberFromUicc = getPhoneNumber(
+ subId, SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, callingPackage,
+ callingFeatureId);
+ if (!TextUtils.isEmpty(numberFromUicc)) {
+ return numberFromUicc;
+ }
+ String numberFromIms = getPhoneNumber(
+ subId, SubscriptionManager.PHONE_NUMBER_SOURCE_IMS, callingPackage,
+ callingFeatureId);
+ if (!TextUtils.isEmpty(numberFromIms)) {
+ return numberFromIms;
+ }
+ return "";
}
- String numberFromUicc = getPhoneNumber(
- subId, SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, callingPackage,
- callingFeatureId);
- if (!TextUtils.isEmpty(numberFromUicc)) {
- return numberFromUicc;
- }
- String numberFromIms = getPhoneNumber(
- subId, SubscriptionManager.PHONE_NUMBER_SOURCE_IMS, callingPackage,
- callingFeatureId);
- if (!TextUtils.isEmpty(numberFromIms)) {
- return numberFromIms;
- }
- return "";
}
/**
@@ -4153,6 +4314,10 @@
SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED)) {
logl("Sim specific settings changed the database.");
mSubscriptionDatabaseManager.reloadDatabaseSync();
+ if (mFeatureFlags.backupAndRestoreForEnable2g()) {
+ Arrays.stream(PhoneFactory.getPhones())
+ .forEach(Phone::loadAllowedNetworksFromSubscriptionDatabase);
+ }
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -4417,13 +4582,49 @@
public List<String> getSatelliteEntitlementPlmnList(int subId) {
SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(
subId);
- if (subInfo == null) {
- loge("getSatelliteEntitlementPlmnList: invalid subId=" + subId);
- return new ArrayList<>();
+
+ return Optional.ofNullable(subInfo)
+ .map(SubscriptionInfoInternal::getSatelliteEntitlementPlmns)
+ .filter(s -> !s.isEmpty())
+ .map(s -> Arrays.stream(s.split(",")).collect(Collectors.toList()))
+ .orElse(new ArrayList<>());
+ }
+
+ /**
+ * checks whether esim bootstrap is activated for any of the available active subscription info
+ * list.
+ *
+ * @return {@code true} if esim bootstrap is activated for any of the active subscription,
+ * else {@code false}
+ *
+ */
+ public boolean isEsimBootStrapProvisioningActivated() {
+ if (!mFeatureFlags.esimBootstrapProvisioningFlag()) {
+ return false;
}
- return Arrays.stream(subInfo.getSatelliteEntitlementPlmns().split(",")).collect(
- Collectors.toList());
+ List<SubscriptionInfo> activeSubInfos =
+ getActiveSubscriptionInfoList(mContext.getOpPackageName(),
+ mContext.getAttributionTag(), true/*isForAllProfile*/);
+
+ return activeSubInfos.stream().anyMatch(subInfo -> subInfo != null
+ && subInfo.getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING);
+ }
+
+ /**
+ * checks whether esim bootstrap is activated for the subscription.
+ *
+ * @return {@code true} if esim bootstrap is activated for sub id else {@code false}
+ *
+ */
+ public boolean isEsimBootStrapProvisioningActiveForSubId(int subId) {
+ if (!mFeatureFlags.esimBootstrapProvisioningFlag()) {
+ return false;
+ }
+
+ SubscriptionInfoInternal subInfo = getSubscriptionInfoInternal(subId);
+ return subInfo != null
+ && subInfo.getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING;
}
/**
@@ -4527,6 +4728,11 @@
"config_satellite_sim_spn_identifier", "");
}
log("isSatelliteSpn: overlaySpn=" + overlaySpn + ", spn=" + spn);
+
+ if (TextUtils.isEmpty(spn) || TextUtils.isEmpty(overlaySpn)) {
+ return false;
+ }
+
return TextUtils.equals(spn, overlaySpn);
}
@@ -4537,6 +4743,24 @@
}
/**
+ * Iterates through previously subscribed SIMs to excludes subscriptions that are not visible
+ * to the users to provide a more appropriate number to describe the current SIM.
+ * @param subId current subscription id.
+ * @return cardNumber subId excluding invisible subscriptions.
+ */
+ private int getCardNumber(int subId) {
+ int cardNumber = subId; // Initialize with the potential card number
+ for (int i = subId - 1; i > 0; i--) {
+ SubscriptionInfoInternal subInfo = getSubscriptionInfoInternal(i);
+ if (subInfo != null && !subInfo.isVisible()) {
+ cardNumber--;
+ }
+ }
+
+ return cardNumber;
+ }
+
+ /**
* Log debug messages.
*
* @param s debug messages
diff --git a/src/java/com/android/internal/telephony/uicc/PinStorage.java b/src/java/com/android/internal/telephony/uicc/PinStorage.java
index 23769ad..e4a0cfa 100644
--- a/src/java/com/android/internal/telephony/uicc/PinStorage.java
+++ b/src/java/com/android/internal/telephony/uicc/PinStorage.java
@@ -193,9 +193,11 @@
CarrierConfigManager ccm = mContext.getSystemService(CarrierConfigManager.class);
// Callback directly handle config change and should be executed in handler thread
- ccm.registerCarrierConfigChangeListener(this::post,
- (slotIndex, subId, carrierId, specificCarrierId) ->
- onCarrierConfigurationChanged(slotIndex));
+ if (ccm != null) {
+ ccm.registerCarrierConfigChangeListener(this::post,
+ (slotIndex, subId, carrierId, specificCarrierId) ->
+ onCarrierConfigurationChanged(slotIndex));
+ }
// Initialize the long term secret key. This needs to be present in all cases:
// - if the device is not secure or is locked: key does not require user authentication
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 0459bf6..84e84d9 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -1799,6 +1799,8 @@
}
pw.decreaseIndent();
pw.println();
+ mCarrierServiceBindHelper.dump(fd, pw, args);
+ pw.println();
pw.println("sLocalLog= ");
pw.increaseIndent();
mPinStorage.dump(fd, pw, args);
diff --git a/src/java/com/android/internal/telephony/uicc/UiccPort.java b/src/java/com/android/internal/telephony/uicc/UiccPort.java
index fd8f1c4..9e341ef 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccPort.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccPort.java
@@ -31,6 +31,7 @@
import com.android.internal.telephony.TelephonyComponentFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.flags.FeatureFlagsImpl;
+import com.android.internal.telephony.flags.Flags;
import com.android.telephony.Rlog;
import java.io.FileDescriptor;
@@ -57,8 +58,9 @@
private int mPortIdx;
private int mPhysicalSlotIndex;
- // The list of the opened logical channel record. The channels will be closed by us when
- // detecting client died without closing them in advance.
+ // The list of the opened logical channel record.
+ // The channels will be closed by us when detecting client died without closing them in advance.
+ // The same lock should be used to protect both access of the list and the individual record.
@GuardedBy("mOpenChannelRecords")
private final List<OpenLogicalChannelRecord> mOpenChannelRecords = new ArrayList<>();
@@ -101,11 +103,13 @@
}
mUiccProfile = null;
}
+ cleanupOpenLogicalChannelRecordsIfNeeded();
}
@Override
protected void finalize() {
if (DBG) log("UiccPort finalized");
+ cleanupOpenLogicalChannelRecordsIfNeeded();
}
/**
@@ -389,8 +393,10 @@
public void onLogicalChannelOpened(@NonNull IccLogicalChannelRequest request) {
OpenLogicalChannelRecord record = new OpenLogicalChannelRecord(request);
try {
- request.binder.linkToDeath(record, /*flags=*/ 0);
- addOpenLogicalChannelRecord(record);
+ synchronized (mOpenChannelRecords) {
+ request.binder.linkToDeath(record, /*flags=*/ 0);
+ mOpenChannelRecords.add(record);
+ }
if (DBG) log("onLogicalChannelOpened: monitoring client " + record);
} catch (RemoteException | NullPointerException ex) {
loge("IccOpenLogicChannel client has died, clean up manually");
@@ -406,11 +412,13 @@
*/
public void onLogicalChannelClosed(int channelId) {
OpenLogicalChannelRecord record = getOpenLogicalChannelRecord(channelId);
- if (record != null && record.mRequest != null && record.mRequest.binder != null) {
- if (DBG) log("onLogicalChannelClosed: stop monitoring client " + record);
- record.mRequest.binder.unlinkToDeath(record, /*flags=*/ 0);
- removeOpenLogicalChannelRecord(record);
- record.mRequest.binder = null;
+ synchronized (mOpenChannelRecords) {
+ if (record != null && record.mRequest != null && record.mRequest.binder != null) {
+ if (DBG) log("onLogicalChannelClosed: stop monitoring client " + record);
+ record.mRequest.binder.unlinkToDeath(record, /*flags=*/ 0);
+ record.mRequest.binder = null;
+ mOpenChannelRecords.remove(record);
+ }
}
}
@@ -428,15 +436,21 @@
return null;
}
- private void addOpenLogicalChannelRecord(OpenLogicalChannelRecord record) {
- synchronized (mOpenChannelRecords) {
- mOpenChannelRecords.add(record);
- }
- }
-
- private void removeOpenLogicalChannelRecord(OpenLogicalChannelRecord record) {
- synchronized (mOpenChannelRecords) {
- mOpenChannelRecords.remove(record);
+ /**
+ * Clean up records when logical channels underneath have been released, in cases like SIM
+ * removal or modem reset. The obsoleted records may trigger a redundant release of logical
+ * channel that may have been assigned to other client.
+ */
+ private void cleanupOpenLogicalChannelRecordsIfNeeded() {
+ if (Flags.cleanupOpenLogicalChannelRecordOnDispose()) {
+ synchronized (mOpenChannelRecords) {
+ for (OpenLogicalChannelRecord record : mOpenChannelRecords) {
+ if (DBG) log("Clean up " + record);
+ record.mRequest.binder.unlinkToDeath(record, /*flags=*/ 0);
+ record.mRequest.binder = null;
+ }
+ mOpenChannelRecords.clear();
+ }
}
}
diff --git a/src/java/com/android/internal/telephony/uicc/UiccProfile.java b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
index 0457971..a22f075 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccProfile.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccProfile.java
@@ -1290,6 +1290,11 @@
return -1;
}
+ if (mUiccApplications[index] == null) {
+ loge("App index " + index + " is invalid");
+ return -1;
+ }
+
if (mUiccApplications[index].getType() != expectedAppType
&& mUiccApplications[index].getType() != altExpectedAppType) {
loge("App index " + index + " is invalid since it's not "
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/EuiccPort.java b/src/java/com/android/internal/telephony/uicc/euicc/EuiccPort.java
index 3bd66f8..7bdec47 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/EuiccPort.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/EuiccPort.java
@@ -133,7 +133,8 @@
UiccCard card, MultipleEnabledProfilesMode supportedMepMode) {
super(c, ci, ics, phoneId, lock, card);
// TODO: Set supportExtendedApdu based on ATR.
- mApduSender = new ApduSender(ci, ISD_R_AID, false /* supportExtendedApdu */);
+ mApduSender = new ApduSender(c, phoneId, ci, ISD_R_AID,
+ false /* supportExtendedApdu */);
if (TextUtils.isEmpty(ics.eid)) {
loge("no eid given in constructor for phone " + phoneId);
} else {
diff --git a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
index 8e7237e..f42d5a2 100644
--- a/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
+++ b/src/java/com/android/internal/telephony/uicc/euicc/apdu/ApduSender.java
@@ -17,9 +17,13 @@
package com.android.internal.telephony.uicc.euicc.apdu;
import android.annotation.Nullable;
+import android.content.Context;
+import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
+import android.preference.PreferenceManager;
import android.telephony.IccOpenLogicalChannelResponse;
+import android.util.Base64;
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.uicc.IccIoResult;
@@ -30,6 +34,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
+import java.util.NoSuchElementException;
/**
* This class sends a list of APDU commands to an AID on a UICC. A logical channel will be opened
@@ -52,6 +57,9 @@
private static final int SW1_NO_ERROR = 0x91;
private static final int WAIT_TIME_MS = 2000;
+ private static final String CHANNEL_ID_PRE = "esim-channel";
+ private static final String ISD_R_AID = "A0000005591010FFFFFFFF8900000100";
+ private static final String CHANNEL_RESPONSE_ID_PRE = "esim-res-id";
private static void logv(String msg) {
Rlog.v(LOG_TAG, msg);
@@ -66,6 +74,9 @@
private final OpenLogicalChannelInvocation mOpenChannel;
private final CloseLogicalChannelInvocation mCloseChannel;
private final TransmitApduLogicalChannelInvocation mTransmitApdu;
+ private final Context mContext;
+ private final String mChannelKey;
+ private final String mChannelResponseKey;
// Lock for accessing mChannelOpened. We only allow to open a single logical channel at any
// time for an AID.
@@ -75,12 +86,17 @@
/**
* @param aid The AID that will be used to open a logical channel to.
*/
- public ApduSender(CommandsInterface ci, String aid, boolean supportExtendedApdu) {
+ public ApduSender(Context context, int phoneId, CommandsInterface ci, String aid,
+ boolean supportExtendedApdu) {
mAid = aid;
+ mContext = context;
mSupportExtendedApdu = supportExtendedApdu;
mOpenChannel = new OpenLogicalChannelInvocation(ci);
mCloseChannel = new CloseLogicalChannelInvocation(ci);
mTransmitApdu = new TransmitApduLogicalChannelInvocation(ci);
+ mChannelKey = CHANNEL_ID_PRE + "_" + phoneId;
+ mChannelResponseKey = CHANNEL_RESPONSE_ID_PRE + "_" + phoneId;
+ closeExistingChannelIfExists();
}
/**
@@ -129,6 +145,20 @@
public void onResult(IccOpenLogicalChannelResponse openChannelResponse) {
int channel = openChannelResponse.getChannel();
int status = openChannelResponse.getStatus();
+ byte[] selectResponse = openChannelResponse.getSelectResponse();
+ if (mAid.equals(ISD_R_AID)
+ && status == IccOpenLogicalChannelResponse.STATUS_NO_SUCH_ELEMENT) {
+ channel = PreferenceManager.getDefaultSharedPreferences(mContext)
+ .getInt(mChannelKey, IccOpenLogicalChannelResponse.INVALID_CHANNEL);
+ if (channel != IccOpenLogicalChannelResponse.INVALID_CHANNEL) {
+ logv("Try to use already opened channel: " + channel);
+ status = IccOpenLogicalChannelResponse.STATUS_NO_ERROR;
+ String storedResponse = PreferenceManager
+ .getDefaultSharedPreferences(mContext)
+ .getString(mChannelResponseKey, "");
+ selectResponse = Base64.decode(storedResponse, Base64.DEFAULT);
+ }
+ }
if (channel == IccOpenLogicalChannelResponse.INVALID_CHANNEL
|| status != IccOpenLogicalChannelResponse.STATUS_NO_ERROR) {
synchronized (mChannelLock) {
@@ -143,8 +173,15 @@
RequestBuilder builder = new RequestBuilder(channel, mSupportExtendedApdu);
Throwable requestException = null;
+ if (mAid.equals(ISD_R_AID)) {
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().putInt(mChannelKey, channel).apply();
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().putString(mChannelResponseKey,
+ Base64.encodeToString(selectResponse, Base64.DEFAULT)).apply();
+ }
try {
- requestProvider.buildRequest(openChannelResponse.getSelectResponse(), builder);
+ requestProvider.buildRequest(selectResponse, builder);
} catch (Throwable e) {
requestException = e;
}
@@ -223,7 +260,7 @@
AsyncResultCallback<IccIoResult> resultCallback,
Handler handler) {
ByteArrayOutputStream resultBuilder =
- responseBuilder == null ? new ByteArrayOutputStream() : responseBuilder;
+ responseBuilder == null ? new ByteArrayOutputStream() : responseBuilder;
if (lastResponse.payload != null) {
try {
resultBuilder.write(lastResponse.payload);
@@ -267,6 +304,12 @@
@Override
public void onResult(Boolean aBoolean) {
synchronized (mChannelLock) {
+ if (mAid.equals(ISD_R_AID)) {
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().remove(mChannelKey).apply();
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().remove(mChannelResponseKey).apply();
+ }
mChannelOpened = false;
mChannelLock.notify();
}
@@ -279,4 +322,39 @@
}
}, handler);
}
+
+ /**
+ * Cleanup the existing opened channel which was remainined opened earlier due
+ * to failure or crash.
+ */
+ private void closeExistingChannelIfExists() {
+ if (mCloseChannel != null) {
+ int channelId = PreferenceManager.getDefaultSharedPreferences(mContext)
+ .getInt(mChannelKey, IccOpenLogicalChannelResponse.INVALID_CHANNEL);
+ if (channelId != IccOpenLogicalChannelResponse.INVALID_CHANNEL) {
+ logv("Trying to clean up the opened channel : " + channelId);
+ synchronized (mChannelLock) {
+ mChannelOpened = true;
+ mChannelLock.notify();
+ }
+ mCloseChannel.invoke(channelId, new AsyncResultCallback<Boolean>() {
+ @Override
+ public void onResult(Boolean isSuccess) {
+ if (isSuccess) {
+ logv("Channel closed successfully: " + channelId);
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().remove(mChannelResponseKey).apply();
+ PreferenceManager.getDefaultSharedPreferences(mContext)
+ .edit().remove(mChannelKey).apply();
+ }
+
+ synchronized (mChannelLock) {
+ mChannelOpened = false;
+ mChannelLock.notify();
+ }
+ }
+ }, new Handler());
+ }
+ }
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
index 2a66a5f..e06e4fe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierAppUtilsTest.java
@@ -23,6 +23,7 @@
import android.os.Bundle;
import android.os.CarrierAssociatedAppEntry;
import android.os.UserHandle;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.test.mock.MockContentProvider;
@@ -34,9 +35,12 @@
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.telephony.flags.Flags;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
@@ -59,6 +63,9 @@
private static final int USER_ID = 12345;
private static final String CALLING_PACKAGE = "phone";
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
// Mocked classes
private Context mContext;
private PackageManager mPackageManager;
@@ -79,6 +86,7 @@
@Before
public void setUp() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_HIDE_PREINSTALLED_CARRIER_APP_AT_MOST_ONCE);
System.setProperty("dexmaker.dexcache",
InstrumentationRegistry.getTargetContext().getCacheDir().getPath());
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
@@ -113,6 +121,7 @@
public void testDisableCarrierAppsUntilPrivileged_EmptyList() {
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, new ArraySet<>(), ASSOCIATED_APPS, mContext);
+
Mockito.verifyNoMoreInteractions(mPackageManager, mTelephonyManager);
}
@@ -125,9 +134,11 @@
| PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(null);
ArraySet<String> systemCarrierAppsDisabledUntilUsed = new ArraySet<>();
systemCarrierAppsDisabledUntilUsed.add("com.example.missing.app");
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, systemCarrierAppsDisabledUntilUsed, ASSOCIATED_APPS,
mContext);
+
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
Mockito.eq(PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN));
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -147,8 +158,10 @@
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS))
.thenReturn(appInfo);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
Mockito.eq(PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN));
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -173,15 +186,16 @@
Mockito.when(mPackageManager
.getApplicationEnabledSetting(Mockito.anyString()))
.thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER);
-
Mockito.when(mPackageManager.getApplicationInfo(CARRIER_APP,
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
| PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(appInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -199,15 +213,16 @@
Mockito.when(mPackageManager
.getApplicationEnabledSetting(Mockito.anyString()))
.thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DISABLED);
-
Mockito.when(mPackageManager.getApplicationInfo(CARRIER_APP,
PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
| PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(appInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -231,8 +246,10 @@
| PackageManager.MATCH_SYSTEM_ONLY)).thenReturn(appInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -255,11 +272,12 @@
Mockito.when(mPackageManager
.getApplicationEnabledSetting(Mockito.anyString()))
.thenReturn(PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
-
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -287,8 +305,10 @@
.thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
@@ -329,8 +349,10 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
@@ -371,8 +393,10 @@
.thenReturn(null);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(ASSOCIATED_APP,
@@ -412,8 +436,10 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
@@ -440,8 +466,10 @@
.thenReturn(appInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -465,9 +493,11 @@
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
| PackageManager.MATCH_SYSTEM_ONLY))
.thenReturn(appInfo);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE,
null /* telephonyManager */, mContentResolver, USER_ID, CARRIER_APPS,
ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -476,7 +506,7 @@
Mockito.eq(PackageManager.SYSTEM_APP_STATE_UNINSTALLED));
}
- /** Configured app has no privileges, and was uninstalled - should do nothing. */
+ /** Configured app has no privileges, and was explicitly disabled - should do nothing. */
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NoPrivileges_Disabled() throws Exception {
ApplicationInfo appInfo = new ApplicationInfo();
@@ -492,8 +522,10 @@
.thenReturn(appInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -502,7 +534,7 @@
Mockito.eq(PackageManager.SYSTEM_APP_STATE_UNINSTALLED));
}
- /** Telephony is not initialized, and app was uninstalled - should do nothing. */
+ /** Telephony is not initialized, and app was explicitly disabled - should do nothing. */
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NullPrivileges_Disabled() throws Exception {
ApplicationInfo appInfo = new ApplicationInfo();
@@ -516,9 +548,11 @@
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
| PackageManager.MATCH_SYSTEM_ONLY))
.thenReturn(appInfo);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE,
null /* telephonyManager */, mContentResolver, USER_ID, CARRIER_APPS,
ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -527,7 +561,7 @@
Mockito.eq(PackageManager.SYSTEM_APP_STATE_UNINSTALLED));
}
- /** Configured app has no privileges, and is explicitly installed - should do nothing. */
+ /** Configured app has no privileges, and was explicitly enabled - should do nothing. */
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NoPrivileges_Enabled() throws Exception {
ApplicationInfo appInfo = new ApplicationInfo();
@@ -543,8 +577,10 @@
.thenReturn(appInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -553,7 +589,7 @@
Mockito.eq(PackageManager.SYSTEM_APP_STATE_UNINSTALLED));
}
- /** Telephony is not initialized, and app is explicitly installed - should do nothing. */
+ /** Telephony is not initialized, and app was explicitly enabled - should do nothing. */
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NullPrivileges_Enabled() throws Exception {
ApplicationInfo appInfo = new ApplicationInfo();
@@ -567,9 +603,11 @@
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
| PackageManager.MATCH_SYSTEM_ONLY))
.thenReturn(appInfo);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE,
null /* telephonyManager */, mContentResolver, USER_ID, CARRIER_APPS,
ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -578,7 +616,8 @@
Mockito.eq(PackageManager.SYSTEM_APP_STATE_UNINSTALLED));
}
- /** Configured /data app has no privileges - should do nothing. */
+ /** Configured app has been installed as an update in /data and has no privileges
+ * - should do nothing. */
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NoPrivileges_UpdatedApp() throws Exception {
ApplicationInfo appInfo = new ApplicationInfo();
@@ -595,8 +634,10 @@
.thenReturn(appInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -620,9 +661,11 @@
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
| PackageManager.MATCH_SYSTEM_ONLY))
.thenReturn(appInfo);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE,
null /* telephonyManager */, mContentResolver, USER_ID, CARRIER_APPS,
ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -632,7 +675,8 @@
}
/**
- * Configured app has no privileges, and is in the default state - should uninstalled.
+ * Configured app has no privileges, is in the default state and it was never uninstalled before
+ * - should uninstalled.
* Associated app is installed and should not be touched.
*/
@Test @SmallTest
@@ -660,8 +704,10 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
@@ -675,8 +721,8 @@
}
/**
- * Configured app has no privileges, and is in the default state along with associated app -
- * should uninstall both.
+ * Configured app has no privileges, is in the default state along with associated app and never
+ * unstalled before - should uninstall both.
*/
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NoPrivileges_Associated_Default()
@@ -703,8 +749,10 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
@@ -717,7 +765,7 @@
/**
* Configured app has no privileges, and is in the default state along with associated app, and
- * disabling has already occurred - should only uninstall configured app.
+ * disabling has already occurred - should uninstall nothing.
*/
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NoPrivileges_Associated_Default_HandledSdk()
@@ -747,15 +795,17 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
// Different associated app SDK than usual.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS,
makeAssociatedApp(CARRIER_APP, ASSOCIATED_APP, Build.VERSION.SDK_INT), mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
- Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
+ Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_INSTALLED);
@@ -765,7 +815,7 @@
/**
* Configured app has no privileges, and is in the default state along with associated app, and
- * disabling has already occurred - should only uninstall configured app.
+ * disabling has already occurred - should uninstall nothing.
*/
@Test @SmallTest
public void testDCAUP_NoPrivileges_Associated_Default_HandledSdk_AssociatedSdkUnspecified()
@@ -795,14 +845,16 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
// Using SDK_UNSPECIFIED for the associated app's addedInSdk.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
- Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
+ Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_INSTALLED);
@@ -812,15 +864,14 @@
/**
* Configured app has no privileges, and is in the default state along with associated app, and
- * disabling has not yet occurred on this SDK level - should uninstall both since the associated
- * app's SDK matches.
+ * disabling has not yet occurred on any SDK level - should uninstall both since disabling never
+ * occurred before and the associated app's SDK matches.
*/
@Test @SmallTest
public void testDCAUP_NoPrivileges_Associated_Default_NewSdk_AssociatedSdkCurrent()
throws Exception {
Settings.Secure.putIntForUser(
- mContentResolver, Settings.Secure.CARRIER_APPS_HANDLED,
- Build.VERSION.SDK_INT - 1, USER_ID);
+ mContentResolver, Settings.Secure.CARRIER_APPS_HANDLED, 0, USER_ID);
ApplicationInfo appInfo = new ApplicationInfo();
appInfo.packageName = CARRIER_APP;
appInfo.flags |= ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_INSTALLED;
@@ -843,10 +894,12 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
// Different associated app SDK than usual.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS,
makeAssociatedApp(CARRIER_APP, ASSOCIATED_APP, Build.VERSION.SDK_INT), mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
@@ -861,7 +914,7 @@
/**
* Configured app has no privileges, and is in the default state along with associated app, and
- * disabling has not yet occurred on the current SDK - should only uninstall configured app
+ * disabling has not yet occurred on the current SDK - should uninstall nothing
* since the associated app's SDK isn't specified but we've already run at least once.
*/
@Test @SmallTest
@@ -892,14 +945,16 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
// Using SDK_UNSPECIFIED for the associated app's addedInSdk.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
- Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
+ Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_INSTALLED);
@@ -909,7 +964,7 @@
/**
* Configured app has no privileges, and is in the default state along with associated app, and
- * disabling has not yet occurred on the current SDK - should only uninstall configured app
+ * disabling has not yet occurred on the current SDK - should uninstall nothing
* since the associated app's SDK doesn't match.
*/
@Test @SmallTest
@@ -940,16 +995,18 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
// Different associated app SDK than usual.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS,
makeAssociatedApp(CARRIER_APP, ASSOCIATED_APP, Build.VERSION.SDK_INT - 1),
mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
- Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
+ Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_INSTALLED);
@@ -959,8 +1016,8 @@
/**
* Configured app has no privileges, and is in the default state along with associated app, and
- * disabling has not yet occurred on this SDK level - should uninstall both since the associated
- * app's SDK is newer than the last evaluation.
+ * disabling has not yet occurred on this SDK level - should uninstall only associated
+ * app since the associated app's SDK is newer than the last evaluation.
*
* While this case is expected to feel somewhat strange, it effectively simulates skipping a
* whole SDK level in a single OTA. For example, the device is on P. A new associated app is
@@ -996,16 +1053,18 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
// Different associated app SDK than usual.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS,
makeAssociatedApp(CARRIER_APP, ASSOCIATED_APP, Build.VERSION.SDK_INT - 1),
mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
- Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
+ Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(ASSOCIATED_APP,
PackageManager.SYSTEM_APP_STATE_INSTALLED);
@@ -1043,10 +1102,12 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
// Different associated app SDK than usual.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS,
makeAssociatedApp(CARRIER_APP, ASSOCIATED_APP, Build.VERSION.SDK_INT), mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
@@ -1089,9 +1150,11 @@
.thenReturn(associatedAppInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
// Using SDK_UNSPECIFIED for the associated app's addedInSdk.
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(ASSOCIATED_APP,
@@ -1104,7 +1167,10 @@
PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
}
- /** Telephony is not initialized, and app is in the default state - should uninstall it. */
+ /**
+ * Telephony is not initialized, and app is in the default state and never uninstall before
+ * - should uninstall it.
+ **/
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NullPrivileges_Default() throws Exception {
ApplicationInfo appInfo = new ApplicationInfo();
@@ -1118,16 +1184,51 @@
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
| PackageManager.MATCH_SYSTEM_ONLY))
.thenReturn(appInfo);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE,
null /* telephonyManager */, mContentResolver, USER_ID, CARRIER_APPS,
ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
}
- /** Configured app has no privileges, and is disabled until used or not installed - should do
+ /**
+ * Telephony is not initialized, and app is in the default state but uninstall before
+ * - should not uninstall again.
+ **/
+ @Test @SmallTest
+ public void testDisableCarrierAppsUntilPrivileged_NullPrivileges_Default_alreadyUninstalled()
+ throws Exception {
+ Settings.Secure.putIntForUser(
+ mContentResolver, Settings.Secure.CARRIER_APPS_HANDLED,
+ Build.VERSION.SDK_INT, USER_ID);
+ ApplicationInfo appInfo = new ApplicationInfo();
+ appInfo.packageName = CARRIER_APP;
+ appInfo.flags |= ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_INSTALLED;
+ Mockito.when(mPackageManager
+ .getApplicationEnabledSetting(Mockito.anyString()))
+ .thenReturn(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);
+ Mockito.when(mPackageManager.getApplicationInfo(CARRIER_APP,
+ PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS
+ | PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
+ | PackageManager.MATCH_SYSTEM_ONLY))
+ .thenReturn(appInfo);
+
+ CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE,
+ null /* telephonyManager */, mContentResolver, USER_ID, CARRIER_APPS,
+ ASSOCIATED_APPS, mContext);
+
+ Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
+ PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
+ Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(CARRIER_APP,
+ PackageManager.SYSTEM_APP_STATE_UNINSTALLED);
+ }
+
+ /**
+ * Configured app has no privileges, and is disabled until used or not installed - should do
* nothing.
**/
@Test @SmallTest
@@ -1146,8 +1247,10 @@
.thenReturn(appInfo);
Mockito.when(mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(CARRIER_APP))
.thenReturn(TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE, mTelephonyManager,
mContentResolver, USER_ID, CARRIER_APPS, ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
@@ -1156,8 +1259,9 @@
Mockito.eq(PackageManager.SYSTEM_APP_STATE_UNINSTALLED));
}
- /** Telephony is not initialized, and app is disabled until used or not installed - should do
- * nothing.
+ /**
+ * Telephony is not initialized, and app is disabled until used or not installed - should do
+ * nothing.
**/
@Test @SmallTest
public void testDisableCarrierAppsUntilPrivileged_NullPrivileges_DisabledUntilUsed()
@@ -1173,9 +1277,11 @@
| PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS
| PackageManager.MATCH_SYSTEM_ONLY))
.thenReturn(appInfo);
+
CarrierAppUtils.disableCarrierAppsUntilPrivileged(CALLING_PACKAGE,
null /* telephonyManager */, mContentResolver, USER_ID, CARRIER_APPS,
ASSOCIATED_APPS, mContext);
+
Mockito.verify(mPackageManager).setSystemAppState(CARRIER_APP,
PackageManager.SYSTEM_APP_STATE_HIDDEN_UNTIL_INSTALLED_HIDDEN);
Mockito.verify(mPackageManager, Mockito.never()).setSystemAppState(Mockito.anyString(),
diff --git a/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java b/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java
index 07482e0..e60e95b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/CarrierKeyDownloadMgrTest.java
@@ -22,6 +22,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.times;
@@ -31,6 +32,8 @@
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityManager;
+import android.net.Network;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.ImsiEncryptionInfo;
@@ -38,18 +41,18 @@
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.text.TextUtils;
import android.util.Pair;
import androidx.test.filters.SmallTest;
-import com.android.internal.telephony.flags.FeatureFlags;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatchers;
+import org.mockito.Mock;
import org.mockito.Mockito;
import java.security.PublicKey;
@@ -91,7 +94,7 @@
+ "\"public-key\": \"" + CERT + "\"}]}";
private CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener;
- private FeatureFlags mFeatureFlags;
+
@Before
public void setUp() throws Exception {
logd("CarrierActionAgentTest +Setup!");
@@ -99,15 +102,18 @@
mBundle = mContextFixture.getCarrierConfigBundle();
when(mCarrierConfigManager.getConfigForSubId(anyInt(), any())).thenReturn(mBundle);
when(mUserManager.isUserUnlocked()).thenReturn(true);
+ when(mKeyguardManager.isDeviceLocked()).thenReturn(false);
// Capture listener to emulate the carrier config change notification used later
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
- mFeatureFlags = Mockito.mock(FeatureFlags.class);
- mCarrierKeyDM = new CarrierKeyDownloadManager(mPhone, mFeatureFlags);
+ mCarrierKeyDM = new CarrierKeyDownloadManager(mPhone);
verify(mCarrierConfigManager).registerCarrierConfigChangeListener(any(),
listenerArgumentCaptor.capture());
mCarrierConfigChangeListener = listenerArgumentCaptor.getAllValues().get(0);
-
+ mConnectivityManager = (ConnectivityManager) mPhone.getContext().getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ Network network = Mockito.mock(Network.class);
+ when(mConnectivityManager.getActiveNetwork()).thenReturn(network);
processAllMessages();
logd("CarrierActionAgentTest -Setup!");
}
@@ -331,8 +337,8 @@
expectedCal.add(Calendar.DATE, 1);
String dateExpected = dt.format(expectedCal.getTime());
- when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
- when(mTelephonyManager.getSimCarrierId()).thenReturn(1);
+ when(mPhone.getOperatorNumeric()).thenReturn("310260");
+ when(mPhone.getCarrierId()).thenReturn(1);
Intent mIntent = new Intent(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
mIntent.putExtra(DownloadManager.EXTRA_DOWNLOAD_ID, downloadId);
mContext.sendBroadcast(mIntent);
@@ -355,11 +361,11 @@
bundle.putInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, 3);
bundle.putString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, mURL);
- when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
- when(mTelephonyManager.getSimCarrierId()).thenReturn(1);
+ when(mPhone.getOperatorNumeric()).thenReturn("310260");
+ when(mPhone.getCarrierId()).thenReturn(1);
mCarrierConfigChangeListener.onCarrierConfigChanged(0 /* slotIndex */,
SubscriptionManager.INVALID_SUBSCRIPTION_ID,
- TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
+ 1, TelephonyManager.UNKNOWN_CARRIER_ID);
processAllMessages();
assertEquals("310260", mCarrierKeyDM.mMccMncForDownload);
assertEquals(1, mCarrierKeyDM.mCarrierId);
@@ -369,6 +375,7 @@
@SmallTest
public void testCarrierConfigChangedWithUserLocked() {
when(mUserManager.isUserUnlocked()).thenReturn(false);
+ when(mKeyguardManager.isDeviceLocked()).thenReturn(true);
CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
int slotId = mPhone.getPhoneId();
@@ -376,14 +383,14 @@
bundle.putInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, 3);
bundle.putString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, mURL);
- when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
- when(mTelephonyManager.getSimCarrierId()).thenReturn(1);
+ when(mPhone.getOperatorNumeric()).thenReturn("310260");
+ when(mPhone.getCarrierId()).thenReturn(1);
mCarrierConfigChangeListener.onCarrierConfigChanged(0 /* slotIndex */,
SubscriptionManager.INVALID_SUBSCRIPTION_ID,
- TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
+ 1, TelephonyManager.UNKNOWN_CARRIER_ID);
processAllMessages();
- assertNull(mCarrierKeyDM.mMccMncForDownload);
- assertEquals(0, mCarrierKeyDM.mCarrierId);
+ assertEquals("310260", mCarrierKeyDM.mMccMncForDownload);
+ assertEquals(1, mCarrierKeyDM.mCarrierId);
}
@Test
@@ -391,6 +398,7 @@
public void testUserLockedAfterCarrierConfigChanged() {
// User is locked at beginning
when(mUserManager.isUserUnlocked()).thenReturn(false);
+ when(mKeyguardManager.isDeviceLocked()).thenReturn(true);
CarrierConfigManager carrierConfigManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
int slotId = mPhone.getPhoneId();
@@ -399,17 +407,18 @@
bundle.putString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, mURL);
// Carrier config change received
- when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
- when(mTelephonyManager.getSimCarrierId()).thenReturn(1);
+ when(mPhone.getOperatorNumeric()).thenReturn("310260");
+ when(mPhone.getCarrierId()).thenReturn(1);
mCarrierConfigChangeListener.onCarrierConfigChanged(0 /* slotIndex */,
SubscriptionManager.INVALID_SUBSCRIPTION_ID,
- TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
+ 1, TelephonyManager.UNKNOWN_CARRIER_ID);
processAllMessages();
// User unlocked event received
- Intent mIntent = new Intent(Intent.ACTION_USER_UNLOCKED);
+ Intent mIntent = new Intent(Intent.ACTION_USER_PRESENT);
mContext.sendBroadcast(mIntent);
when(mUserManager.isUserUnlocked()).thenReturn(true);
+ when(mKeyguardManager.isDeviceLocked()).thenReturn(false);
processAllMessages();
assertEquals("310260", mCarrierKeyDM.mMccMncForDownload);
@@ -432,11 +441,11 @@
mCarrierConfigChangeListener.onCarrierConfigChanged(0 /* slotIndex */,
SubscriptionManager.INVALID_SUBSCRIPTION_ID,
- TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
+ 1, TelephonyManager.UNKNOWN_CARRIER_ID);
processAllMessages();
- assertNull(mCarrierKeyDM.mMccMncForDownload);
+ assertTrue(TextUtils.isEmpty(mCarrierKeyDM.mMccMncForDownload));
- verify(mPhone).deleteCarrierInfoForImsiEncryption(0);
+ verify(mPhone).deleteCarrierInfoForImsiEncryption(1, "");
}
/**
@@ -453,8 +462,8 @@
bundle.putInt(CarrierConfigManager.IMSI_KEY_AVAILABILITY_INT, 3);
bundle.putString(CarrierConfigManager.IMSI_KEY_DOWNLOAD_URL_STRING, mURL);
- when(mTelephonyManager.getSimOperator(anyInt())).thenReturn("310260");
- when(mTelephonyManager.getSimCarrierId()).thenReturn(1);
+ when(mPhone.getOperatorNumeric()).thenReturn("310260");
+ when(mPhone.getCarrierId()).thenReturn(1);
Intent mIntent = new Intent("com.android.internal.telephony.carrier_key_download_alarm");
mIntent.putExtra(SubscriptionManager.EXTRA_SLOT_INDEX, slotIndex);
mContext.sendBroadcast(mIntent);
@@ -493,4 +502,4 @@
assertEquals(CarrierKeyDownloadManager
.cleanCertString("Comments before" + CERT + "Comments after"), CERT);
}
-}
+}
\ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
index 0bce5cb..329b0b8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ConnectionTest.java
@@ -18,6 +18,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -25,9 +26,14 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import java.util.ArrayList;
+
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
+import android.telephony.emergency.EmergencyNumber;
+import com.android.internal.telephony.PhoneInternalInterface.DialArgs;
import com.android.internal.telephony.emergency.EmergencyNumberTracker;
import org.junit.After;
@@ -150,7 +156,7 @@
assertNull(connection1.getEmergencyNumberInfo());
assertFalse(connection1.hasKnownUserIntentEmergency());
- connection2.setEmergencyCallInfo(mPhone.getCallTracker());
+ connection2.setEmergencyCallInfo(mPhone.getCallTracker(), null);
connection2.setHasKnownUserIntentEmergency(true);
connection1.migrateFrom(connection2);
@@ -164,7 +170,7 @@
@Test
public void testEmergencyCallParameters() {
Connection connection = new TestConnection(TEST_PHONE_TYPE);
- connection.setEmergencyCallInfo(mPhone.getCallTracker());
+ connection.setEmergencyCallInfo(mPhone.getCallTracker(), null);
assertTrue(connection.isEmergencyCall());
assertEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
connection.setHasKnownUserIntentEmergency(true);
@@ -186,9 +192,44 @@
.thenReturn(getTestEmergencyNumber());
//Ensure the connection is considered as an emergency call:
- mTestConnection.setEmergencyCallInfo(mCT);
+ mTestConnection.setEmergencyCallInfo(mCT, null);
assertTrue(mTestConnection.isEmergencyCall());
}
+ @Test
+ public void testUpdateEmergencyRouting() {
+ DialArgs dialArgs = new DialArgs.Builder().build();
+ Connection connection = new TestConnection(TEST_PHONE_TYPE);
+ connection.setEmergencyCallInfo(mPhone.getCallTracker(), dialArgs);
+
+ // Not updated when DomainSelectionService is disabled.
+ assertEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+
+ // Enable DomainSelectionService
+ doReturn(true).when(mDomainSelectionResolver).isDomainSelectionSupported();
+ connection = new TestConnection(TEST_PHONE_TYPE);
+ connection.setEmergencyCallInfo(mPhone.getCallTracker(), dialArgs);
+
+ // Not updated when IS_EMERGENCY_ROUTING is not specified.
+ assertEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+
+ Bundle extras = new Bundle();
+ extras.putBoolean(PhoneConstants.EXTRA_USE_EMERGENCY_ROUTING, true);
+ extras.putInt(PhoneConstants.EXTRA_EMERGENCY_SERVICE_CATEGORY,
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE);
+ dialArgs = new DialArgs.Builder().setIntentExtras(extras).build();
+
+ connection = new TestConnection(TEST_PHONE_TYPE);
+ connection.setEmergencyCallInfo(mPhone.getCallTracker(), dialArgs);
+ EmergencyNumber expectedNumber = new EmergencyNumber("911", "us", "30",
+ EmergencyNumber.EMERGENCY_SERVICE_CATEGORY_POLICE,
+ new ArrayList<String>(), EmergencyNumber.EMERGENCY_NUMBER_SOURCE_NETWORK_SIGNALING,
+ EmergencyNumber.EMERGENCY_CALL_ROUTING_EMERGENCY);
+
+ // Updated when DomainSelectionService is enabled.
+ assertNotEquals(getTestEmergencyNumber(), connection.getEmergencyNumberInfo());
+ assertEquals(expectedNumber, connection.getEmergencyNumberInfo());
+ }
+
// TODO Verify more methods in Connection
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
index bef8944..4612ad9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ContextFixture.java
@@ -65,6 +65,7 @@
import android.net.wifi.WifiManager;
import android.os.BatteryManager;
import android.os.Bundle;
+import android.os.DropBoxManager;
import android.os.Handler;
import android.os.IInterface;
import android.os.PersistableBundle;
@@ -313,6 +314,8 @@
return mImsManager;
case Context.DEVICE_POLICY_SERVICE:
return mDevicePolicyManager;
+ case Context.DROPBOX_SERVICE:
+ return mDropBoxManager;
default:
return null;
}
@@ -362,6 +365,10 @@
return Context.ALARM_SERVICE;
} else if (serviceClass == DevicePolicyManager.class) {
return Context.DEVICE_POLICY_SERVICE;
+ } else if (serviceClass == NotificationManager.class) {
+ return Context.NOTIFICATION_SERVICE;
+ } else if (serviceClass == DropBoxManager.class) {
+ return Context.DROPBOX_SERVICE;
}
return super.getSystemServiceName(serviceClass);
}
@@ -737,6 +744,7 @@
private final NetworkPolicyManager mNetworkPolicyManager = mock(NetworkPolicyManager.class);
private final ImsManager mImsManager = mock(ImsManager.class);
private final DevicePolicyManager mDevicePolicyManager = mock(DevicePolicyManager.class);
+ private final DropBoxManager mDropBoxManager = mock(DropBoxManager.class);
private final Configuration mConfiguration = new Configuration();
private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
private final SharedPreferences mSharedPreferences = PreferenceManager
diff --git a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
index d27ab98..8209f92 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/DefaultPhoneNotifierTest.java
@@ -392,4 +392,13 @@
verify(mTelephonyRegistryManager).notifySimultaneousCellularCallingSubscriptionsChanged(
eq(subs));
}
+
+ @Test
+ @SmallTest
+ public void testCarrierRoamingNtnModeChanged() {
+ int subId = mPhone.getSubId();
+ mDefaultPhoneNotifierUT.notifyCarrierRoamingNtnModeChanged(mPhone, true);
+ verify(mTelephonyRegistryManager).notifyCarrierRoamingNtnModeChanged(
+ eq(subId), eq(true));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 9f96ce4..ba08f8b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -2712,6 +2712,9 @@
doReturn(true).when(dsResolver).isDomainSelectionSupported();
DomainSelectionResolver.setDomainSelectionResolver(dsResolver);
+ EmergencyStateTracker est = Mockito.mock(EmergencyStateTracker.class);
+ replaceInstance(EmergencyStateTracker.class, "INSTANCE", null, est);
+
mPhoneUT.handleMessage(mPhoneUT.obtainMessage(
GsmCdmaPhone.EVENT_EMERGENCY_CALLBACK_MODE_ENTER));
@@ -2721,7 +2724,8 @@
mPhoneUT.exitEmergencyCallbackMode();
processAllMessages();
- verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
+ // Verify that the request is routed to EmergencyStateTracker.
+ verify(est).exitEmergencyCallbackMode();
}
@Test
@@ -3015,7 +3019,63 @@
processAllMessages();
verify(mNullCipherNotifier, times(1))
- .onSecurityAlgorithmUpdate(eq(mContext), eq(0), eq(update));
+ .onSecurityAlgorithmUpdate(eq(mContext), eq(0), eq(0), eq(update));
+ }
+
+ @Test
+ public void testUpdateNullCipherNotifier_flagDisabled() {
+ when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(false);
+ Phone phoneUT = makeNewPhoneUT();
+ phoneUT.sendMessage(
+ mPhoneUT.obtainMessage(
+ Phone.EVENT_SUBSCRIPTIONS_CHANGED,
+ new AsyncResult(null, null, null)));
+ processAllMessages();
+
+ verify(mNullCipherNotifier, never()).setSubscriptionMapping(any(), anyInt(), anyInt());
+ }
+
+ @Test
+ public void testUpdateNullCipherNotifier_activeSubscription() {
+ when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
+
+ int subId = 10;
+ SubscriptionInfoInternal subInfo = new SubscriptionInfoInternal.Builder().setSimSlotIndex(
+ 0).setId(subId).build();
+ when(mSubscriptionManagerService.getSubscriptionInfoInternal(subId)).thenReturn(
+ subInfo);
+ doReturn(subId).when(mSubscriptionManagerService)
+ .getSubId(anyInt());
+ Phone phoneUT = makeNewPhoneUT();
+
+ phoneUT.sendMessage(
+ mPhoneUT.obtainMessage(
+ Phone.EVENT_SUBSCRIPTIONS_CHANGED,
+ new AsyncResult(null, null, null)));
+ processAllMessages();
+
+ verify(mNullCipherNotifier, times(1)).setSubscriptionMapping(eq(mContext), eq(0), eq(10));
+ }
+
+ @Test
+ public void testUpdateNullCipherNotifier_inactiveSubscription() {
+ when(mFeatureFlags.enableModemCipherTransparencyUnsolEvents()).thenReturn(true);
+ int subId = 1;
+ SubscriptionInfoInternal subInfo = new SubscriptionInfoInternal.Builder().setSimSlotIndex(
+ -1).setId(subId).build();
+ when(mSubscriptionManagerService.getSubscriptionInfoInternal(subId)).thenReturn(
+ subInfo);
+ doReturn(subId).when(mSubscriptionManagerService)
+ .getSubId(anyInt());
+ Phone phoneUT = makeNewPhoneUT();
+
+ phoneUT.sendMessage(
+ mPhoneUT.obtainMessage(
+ Phone.EVENT_SUBSCRIPTIONS_CHANGED,
+ new AsyncResult(null, null, null)));
+ processAllMessages();
+
+ verify(mNullCipherNotifier, times(1)).setSubscriptionMapping(eq(mContext), eq(0), eq(-1));
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
index a7e9604..855a5dc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/MultiSimSettingControllerTest.java
@@ -18,10 +18,8 @@
import static android.telephony.TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED;
import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE;
-import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL;
import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA;
import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS;
-import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -251,6 +249,8 @@
bundle.putBoolean(CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+ doReturn(true).when(mFeatureFlags).resetPrimarySimDefaultValues();
+
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
// Capture listener to emulate the carrier config change notification used later
ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
@@ -496,18 +496,9 @@
sendCarrierConfigChanged(1, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
processAllMessages();
- verify(mSubscriptionManagerService).setDefaultDataSubId(
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- verify(mSubscriptionManagerService).setDefaultSmsSubId(
- SubscriptionManager.INVALID_SUBSCRIPTION_ID);
- verify(mSubscriptionManagerService, never()).setDefaultVoiceSubId(anyInt());
-
- // Verify intent sent to select sub 2 as default for all types.
- Intent intent = captureBroadcastIntent();
- assertEquals(ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED, intent.getAction());
- assertEquals(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL,
- intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, -1));
- assertEquals(2, intent.getIntExtra(EXTRA_SUBSCRIPTION_ID, -1));
+ verify(mSubscriptionManagerService).setDefaultDataSubId(2);
+ verify(mSubscriptionManagerService).setDefaultSmsSubId(2);
+ verify(mSubscriptionManagerService).setDefaultVoiceSubId(2);
}
@Test
@@ -911,6 +902,27 @@
// This time user data should be disabled on phone1.
verify(mDataSettingsManagerMock2).setDataEnabled(
TelephonyManager.DATA_ENABLED_REASON_USER, false, PHONE_PACKAGE);
+
+ // Remove and insert back SIM before it's loaded.
+ clearInvocations(mSubscriptionManagerService);
+ markSubscriptionInactive(1/*subid*/);
+ sendCarrierConfigChanged(0/*phoneid*/, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+ verify(mSubscriptionManagerService).setDefaultDataSubId(2);
+
+ // insert it back, but carrier config not loaded yet
+ clearInvocations(mSubscriptionManagerService);
+ setSimSlotIndex(1/*subid*/, 0/*phoneid*/);
+ mMultiSimSettingControllerUT.notifySubscriptionInfoChanged();
+ sendCarrierConfigChanged(0/*phoneid*/, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+ verify(mSubscriptionManagerService, never()).setDefaultDataSubId(
+ SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+
+ // carrier config loaded
+ clearInvocations(mContext);
+ sendCarrierConfigChanged(0/*phoneid*/, 1/*subid*/);
+ verify(mContext).sendBroadcast(any());
}
@Test
@@ -1007,4 +1019,57 @@
// Default data is set to sub1
verify(mSubscriptionManagerService).syncGroupedSetting(1);
}
+
+ @Test
+ public void testDailogsAndWarnings_WithBootstrapSim() {
+ doReturn(true).when(mFeatureFlags).esimBootstrapProvisioningFlag();
+
+ // Mark sub 2 as inactive.
+ markSubscriptionInactive(2);
+ mMultiSimSettingControllerUT.notifyAllSubscriptionLoaded();
+ sendCarrierConfigChanged(0, 1);
+ processAllMessages();
+
+ // Sub 1 should be default sub silently.
+ verify(mSubscriptionManagerService).setDefaultDataSubId(1);
+ verify(mSubscriptionManagerService).setDefaultVoiceSubId(1);
+ verify(mSubscriptionManagerService).setDefaultSmsSubId(1);
+ verifyDismissIntentSent();
+
+ // Mark sub 2 bootstrap sim as active in phone[1].
+ doReturn(true).when(mSubscriptionManagerService).isEsimBootStrapProvisioningActivated();
+ setSimSlotIndex(2, 1);
+ clearInvocations(mSubscriptionManagerService);
+ clearInvocations(mContext);
+ mSubInfo[2] = new SubscriptionInfoInternal.Builder().setId(2).setSimSlotIndex(1)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_PROVISIONING).build();
+ mMultiSimSettingControllerUT.notifySubscriptionInfoChanged();
+ sendCarrierConfigChanged(1, 2);
+ processAllMessages();
+
+ // Taking out SIM 1.
+ clearInvocations(mSubscriptionManagerService);
+ markSubscriptionInactive(1/*subid*/);
+ mMultiSimSettingControllerUT.notifySubscriptionInfoChanged();
+ sendCarrierConfigChanged(0/*phoneid*/, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ processAllMessages();
+
+ // No user selection needed, no intent should be sent for notification
+ verify(mContext, never()).sendBroadcast(any());
+
+ //Insert back sim1 and switch from sub 1 to sub 3 in phone[0].
+ clearInvocations(mSubscriptionManagerService);
+ markSubscriptionInactive(1);
+ setSimSlotIndex(3, 0);
+ mMultiSimSettingControllerUT.notifySubscriptionInfoChanged();
+ sendCarrierConfigChanged(0/*phoneid*/, 3/*subid*/);
+ processAllMessages();
+
+ // Sub 3 should be default sub.
+ verify(mSubscriptionManagerService).setDefaultDataSubId(3);
+ verify(mSubscriptionManagerService).setDefaultVoiceSubId(3);
+ verify(mSubscriptionManagerService).setDefaultSmsSubId(3);
+ verify(mContext, never()).sendBroadcast(any());
+ }
+
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
index 6743d1c..0e04aff 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
@@ -57,6 +57,7 @@
import org.mockito.Mockito;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -157,6 +158,7 @@
init(1);
assertEquals(PhoneCapability.DEFAULT_SSSS_CAPABILITY, mPcm.getStaticPhoneCapability());
+ mPcm.updateRadioCapability();
setAndVerifyStaticCapability(PhoneCapability.DEFAULT_DSDS_CAPABILITY);
}
@@ -171,6 +173,7 @@
.setMaxActiveVoiceSubscriptions(2)
.build();
+ mPcm.updateRadioCapability();
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(mMockRadioConfig).getPhoneCapability(captor.capture());
Message msg = captor.getValue();
@@ -188,7 +191,7 @@
init(2);
mPcm.updateSimultaneousCallingSupport();
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
Message msg = captor.getValue();
@@ -209,7 +212,7 @@
mPcm.updateSimultaneousCallingSupport();
// Have the modem send invalid phone slots -1 and 5:
- int[] invalidEnabledLogicalSlots = {-1, 5};
+ List<Integer> invalidEnabledLogicalSlots = Arrays.asList(-1, 5);
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
Message msg = captor.getValue();
@@ -245,14 +248,14 @@
mPcm.registerForSimultaneousCellularCallingSlotsChanged(newSlots ->
cachedSimultaneousCallingSlots[0] = newSlots);
- mPcm.getStaticPhoneCapability();
+ mPcm.updateRadioCapability();
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> cBCaptor =
ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
verify(mMockRegistryManager).addOnSubscriptionsChangedListener(cBCaptor.capture(), any());
processAllMessages();
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
HashSet<Integer> expectedSlots = new HashSet<>(2);
for (int i : enabledLogicalSlots) {
expectedSlots.add(i);
@@ -296,7 +299,7 @@
// Simultaneous calling enabled
mPcm.updateSimultaneousCallingSupport();
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
Message msg = captor.getValue();
@@ -318,7 +321,7 @@
// Simultaneous Calling Disabled
mPcm.updateSimultaneousCallingSupport();
- int[] disabled = {};
+ List<Integer> disabled = List.of();
captor = ArgumentCaptor.forClass(Message.class);
verify(mMockRadioConfig, times(2)).updateSimultaneousCallingSupport(captor.capture());
msg = captor.getAllValues().get(1);
@@ -346,13 +349,13 @@
// Set the capability to DSDA mode to register listener, which will also trigger
// simultaneous calling evaluation
- mPcm.getCurrentPhoneCapability();
+ mPcm.updateRadioCapability();
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> cBCaptor =
ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
verify(mMockRegistryManager).addOnSubscriptionsChangedListener(cBCaptor.capture(), any());
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
Message msg = captor.getValue();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
index 1c4e43d..bf9ced3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneNumberUtilsTest.java
@@ -21,7 +21,10 @@
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+import com.android.internal.telephony.flags.Flags;
+
import android.net.Uri;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.PhoneNumberUtils;
import android.text.SpannableStringBuilder;
import android.text.style.TtsSpan;
@@ -32,6 +35,7 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
+import org.junit.Rule;
import org.junit.Test;
public class PhoneNumberUtilsTest {
@@ -40,6 +44,8 @@
private int mOldMinMatch;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Before
public void setUp() throws Exception {
mOldMinMatch = PhoneNumberUtils.getMinMatchForTest();
@@ -613,6 +619,60 @@
assertEquals("+1 650-555-1212", PhoneNumberUtils.formatNumber("+16505551212", "jp"));
}
+ /**
+ * Test to ensure that when international calls to Singapore are being placed the country
+ * code is present with and without the feature flag enabled.
+ */
+ @SmallTest
+ @Test
+ public void testFormatSingaporeInternational() {
+ // Disable feature flag.
+ mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+
+ // International call from a US iso
+ assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "US"));
+
+ // Lowercase country iso
+ assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "us"));
+
+ // Enable feature flag
+ mSetFlagsRule.enableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+
+ // Internal call from a US iso
+ assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "US"));
+
+ // Lowercase country iso
+ assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "us"));
+ mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+ }
+
+ /**
+ * Test to ensure that when local calls from Singaporean numbers are being placed to other
+ * Singaporean numbers the country code +65 is not being shown.
+ */
+ @SmallTest
+ @Test
+ public void testFormatSingaporeNational() {
+ // Disable feature flag.
+ mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+
+ // Local call from a Singaporean number to a Singaporean number
+ assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "SG"));
+
+ // Lowercase country iso.
+ assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg"));
+
+ // Enable feature flag.
+ mSetFlagsRule.enableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+
+ // Local call from a Singaporean number to a Singaporean number.
+ assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "SG"));
+
+ // Lowercase country iso.
+ assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg"));
+ mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
+ }
+
@SmallTest
@Test
public void testFormatNumber_LeadingStarAndHash() {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
index c2af9d8..d8005e8 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneSubInfoControllerTest.java
@@ -43,7 +43,8 @@
import android.os.Build;
import android.os.RemoteException;
import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.uicc.IsimUiccRecords;
import com.android.internal.telephony.uicc.SIMRecords;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
index bfe9649..88c5389 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RILTest.java
@@ -330,7 +330,7 @@
proxies.put(HAL_SERVICE_MODEM, mRadioModemProxy);
mRILInstance = new RIL(context,
RadioAccessFamily.getRafFromNetworkType(RILConstants.PREFERRED_NETWORK_MODE),
- Phone.PREFERRED_CDMA_SUBSCRIPTION, 0, proxies);
+ Phone.PREFERRED_CDMA_SUBSCRIPTION, 0, proxies, mFeatureFlags);
mRILUnderTest = spy(mRILInstance);
doReturn(mRadioProxy).when(mRILUnderTest).getRadioProxy();
doReturn(mDataProxy).when(mRILUnderTest).getRadioServiceProxy(eq(RadioDataProxy.class));
@@ -354,6 +354,8 @@
replaceInstance(RIL.class, "mHalVersion", mRILUnderTest, mHalVersionV14);
} catch (Exception e) {
}
+
+ doReturn(true).when(mFeatureFlags).combineRilDeathHandle();
}
@After
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
index 121136d..e3da458 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ServiceStateTrackerTest.java
@@ -2605,10 +2605,15 @@
waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
// PS WLAN
+ int wlanRat = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ if (wlanState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME
+ || wlanState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING) {
+ wlanRat = TelephonyManager.NETWORK_TYPE_IWLAN;
+ }
NetworkRegistrationInfo dataIwlanResult = new NetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
- wlanState, TelephonyManager.NETWORK_TYPE_IWLAN, 0, false,
- null, null, "", 1, false, false, false, lteVopsSupportInfo);
+ wlanState, wlanRat, 0, false, null, null,
+ "", 1, false, false, false, lteVopsSupportInfo);
sst.sendMessage(sst.obtainMessage(
ServiceStateTracker.EVENT_POLL_STATE_PS_IWLAN_REGISTRATION,
new AsyncResult(sst.mPollingContext, dataIwlanResult, null)));
@@ -2645,6 +2650,47 @@
verify(mLocaleTracker).updateOperatorNumeric(eq(""));
}
+ /**
+ * Ensure that LocaleTracker is not updated with mcc when only IWLAN is not in-service and the
+ * ims registration status is connected over iwlan,
+ */
+ @Test
+ public void testLocaleTrackerUpdateWithImsRegistrationTechIwlan() {
+ // Start state: Cell data only LTE + IWLAN
+ final String[] OpNamesResult = new String[] { "carrier long", "carrier", "310310" };
+ // Clear invocations for mLocaleTracker as precondition before test case execution & as part
+ // test setup
+ Mockito.clearInvocations(mLocaleTracker);
+
+ // Both Cellular abd Iwlan is in-service.
+ changeRegStateWithIwlanOperatorNumeric(
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, OpNamesResult, true);
+ verify(mLocaleTracker).updateOperatorNumeric(eq(OpNamesResult[2]));
+
+ // Test with Cellular as NOT_REG
+ changeRegStateWithIwlanOperatorNumeric(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
+ TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, OpNamesResult, true);
+ /* cellId based mccmnc */
+ verify(mLocaleTracker).updateOperatorNumeric(eq("00101"));
+
+ // IMS over Iwlan is registered.
+ doReturn(mImsPhone)
+ .when(mPhone).getImsPhone();
+ doReturn(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN)
+ .when(mImsPhone).getImsRegistrationTech();
+
+ // Test with Iwlan as NOT_REG
+ changeRegStateWithIwlanOperatorNumeric(
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
+ TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING,
+ OpNamesResult, false);
+ verify(mLocaleTracker).updateOperatorNumeric(eq(""));
+ }
@Test
public void testGetServiceProviderNameWithBrandOverride() {
String brandOverride = "spn from brand override";
@@ -3425,9 +3471,12 @@
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
assertEquals(2, nriList.size());
for (NetworkRegistrationInfo nri : nriList) {
- assertTrue(Arrays.equals(satelliteSupportedServices, nri.getAvailableServices().stream()
- .mapToInt(Integer::intValue)
- .toArray()));
+ if (nri.isInService()) {
+ assertTrue(Arrays.equals(satelliteSupportedServices,
+ nri.getAvailableServices().stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
+ }
}
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
index d3fde34..879b184 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimultaneousCallingTrackerTest.java
@@ -172,7 +172,7 @@
}
private void setAndVerifyStaticCapability(PhoneCapability capability) {
- mPcm.getCurrentPhoneCapability();
+ mPcm.updateRadioCapability();
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(mMockRadioConfig).getPhoneCapability(captor.capture());
Message msg = captor.getValue();
@@ -185,7 +185,8 @@
}
- private void setAndVerifySlotsSupportingSimultaneousCellularCalling(int[] enabledLogicalSlots) {
+ private void setAndVerifySlotsSupportingSimultaneousCellularCalling(
+ List<Integer> enabledLogicalSlots) {
ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
verify(mMockRadioConfig).updateSimultaneousCallingSupport(captor.capture());
Message msg = captor.getValue();
@@ -241,7 +242,7 @@
init(2);
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
@@ -264,7 +265,7 @@
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
// Have the modem inform telephony that only phone slot 0 supports DSDA:
- int[] enabledLogicalSlots = {0};
+ List<Integer> enabledLogicalSlots = List.of(0);
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
@@ -286,7 +287,7 @@
init(2);
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
@@ -309,7 +310,7 @@
init(2);
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
@@ -356,7 +357,7 @@
init(2);
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
@@ -384,7 +385,7 @@
init(2);
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
- int[] enabledLogicalSlots = {0};
+ List<Integer> enabledLogicalSlots = List.of(0);
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
@@ -416,7 +417,7 @@
init(2);
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
@@ -449,7 +450,7 @@
init(3);
setAndVerifyStaticCapability(STATIC_DSDA_CAPABILITY);
- int[] enabledLogicalSlots = {0, 1};
+ List<Integer> enabledLogicalSlots = Arrays.asList(0, 1);
setAndVerifySlotsSupportingSimultaneousCellularCalling(enabledLogicalSlots);
// Trigger onSubscriptionsChanged by updating the subscription ID of a phone slot:
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
index 70e3d6b..414fb3b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SmsDispatchersControllerTest.java
@@ -111,8 +111,8 @@
}
public void testNotifySmsSentToEmergencyStateTracker(String destAddr, long messageId,
- boolean isOverIms) {
- notifySmsSentToEmergencyStateTracker(destAddr, messageId, isOverIms);
+ boolean isOverIms, boolean isLastSmsPart) {
+ notifySmsSentToEmergencyStateTracker(destAddr, messageId, isOverIms, isLastSmsPart);
}
public void testNotifySmsSentFailedToEmergencyStateTracker(String destAddr,
@@ -456,7 +456,7 @@
@Test
@SmallTest
- public void testSendEmergencyTextWhenDomainPs() throws Exception {
+ public void testSendTextForEmergencyWhenDomainPs() throws Exception {
setUpDomainSelectionConnection();
setUpSmsDispatchers();
setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
@@ -488,7 +488,7 @@
@Test
@SmallTest
- public void testSendEmergencyTextWhenEmergencyStateTrackerReturnsFailure() throws Exception {
+ public void testSendTextForEmergencyWhenEmergencyStateTrackerReturnsFailure() throws Exception {
setUpDomainSelectionConnection();
setUpSmsDispatchers();
setUpEmergencyStateTracker(DisconnectCause.OUT_OF_SERVICE);
@@ -503,16 +503,88 @@
@Test
@SmallTest
+ public void testSendMultipartTextForEmergencyWhenDomainPs() throws Exception {
+ setUpDomainSelectionConnection();
+ setUpSmsDispatchers();
+ setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+
+ ArrayList<String> parts = new ArrayList<>();
+ ArrayList<PendingIntent> sentIntents = new ArrayList<>();
+ ArrayList<PendingIntent> deliveryIntents = new ArrayList<>();
+ mSmsDispatchersController.testSendMultipartText("911", "2222", parts, sentIntents,
+ deliveryIntents, null, "test-app", false, 0, false, 10, 1L);
+ processAllMessages();
+
+ SmsDispatchersController.DomainSelectionConnectionHolder holder =
+ mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true);
+ verify(mEmergencySmsDsc).requestDomainSelection(any(), any());
+ assertNotNull(holder);
+ assertNotNull(holder.getConnection());
+ assertTrue(holder.isEmergency());
+ assertTrue(holder.isDomainSelectionRequested());
+ assertEquals(1, holder.getPendingRequests().size());
+
+ mDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+ processAllMessages();
+
+ verify(mEmergencySmsDsc).finishSelection();
+ verify(mImsSmsDispatcher).sendMultipartText(eq("911"), eq("2222"), eq(parts),
+ eq(sentIntents), eq(deliveryIntents), any(), eq("test-app"), eq(false), eq(0),
+ eq(false), eq(10), eq(1L));
+ assertNull(holder.getConnection());
+ assertFalse(holder.isDomainSelectionRequested());
+ assertEquals(0, holder.getPendingRequests().size());
+ }
+
+ @Test
+ @SmallTest
+ public void testSendRetrySmsForEmergencyWhenDomainPs() throws Exception {
+ setUpDomainSelectionConnection();
+ setUpSmsDispatchers();
+ setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+
+ when(mPhone.getPhoneType()).thenReturn(PhoneConstants.PHONE_TYPE_GSM);
+ when(mImsSmsDispatcher.getFormat()).thenReturn(SmsConstants.FORMAT_3GPP);
+ when(mCdmaSmsDispatcher.getFormat()).thenReturn(SmsConstants.FORMAT_3GPP2);
+ when(mGsmSmsDispatcher.getFormat()).thenReturn(SmsConstants.FORMAT_3GPP);
+ replaceInstance(SMSDispatcher.SmsTracker.class,
+ "mFormat", mTracker, SmsConstants.FORMAT_3GPP);
+ replaceInstance(SMSDispatcher.SmsTracker.class, "mDestAddress", mTracker, "911");
+
+ mSmsDispatchersController.sendRetrySms(mTracker);
+ processAllMessages();
+
+ SmsDispatchersController.DomainSelectionConnectionHolder holder =
+ mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true);
+ verify(mEmergencySmsDsc).requestDomainSelection(any(), any());
+ assertNotNull(holder);
+ assertNotNull(holder.getConnection());
+ assertTrue(holder.isEmergency());
+ assertTrue(holder.isDomainSelectionRequested());
+ assertEquals(1, holder.getPendingRequests().size());
+
+ mDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+ processAllMessages();
+
+ verify(mEmergencySmsDsc).finishSelection();
+ verify(mImsSmsDispatcher).sendSms(eq(mTracker));
+ assertNull(holder.getConnection());
+ assertFalse(holder.isDomainSelectionRequested());
+ assertEquals(0, holder.getPendingRequests().size());
+ }
+
+ @Test
+ @SmallTest
public void testNotifySmsSentToEmergencyStateTrackerOnDomainCs() throws Exception {
setUpDomainSelectionEnabled(true);
setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
- mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("911", 1L, false);
+ mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("911", 1L, false, true);
processAllMessages();
verify(mTelephonyManager).isEmergencyNumber(eq("911"));
verify(mEmergencyStateTracker)
- .endSms(eq("1"), eq(true), eq(NetworkRegistrationInfo.DOMAIN_CS));
+ .endSms(eq("1"), eq(true), eq(NetworkRegistrationInfo.DOMAIN_CS), eq(true));
}
@Test
@@ -521,12 +593,12 @@
setUpDomainSelectionEnabled(true);
setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
- mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("911", 1L, true);
+ mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("911", 1L, true, true);
processAllMessages();
verify(mTelephonyManager).isEmergencyNumber(eq("911"));
verify(mEmergencyStateTracker)
- .endSms(eq("1"), eq(true), eq(NetworkRegistrationInfo.DOMAIN_PS));
+ .endSms(eq("1"), eq(true), eq(NetworkRegistrationInfo.DOMAIN_PS), eq(true));
}
@Test
@@ -535,11 +607,12 @@
setUpDomainSelectionEnabled(true);
setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
- mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("1234", 1L, true);
+ mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("1234", 1L, true, true);
processAllMessages();
verify(mTelephonyManager).isEmergencyNumber(eq("1234"));
- verify(mEmergencyStateTracker, never()).endSms(anyString(), anyBoolean(), anyInt());
+ verify(mEmergencyStateTracker, never())
+ .endSms(anyString(), anyBoolean(), anyInt(), anyBoolean());
}
@Test
@@ -547,7 +620,7 @@
public void testNotifySmsSentToEmergencyStateTrackerWithoutEmergencyStateTracker()
throws Exception {
setUpDomainSelectionEnabled(true);
- mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("911", 1L, true);
+ mSmsDispatchersController.testNotifySmsSentToEmergencyStateTracker("911", 1L, true, true);
verify(mTelephonyManager, never()).isEmergencyNumber(anyString());
}
@@ -563,7 +636,7 @@
verify(mTelephonyManager).isEmergencyNumber(eq("911"));
verify(mEmergencyStateTracker)
- .endSms(eq("1"), eq(false), eq(NetworkRegistrationInfo.DOMAIN_CS));
+ .endSms(eq("1"), eq(false), eq(NetworkRegistrationInfo.DOMAIN_CS), eq(true));
}
@Test
@@ -577,7 +650,7 @@
verify(mTelephonyManager).isEmergencyNumber(eq("911"));
verify(mEmergencyStateTracker)
- .endSms(eq("1"), eq(false), eq(NetworkRegistrationInfo.DOMAIN_PS));
+ .endSms(eq("1"), eq(false), eq(NetworkRegistrationInfo.DOMAIN_PS), eq(true));
}
@Test
@@ -591,7 +664,8 @@
processAllMessages();
verify(mTelephonyManager).isEmergencyNumber(eq("1234"));
- verify(mEmergencyStateTracker, never()).endSms(anyString(), anyBoolean(), anyInt());
+ verify(mEmergencyStateTracker, never())
+ .endSms(anyString(), anyBoolean(), anyInt(), anyBoolean());
}
@Test
@@ -742,15 +816,237 @@
setUpDomainSelectionConnection();
setUpSmsDispatchers();
when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(false);
+ when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
+
+ mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
+ "test-app", false, 0, false, 10, false, 1L, false);
+
+ // Expect that the domain selection is not executed and
+ // ImsSmsDispatcher handles this text directly.
+ verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"),
+ eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10),
+ eq(false), eq(1L), eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSendTextWhenDomainSelectionFinishedAndNewTextSent() throws Exception {
+ setUpDomainSelectionConnection();
+ setUpSmsDispatchers();
mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
"test-app", false, 0, false, 10, false, 1L, false);
processAllMessages();
- // Expect that the domain selection logic will not be executed.
SmsDispatchersController.DomainSelectionConnectionHolder holder =
mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
- assertNull(holder);
+ verify(mSmsDsc).requestDomainSelection(any(), any());
+ assertNotNull(holder);
+ assertNotNull(holder.getConnection());
+ assertTrue(holder.isDomainSelectionRequested());
+ assertEquals(1, holder.getPendingRequests().size());
+
+ // Expect that finishDomainSelection is called while a new pending request is posted.
+ mDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+
+ SmsDomainSelectionConnection newSmsDsc = Mockito.mock(SmsDomainSelectionConnection.class);
+ mSmsDispatchersController.setDomainSelectionResolverProxy(
+ new SmsDispatchersController.DomainSelectionResolverProxy() {
+ @Override
+ @Nullable
+ public DomainSelectionConnection getDomainSelectionConnection(Phone phone,
+ @DomainSelectionService.SelectorType int selectorType,
+ boolean isEmergency) {
+ return newSmsDsc;
+ }
+
+ @Override
+ public boolean isDomainSelectionSupported() {
+ return true;
+ }
+ });
+ CompletableFuture newDscFuture = new CompletableFuture<>();
+ when(newSmsDsc.requestDomainSelection(
+ any(DomainSelectionService.SelectionAttributes.class),
+ any(DomainSelectionConnection.DomainSelectionConnectionCallback.class)))
+ .thenReturn(newDscFuture);
+
+ // Expect that new domain selection connection is created and domain selection is performed.
+ mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
+ "test-app", false, 0, false, 10, false, 1L, false);
+ processAllMessages();
+
+ verify(mSmsDsc).finishSelection();
+
+ verify(newSmsDsc).requestDomainSelection(any(), any());
+ assertNotNull(holder.getConnection());
+ assertTrue(holder.isDomainSelectionRequested());
+ assertEquals(1, holder.getPendingRequests().size());
+
+ newDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+ processAllMessages();
+
+ verify(newSmsDsc).finishSelection();
+ verify(mImsSmsDispatcher, times(2)).sendText(eq("1111"), eq("2222"), eq("text"),
+ eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10),
+ eq(false), eq(1L), eq(false));
+ assertNull(holder.getConnection());
+ assertFalse(holder.isDomainSelectionRequested());
+ assertEquals(0, holder.getPendingRequests().size());
+ }
+
+ @Test
+ @SmallTest
+ public void testSendTextForEmergencyWhenDomainSelectionFinishedAndNewTextSent()
+ throws Exception {
+ setUpDomainSelectionConnection();
+ setUpSmsDispatchers();
+ setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+
+ mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
+ "test-app", false, 0, false, 10, false, 1L, false);
+ processAllMessages();
+
+ SmsDispatchersController.DomainSelectionConnectionHolder holder =
+ mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true);
+ verify(mEmergencySmsDsc).requestDomainSelection(any(), any());
+ assertNotNull(holder);
+ assertNotNull(holder.getConnection());
+ assertTrue(holder.isEmergency());
+ assertTrue(holder.isDomainSelectionRequested());
+ assertEquals(1, holder.getPendingRequests().size());
+
+ // Expect that finishDomainSelection is called while a new pending request is posted.
+ mDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+
+ EmergencySmsDomainSelectionConnection newEmergencySmsDsc =
+ Mockito.mock(EmergencySmsDomainSelectionConnection.class);
+ mSmsDispatchersController.setDomainSelectionResolverProxy(
+ new SmsDispatchersController.DomainSelectionResolverProxy() {
+ @Override
+ @Nullable
+ public DomainSelectionConnection getDomainSelectionConnection(Phone phone,
+ @DomainSelectionService.SelectorType int selectorType,
+ boolean isEmergency) {
+ return newEmergencySmsDsc;
+ }
+
+ @Override
+ public boolean isDomainSelectionSupported() {
+ return true;
+ }
+ });
+ CompletableFuture newDscFuture = new CompletableFuture<>();
+ when(newEmergencySmsDsc.requestDomainSelection(
+ any(DomainSelectionService.SelectionAttributes.class),
+ any(DomainSelectionConnection.DomainSelectionConnectionCallback.class)))
+ .thenReturn(newDscFuture);
+
+ // Expect that new domain selection connection is created and domain selection is performed.
+ mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
+ "test-app", false, 0, false, 10, false, 1L, false);
+ processAllMessages();
+
+ verify(mEmergencySmsDsc).finishSelection();
+
+ verify(newEmergencySmsDsc).requestDomainSelection(any(), any());
+ assertNotNull(holder.getConnection());
+ assertTrue(holder.isDomainSelectionRequested());
+ assertEquals(1, holder.getPendingRequests().size());
+
+ newDscFuture.complete(NetworkRegistrationInfo.DOMAIN_PS);
+ processAllMessages();
+
+ verify(newEmergencySmsDsc).finishSelection();
+ verify(mImsSmsDispatcher, times(2)).sendText(eq("911"), eq("2222"), eq("text"),
+ eq(mSentIntent), any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10),
+ eq(false), eq(1L), eq(false));
+ assertNull(holder.getConnection());
+ assertFalse(holder.isDomainSelectionRequested());
+ assertEquals(0, holder.getPendingRequests().size());
+ }
+
+ @Test
+ @SmallTest
+ public void testSendTextFallbackWhenDomainSelectionConnectionNotCreated() throws Exception {
+ mSmsDispatchersController.setDomainSelectionResolverProxy(
+ new SmsDispatchersController.DomainSelectionResolverProxy() {
+ @Override
+ @Nullable
+ public DomainSelectionConnection getDomainSelectionConnection(Phone phone,
+ @DomainSelectionService.SelectorType int selectorType,
+ boolean isEmergency) {
+ return null;
+ }
+
+ @Override
+ public boolean isDomainSelectionSupported() {
+ return true;
+ }
+ });
+ when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(true);
+ setUpSmsDispatchers();
+ when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
+
+ // Expect that creating a domain selection connection is failed and
+ // fallback to the legacy implementation.
+ mSmsDispatchersController.sendText("1111", "2222", "text", mSentIntent, null, null,
+ "test-app", false, 0, false, 10, false, 1L, false);
+ processAllMessages();
+
+ SmsDispatchersController.DomainSelectionConnectionHolder holder =
+ mSmsDispatchersController.testGetDomainSelectionConnectionHolder(false);
+ assertNotNull(holder);
+ assertNull(holder.getConnection());
+ assertFalse(holder.isDomainSelectionRequested());
+ assertEquals(0, holder.getPendingRequests().size());
+
+ verify(mImsSmsDispatcher).sendText(eq("1111"), eq("2222"), eq("text"), eq(mSentIntent),
+ any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
+ eq(1L), eq(false));
+ }
+
+ @Test
+ @SmallTest
+ public void testSendTextFallbackForEmergencyWhenDomainSelectionConnectionNotCreated()
+ throws Exception {
+ mSmsDispatchersController.setDomainSelectionResolverProxy(
+ new SmsDispatchersController.DomainSelectionResolverProxy() {
+ @Override
+ @Nullable
+ public DomainSelectionConnection getDomainSelectionConnection(Phone phone,
+ @DomainSelectionService.SelectorType int selectorType,
+ boolean isEmergency) {
+ return null;
+ }
+
+ @Override
+ public boolean isDomainSelectionSupported() {
+ return true;
+ }
+ });
+ when(mFeatureFlags.smsDomainSelectionEnabled()).thenReturn(true);
+ setUpSmsDispatchers();
+ setUpEmergencyStateTracker(DisconnectCause.NOT_DISCONNECTED);
+ when(mImsSmsDispatcher.isAvailable()).thenReturn(true);
+
+ // Expect that creating a domain selection connection is failed and
+ // fallback to the legacy implementation.
+ mSmsDispatchersController.sendText("911", "2222", "text", mSentIntent, null, null,
+ "test-app", false, 0, false, 10, false, 1L, false);
+ processAllMessages();
+
+ SmsDispatchersController.DomainSelectionConnectionHolder holder =
+ mSmsDispatchersController.testGetDomainSelectionConnectionHolder(true);
+ assertNotNull(holder);
+ assertNull(holder.getConnection());
+ assertTrue(holder.isEmergency());
+ assertFalse(holder.isDomainSelectionRequested());
+ assertEquals(0, holder.getPendingRequests().size());
+
+ verify(mImsSmsDispatcher).sendText(eq("911"), eq("2222"), eq("text"), eq(mSentIntent),
+ any(), any(), eq("test-app"), eq(false), eq(0), eq(false), eq(10), eq(false),
+ eq(1L), eq(false));
}
private void switchImsSmsFormat(int phoneType) {
@@ -843,7 +1139,8 @@
mSmsDispatchersController, mEmergencyStateTracker);
when(mEmergencyStateTracker.startEmergencySms(any(Phone.class), anyString(), anyBoolean()))
.thenReturn(mEmergencySmsFuture);
- doNothing().when(mEmergencyStateTracker).endSms(anyString(), anyBoolean(), anyInt());
+ doNothing().when(mEmergencyStateTracker)
+ .endSms(anyString(), anyBoolean(), anyInt(), anyBoolean());
mEmergencySmsFuture.complete(result);
when(mTelephonyManager.isEmergencyNumber(eq("911"))).thenReturn(true);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
index 6369825..d4717dd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
@@ -73,7 +73,6 @@
// Mocked classes
private Context mMockContext;
- private FeatureFlags mMockFeatureFlag;
private AppOpsManager mMockAppOps;
private SubscriptionManager mMockSubscriptionManager;
private ITelephony mMockTelephony;
@@ -92,7 +91,6 @@
@Before
public void setUp() throws Exception {
mMockContext = mock(Context.class);
- mMockFeatureFlag = mock(FeatureFlags.class);
mMockAppOps = mock(AppOpsManager.class);
mMockSubscriptionManager = mock(SubscriptionManager.class);
mMockTelephony = mock(ITelephony.class);
@@ -135,13 +133,11 @@
when(mMockContext.checkPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
PID, UID)).thenReturn(PackageManager.PERMISSION_DENIED);
- replaceFeatureFlag(mMockFeatureFlag);
setTelephonyMockAsService();
}
@After
public void tearDown() throws Exception {
- replaceFeatureFlag(mRealFeatureFlagToBeRestored);
mMockContentResolver = null;
mFakeSettingsConfigProvider = null;
mRealFeatureFlagToBeRestored = null;
@@ -554,9 +550,7 @@
}
@Test
- public void testCheckSubscriptionAssociatedWithUser_badSub_flag_enabled() {
- doReturn(true).when(mMockFeatureFlag).rejectBadSubIdInteraction();
-
+ public void testCheckSubscriptionAssociatedWithUser() {
doThrow(new IllegalArgumentException("has no records on device"))
.when(mMockSubscriptionManager).isSubscriptionAssociatedWithUser(SUB_ID,
UserHandle.SYSTEM);
@@ -564,19 +558,6 @@
UserHandle.SYSTEM));
}
- @Test
- public void testCheckSubscriptionAssociatedWithUser_badSub_flag_disabled() {
- doReturn(false).when(mMockFeatureFlag).rejectBadSubIdInteraction();
-
- doThrow(new IllegalArgumentException("No records found for sub"))
- .when(mMockSubscriptionManager).isSubscriptionAssociatedWithUser(SUB_ID,
- UserHandle.SYSTEM);
- assertTrue(TelephonyPermissions.checkSubscriptionAssociatedWithUser(mMockContext, SUB_ID,
- UserHandle.SYSTEM));
- assertTrue(TelephonyPermissions.checkSubscriptionAssociatedWithUser(mMockContext,
- SubscriptionManager.INVALID_SUBSCRIPTION_ID, UserHandle.SYSTEM));
- }
-
// Put mMockTelephony into service cache so that TELEPHONY_SUPPLIER will get it.
private void setTelephonyMockAsService() throws Exception {
when(mMockTelephonyBinder.queryLocalInterface(anyString())).thenReturn(mMockTelephony);
@@ -666,13 +647,4 @@
field.setAccessible(true);
field.set(providerHolder, iContentProvider);
}
-
- private synchronized void replaceFeatureFlag(final FeatureFlags newValue)
- throws Exception {
- Field field = TelephonyPermissions.class.getDeclaredField("sFeatureFlag");
- field.setAccessible(true);
-
- mRealFeatureFlagToBeRestored = (FeatureFlags) field.get(null);
- field.set(null, newValue);
- }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
index 6050b18..3e447a9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyRegistryTest.java
@@ -117,6 +117,7 @@
private CellIdentity mCellIdentityForRegiFail;
private int mRegistrationFailReason;
private Set<Integer> mSimultaneousCallingSubscriptions;
+ private boolean mCarrierRoamingNtnMode;
// All events contribute to TelephonyRegistry#isPhoneStatePermissionRequired
private static final Set<Integer> READ_PHONE_STATE_EVENTS;
@@ -192,7 +193,8 @@
TelephonyCallback.BarringInfoListener,
TelephonyCallback.RegistrationFailedListener,
TelephonyCallback.DataActivityListener,
- TelephonyCallback.SimultaneousCellularCallingSupportListener {
+ TelephonyCallback.SimultaneousCellularCallingSupportListener,
+ TelephonyCallback.CarrierRoamingNtnModeListener {
// This class isn't mockable to get invocation counts because the IBinder is null and
// crashes the TelephonyRegistry. Make a cheesy verify(times()) alternative.
public AtomicInteger invocationCount = new AtomicInteger(0);
@@ -287,6 +289,12 @@
invocationCount.incrementAndGet();
mSimultaneousCallingSubscriptions = simultaneousCallingSubscriptionIds;
}
+
+ @Override
+ public void onCarrierRoamingNtnModeChanged(boolean active) {
+ invocationCount.incrementAndGet();
+ mCarrierRoamingNtnMode = active;
+ }
}
private void addTelephonyRegistryService() {
@@ -1562,4 +1570,19 @@
processAllMessages();
assertEquals(subIdSet, mSimultaneousCallingSubscriptions);
}
+
+ @Test
+ public void testNotifyCarrierRoamingNtnModeChanged() {
+ int subId = INVALID_SUBSCRIPTION_ID;
+ doReturn(mMockSubInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());
+ doReturn(0/*slotIndex*/).when(mMockSubInfo).getSimSlotIndex();
+ int[] events = {TelephonyCallback.EVENT_CARRIER_ROAMING_NTN_MODE_CHANGED};
+
+ mTelephonyRegistry.listenWithEventList(false, false, subId, mContext.getOpPackageName(),
+ mContext.getAttributionTag(), mTelephonyCallback.callback, events, true);
+
+ mTelephonyRegistry.notifyCarrierRoamingNtnModeChanged(subId, true);
+ processAllMessages();
+ assertTrue(mCarrierRoamingNtnMode);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
index 673acbc..38b4f77 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyTest.java
@@ -35,6 +35,7 @@
import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.app.PropertyInvalidatedCache;
+import android.app.admin.DevicePolicyManager;
import android.app.usage.NetworkStatsManager;
import android.content.ContentProvider;
import android.content.ContentResolver;
@@ -304,6 +305,7 @@
protected AppOpsManager mAppOpsManager;
protected CarrierConfigManager mCarrierConfigManager;
protected UserManager mUserManager;
+ protected DevicePolicyManager mDevicePolicyManager;
protected KeyguardManager mKeyguardManager;
protected VcnManager mVcnManager;
protected NetworkPolicyManager mNetworkPolicyManager;
@@ -630,6 +632,8 @@
mCarrierConfigManager =
(CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
+ Context.DEVICE_POLICY_SERVICE);
mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
mVcnManager = mContext.getSystemService(VcnManager.class);
mNetworkPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
@@ -685,7 +689,7 @@
doReturn(mEriManager).when(mTelephonyComponentFactory)
.makeEriManager(nullable(Phone.class), anyInt());
doReturn(mLinkBandwidthEstimator).when(mTelephonyComponentFactory)
- .makeLinkBandwidthEstimator(nullable(Phone.class));
+ .makeLinkBandwidthEstimator(nullable(Phone.class), any(Looper.class));
doReturn(mDataProfileManager).when(mTelephonyComponentFactory)
.makeDataProfileManager(any(Phone.class), any(DataNetworkController.class),
any(DataServiceManager.class), any(Looper.class),
diff --git a/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
index 629327d..0563481 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/configupdate/TelephonyConfigUpdateInstallReceiverTest.java
@@ -16,34 +16,47 @@
package com.android.internal.telephony.configupdate;
-import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.UPDATE_CONTENT_PATH;
+import static android.telephony.NetworkRegistrationInfo.FIRST_SERVICE_TYPE;
+import static android.telephony.NetworkRegistrationInfo.LAST_SERVICE_TYPE;
+
+import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.NEW_CONFIG_CONTENT_PATH;
import static com.android.internal.telephony.configupdate.TelephonyConfigUpdateInstallReceiver.UPDATE_DIR;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.atLeast;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Intent;
+import android.util.ArraySet;
import androidx.annotation.Nullable;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.satellite.SatelliteConfig;
import com.android.internal.telephony.satellite.SatelliteConfigParser;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.File;
import java.util.Base64;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@@ -74,7 +87,7 @@
TelephonyConfigUpdateInstallReceiver testReceiver =
new TelephonyConfigUpdateInstallReceiver();
assertEquals(UPDATE_DIR, testReceiver.getUpdateDir().toString());
- assertEquals(new File(new File(UPDATE_DIR), UPDATE_CONTENT_PATH).toString(),
+ assertEquals(new File(new File(UPDATE_DIR), NEW_CONFIG_CONTENT_PATH).toString(),
testReceiver.getUpdateContent().toString());
}
@@ -92,38 +105,133 @@
// create spyTelephonyConfigUpdateInstallReceiver
TelephonyConfigUpdateInstallReceiver spyTelephonyConfigUpdateInstallReceiver =
spy(new TelephonyConfigUpdateInstallReceiver());
-
- // mock BeforeParser
- String mBase64StrForPBByteArray =
- "CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
- byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
- doReturn(mBytesProtoBuffer).when(
- spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
- SatelliteConfigParser mMockSatelliteConfigParserBefore =
- spy(new SatelliteConfigParser(mBytesProtoBuffer));
- doReturn(mMockSatelliteConfigParserBefore).when(
- spyTelephonyConfigUpdateInstallReceiver).getConfigParser(DOMAIN_SATELLITE);
-
- // mock UpdatedParser
- SatelliteConfigParser spySatelliteConfigParserAfter =
- spy(new SatelliteConfigParser(mBytesProtoBuffer));
- doReturn(5).when(spySatelliteConfigParserAfter).getVersion();
- doReturn(spySatelliteConfigParserAfter).when(spyTelephonyConfigUpdateInstallReceiver)
- .getNewConfigParser(any(), any());
-
+ doReturn(true).when(spyTelephonyConfigUpdateInstallReceiver)
+ .copySourceFileToTargetFile(any(), any());
replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
null, spyTelephonyConfigUpdateInstallReceiver);
assertSame(spyTelephonyConfigUpdateInstallReceiver,
TelephonyConfigUpdateInstallReceiver.getInstance());
+ // valid config data case
+ // mVersion:4 | mSupportedServicesPerCarrier:{1={310160=[1, 2, 3], 310220=[3]}} |
+ // mSatelliteRegionCountryCodes:[US] | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+ String mBase64StrForPBByteArray =
+ "CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+ byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+ doReturn(mBytesProtoBuffer).when(
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+ // mock UpdatedParser
+ SatelliteConfigParser spyValidParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+
ConcurrentHashMap<Executor, ConfigProviderAdaptor.Callback> spyCallbackHashMap = spy(
new ConcurrentHashMap<>());
spyCallbackHashMap.put(mExecutor, mCallback);
spyTelephonyConfigUpdateInstallReceiver.setCallbackMap(spyCallbackHashMap);
+
spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
- verify(spyCallbackHashMap, atLeast(1)).keySet();
+ verify(spyCallbackHashMap, times(2)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(1))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+ replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "mConfigParser",
+ spyTelephonyConfigUpdateInstallReceiver, spyValidParser);
+
+ // valid config data but smaller version case
+ // mVersion:3 | mSupportedServicesPerCarrier:{1={12345=[1, 2]}} |
+ // mSatelliteRegionCountryCodes:[US] | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+ mBase64StrForPBByteArray =
+ "CicIAxIPCAESCwoFMTIzNDUQARACGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+ mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+
+ // mock UpdatedParser
+ SatelliteConfigParser spyInvalidParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+ doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+ .getNewConfigParser(any(), any());
+
+ spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+ verify(spyCallbackHashMap, times(0)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+ // Empty config data case which is valid
+ // mSupportedServicesPerCarrier:{} | mSatelliteRegionCountryCodes:[US] |
+ // mIsSatelliteRegionAllowed:true | s2CellFile size:30
+ mBase64StrForPBByteArray =
+ "CioIDBomCh4wMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkSAlVTGAE=";
+ mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+ doReturn(mBytesProtoBuffer).when(
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+ // mock UpdatedParser
+ SatelliteConfigParser spyValidEmptyParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+ doReturn(spyValidEmptyParser).when(spyTelephonyConfigUpdateInstallReceiver)
+ .getNewConfigParser(any(), any());
+
+ spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+ verify(spyCallbackHashMap, times(2)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(1))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+ // Wrong plmn("1234") config data case
+ // mSupportedServicesPerCarrier:{1={"1234"=[1, 2, 3]}} |
+ // mSatelliteRegionCountryCodes:[US]
+ // | mIsSatelliteRegionAllowed:true | s2CellFile size:10
+ mBase64StrForPBByteArray =
+ "CigIDBIQCAESDAoEMTIzNBABEAIQAxoSCgowMTIzNDU2Nzg5EgJVUxgB";
+ mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+ doReturn(mBytesProtoBuffer).when(
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+ // mock UpdatedParser
+ spyInvalidParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+ doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+ .getNewConfigParser(any(), any());
+
+ spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+ verify(spyCallbackHashMap, times(0)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
+
+ // Wrong service("8") config data case
+ // mSupportedServicesPerCarrier:{1={12345=[6, "8"]}} |
+ // mSatelliteRegionCountryCodes:[US] |
+ // mIsSatelliteRegionAllowed:true | s2CellFile size:10
+ mBase64StrForPBByteArray =
+ "CicIDBIPCAESCwoFMTIzNDUQBhAIGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
+ mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
+ doReturn(mBytesProtoBuffer).when(
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
+
+ // mock UpdatedParser
+ spyInvalidParser =
+ spy(new SatelliteConfigParser(mBytesProtoBuffer));
+ doReturn(spyInvalidParser).when(spyTelephonyConfigUpdateInstallReceiver)
+ .getNewConfigParser(any(), any());
+
+ spyTelephonyConfigUpdateInstallReceiver.postInstall(mContext, new Intent());
+
+ verify(spyCallbackHashMap, times(0)).keySet();
+ verify(spyTelephonyConfigUpdateInstallReceiver, times(0))
+ .copySourceFileToTargetFile(any(), any());
+ Mockito.clearInvocations(spyCallbackHashMap);
+ Mockito.clearInvocations(spyTelephonyConfigUpdateInstallReceiver);
}
@@ -133,7 +241,7 @@
spy(new TelephonyConfigUpdateInstallReceiver());
doReturn(null).when(
- spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
null, spyTelephonyConfigUpdateInstallReceiver);
@@ -144,7 +252,7 @@
"CjYIBBIeCAESDgoGMzEwMTYwEAEQAhADEgoKBjMxMDIyMBADGhIKCjAxMjM0NTY3ODkSAlVTGAE=";
byte[] mBytesProtoBuffer = Base64.getDecoder().decode(mBase64StrForPBByteArray);
doReturn(mBytesProtoBuffer).when(
- spyTelephonyConfigUpdateInstallReceiver).getCurrentContent();
+ spyTelephonyConfigUpdateInstallReceiver).getContentFromContentPath(any());
replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
null, spyTelephonyConfigUpdateInstallReceiver);
@@ -172,4 +280,59 @@
testReceiver.unregisterCallback(testCallback);
assertEquals(0, testReceiver.getCallbackMap().size());
}
+
+ @Test
+ public void testIsValidSatelliteCarrierConfigData() {
+ TelephonyConfigUpdateInstallReceiver spyTelephonyConfigUpdateInstallReceiver =
+ spy(new TelephonyConfigUpdateInstallReceiver());
+ SatelliteConfigParser mockParser = mock(SatelliteConfigParser.class);
+ SatelliteConfig mockConfig = mock(SatelliteConfig.class);
+ doReturn(new ArraySet<>()).when(mockConfig).getAllSatelliteCarrierIds();
+ doReturn(mockConfig).when(mockParser).getConfig();
+
+ assertTrue(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> validPlmnsServices = new HashMap<>();
+ validPlmnsServices.put("123456", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+ validPlmnsServices.put("12345", Set.of(FIRST_SERVICE_TYPE, 4, LAST_SERVICE_TYPE));
+ doReturn(validPlmnsServices).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+
+ assertTrue(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> invalidPlmnsServices1 = new HashMap<>();
+ invalidPlmnsServices1.put("123456", Set.of(FIRST_SERVICE_TYPE - 1, 3, LAST_SERVICE_TYPE));
+ doReturn(invalidPlmnsServices1).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+ assertFalse(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> invalidPlmnsServices2 = new HashMap<>();
+ invalidPlmnsServices2.put("123456", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE + 1));
+ doReturn(invalidPlmnsServices2).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+ assertFalse(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> invalidPlmnsServices3 = new HashMap<>();
+ invalidPlmnsServices3.put("1234", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+ doReturn(invalidPlmnsServices3).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+ assertFalse(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+
+ doReturn(Set.of(1)).when(mockConfig).getAllSatelliteCarrierIds();
+ Map<String, Set<Integer>> invalidPlmnsServices4 = new HashMap<>();
+ invalidPlmnsServices4.put("1234567", Set.of(FIRST_SERVICE_TYPE, 3, LAST_SERVICE_TYPE));
+ doReturn(invalidPlmnsServices4).when(mockConfig).getSupportedSatelliteServices(anyInt());
+ doReturn(mockConfig).when(mockParser).getConfig();
+ assertFalse(spyTelephonyConfigUpdateInstallReceiver
+ .isValidSatelliteCarrierConfigData(mockParser));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/AccessNetworksManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/AccessNetworksManagerTest.java
index d1e5066..e45023c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/AccessNetworksManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/AccessNetworksManagerTest.java
@@ -356,7 +356,7 @@
mAccessNetworksManager.registerCallback(mMockedCallback);
- mQnsCallback.onReconnectQualifedNetworkType(ApnSetting.TYPE_IMS | ApnSetting.TYPE_MMS,
+ mQnsCallback.onReconnectQualifiedNetworkType(ApnSetting.TYPE_IMS | ApnSetting.TYPE_MMS,
AccessNetworkType.IWLAN);
processAllMessages();
@@ -381,7 +381,7 @@
@Test
public void testCallbackForReconnectQualifiedNetworkTypeWithFlagDisabled() throws Exception {
when(mFeatureFlags.reconnectQualifiedNetwork()).thenReturn(false);
- mQnsCallback.onReconnectQualifedNetworkType(ApnSetting.TYPE_IMS | ApnSetting.TYPE_MMS,
+ mQnsCallback.onReconnectQualifiedNetworkType(ApnSetting.TYPE_IMS | ApnSetting.TYPE_MMS,
AccessNetworkType.IWLAN);
processAllMessages();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
index ddbe9c0..0e2676e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/AutoDataSwitchControllerTest.java
@@ -93,8 +93,10 @@
private TelephonyDisplayInfo mGoodTelephonyDisplayInfo;
private TelephonyDisplayInfo mBadTelephonyDisplayInfo;
private int mDefaultDataSub;
+ private DataEvaluation mDataEvaluation;
private AutoDataSwitchController mAutoDataSwitchControllerUT;
private Map<Integer, AlarmManager.OnAlarmListener> mEventsToAlarmListener;
+ private Map<Integer, Object> mScheduledEventsToExtras;
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
@@ -137,6 +139,8 @@
doAnswer(invocation -> phone.getSubId() == mDefaultDataSub)
.when(phone).isUserDataEnabled();
}
+ mDataEvaluation = new DataEvaluation(DataEvaluation.DataEvaluationReason.EXTERNAL_QUERY);
+ doReturn(mDataEvaluation).when(mDataNetworkController).getInternetEvaluation(anyBoolean());
doReturn(new int[]{SUB_1, SUB_2}).when(mSubscriptionManagerService)
.getActiveSubIdList(true);
doAnswer(invocation -> {
@@ -184,9 +188,12 @@
mAutoDataSwitchControllerUT, mMockedAlarmManager);
mEventsToAlarmListener = getPrivateField(mAutoDataSwitchControllerUT,
"mEventsToAlarmListener", Map.class);
+ mScheduledEventsToExtras = getPrivateField(mAutoDataSwitchControllerUT,
+ "mScheduledEventsToExtras", Map.class);
doReturn(true).when(mFeatureFlags).autoDataSwitchAllowRoaming();
doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
+ doReturn(true).when(mFeatureFlags).autoDataSwitchUsesDataEnabled();
}
@After
@@ -240,7 +247,10 @@
prepareIdealUsesNonDdsCondition();
processAllFutureMessages();
clearInvocations(mMockedPhoneSwitcherCallback);
- doReturn(false).when(mPhone2).isDataAllowed();
+ mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason
+ .NO_SUITABLE_DATA_PROFILE);
+ doReturn(mDataEvaluation)
+ .when(mDataNetworkController).getInternetEvaluation(anyBoolean());
mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
processAllFutureMessages();
@@ -350,7 +360,6 @@
@Test
public void testRoaming_same_roaming_condition_uses_rat_signalStrength() {
- doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs();
// On primary phone
// 1. Both roaming, user allow roaming on both phone, uses RAT score to decide switch.
prepareIdealUsesNonDdsCondition();
@@ -375,7 +384,6 @@
@Test
public void testCancelSwitch_onPrimary_rat_signalStrength() {
- doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs();
// 4.1.1 Display info and signal strength on secondary phone became bad,
// but primary is still OOS, so still switch to the secondary.
prepareIdealUsesNonDdsCondition();
@@ -467,7 +475,7 @@
prepareIdealUsesNonDdsCondition();
// 2.2 Auto switch feature is disabled, no need validation
clearInvocations(mCellularNetworkValidator);
- doReturn(false).when(mPhone2).isDataAllowed();
+ mDataEvaluation.addDataDisallowedReason(DataEvaluation.DataDisallowedReason.DATA_DISABLED);
mAutoDataSwitchControllerUT.evaluateAutoDataSwitch(EVALUATION_REASON_DATA_SETTINGS_CHANGED);
processAllFutureMessages();
@@ -483,11 +491,13 @@
verify(mMockedPhoneSwitcherCallback).onRequireValidation(DEFAULT_PHONE_INDEX,
false/*needValidation*/);
+
+ clearInvocations(mMockedPhoneSwitcherCallback);
+ prepareIdealUsesNonDdsCondition();
}
@Test
public void testOnNonDdsSwitchBackToPrimary_rat_signalStrength() {
- doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs();
prepareIdealUsesNonDdsCondition();
processAllFutureMessages();
doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId();
@@ -536,10 +546,16 @@
@Test
public void testStabilityCheckOverride_basic() {
+ // Disable RAT + signalStrength base switching.
+ doReturn(-1).when(mDataConfigManager).getAutoDataSwitchScoreTolerance();
+ mAutoDataSwitchControllerUT = new AutoDataSwitchController(mContext, Looper.myLooper(),
+ mPhoneSwitcher, mFeatureFlags, mMockedPhoneSwitcherCallback);
+
// Starting stability check for switching to non-DDS
prepareIdealUsesNonDdsCondition();
- processAllMessages();
+ processAllFutureMessages();
+ clearInvocations(mMockedPhoneSwitcherCallback);
// Switch success, but the previous stability check is still pending
doReturn(PHONE_2).when(mPhoneSwitcher).getPreferredDataPhoneId();
@@ -557,7 +573,6 @@
@Test
public void testStabilityCheckOverride_uses_rat_signalStrength() {
- doReturn(true).when(mFeatureFlags).autoDataSwitchRatSs();
// Switching due to availability first.
prepareIdealUsesNonDdsCondition();
@@ -578,6 +593,7 @@
public void testValidationFailedRetry() {
prepareIdealUsesNonDdsCondition();
+ clearInvocations(mMockedPhoneSwitcherCallback);
for (int i = 0; i < MAX_RETRY; i++) {
mAutoDataSwitchControllerUT.evaluateRetryOnValidationFailed();
processAllFutureMessages();
@@ -730,7 +746,7 @@
// 4.2 Auto switch feature is enabled
doReturn(true).when(mPhone2).getDataRoamingEnabled();
- doReturn(true).when(mPhone2).isDataAllowed();
+ mDataEvaluation.addDataAllowedReason(DataEvaluation.DataAllowedReason.NORMAL);
// 5. No default network
mAutoDataSwitchControllerUT.updateDefaultNetworkCapabilities(null /*networkCapabilities*/);
@@ -783,10 +799,12 @@
@Override
public void processAllFutureMessages() {
- if (mFeatureFlags.autoDataSwitchRatSs()
- && mEventsToAlarmListener.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
+ if (mScheduledEventsToExtras.containsKey(EVENT_STABILITY_CHECK_PASSED)) {
mEventsToAlarmListener.get(EVENT_STABILITY_CHECK_PASSED).onAlarm();
}
+ if (mScheduledEventsToExtras.containsKey(EVENT_EVALUATE_AUTO_SWITCH)) {
+ mEventsToAlarmListener.get(EVENT_EVALUATE_AUTO_SWITCH).onAlarm();
+ }
super.processAllFutureMessages();
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index 9423551..60dcb59 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
@@ -51,6 +51,7 @@
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
+import android.net.Uri;
import android.net.vcn.VcnManager.VcnNetworkPolicyChangeListener;
import android.net.vcn.VcnNetworkPolicyResult;
import android.os.AsyncResult;
@@ -138,6 +139,8 @@
import java.util.Set;
import java.util.concurrent.Executor;
+import javax.annotation.Nullable;
+
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class DataNetworkControllerTest extends TelephonyTest {
@@ -182,8 +185,6 @@
private LinkBandwidthEstimatorCallback mLinkBandwidthEstimatorCallback;
private boolean mIsNonTerrestrialNetwork = false;
- private ArrayList<Integer> mCarrierSupportedSatelliteServices = new ArrayList<>();
- private FeatureFlags mFeatureFlags;
private final DataProfile mGeneralPurposeDataProfile = new DataProfile.Builder()
.setApnSetting(new ApnSetting.Builder()
@@ -393,17 +394,6 @@
"PRIORITIZE_LATENCY", 1).getBytes()))
.build();
- private final DataProfile mMmsOnWlanDataProfile = new DataProfile.Builder()
- .setApnSetting(new ApnSetting.Builder()
- .setEntryName("mms_wlan")
- .setApnName("mms_wlan")
- .setApnTypeBitmask(ApnSetting.TYPE_MMS)
- .setCarrierEnabled(true)
- .setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN)
- .build())
- .setPreferred(false)
- .build();
-
private final DataProfile mNtnDataProfile = new DataProfile.Builder()
.setApnSetting(new ApnSetting.Builder()
.setEntryName("ntn")
@@ -700,7 +690,6 @@
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setDataSpecificInfo(dsri)
.setIsNonTerrestrialNetwork(mIsNonTerrestrialNetwork)
- .setAvailableServices(mCarrierSupportedSatelliteServices)
.setEmergencyOnly(isEmergencyOnly)
.build());
@@ -710,7 +699,6 @@
.setRegistrationState(iwlanRegState)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setIsNonTerrestrialNetwork(mIsNonTerrestrialNetwork)
- .setAvailableServices(mCarrierSupportedSatelliteServices)
.setEmergencyOnly(isEmergencyOnly)
.build());
@@ -854,6 +842,11 @@
.config_enable_iwlan_handover_policy, true);
mContextFixture.putBooleanResource(com.android.internal.R.bool
.config_enhanced_iwlan_handover_check, true);
+ mContextFixture.putStringArrayResource(com.android.internal.R.array
+ .config_force_cellular_transport_capabilities,
+ new String[] {"ims", "eims", "xcap"});
+ mContextFixture.putIntResource(com.android.internal.R.integer
+ .config_reevaluate_bootstrap_sim_data_usage_millis, 60000);
}
@Before
@@ -870,7 +863,6 @@
mMockedDataNetworkControllerCallback = Mockito.mock(DataNetworkControllerCallback.class);
mMockedDataRetryManagerCallback = Mockito.mock(DataRetryManagerCallback.class);
mMockSubInfo = Mockito.mock(SubscriptionInfo.class);
- mFeatureFlags = Mockito.mock(FeatureFlags.class);
when(mTelephonyComponentFactory.makeDataSettingsManager(any(Phone.class),
any(DataNetworkController.class), any(FeatureFlags.class), any(Looper.class),
any(DataSettingsManager.DataSettingsManagerCallback.class))).thenCallRealMethod();
@@ -896,6 +888,10 @@
doReturn(PhoneConstants.State.IDLE).when(mCT).getState();
doReturn(new SubscriptionInfoInternal.Builder().setId(1).build())
.when(mSubscriptionManagerService).getSubscriptionInfoInternal(anyInt());
+ doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
+ doReturn(true).when(mFeatureFlags).satelliteInternet();
+ doReturn(true).when(mFeatureFlags)
+ .ignoreExistingNetworksForInternetAllowedChecking();
List<SubscriptionInfo> infoList = new ArrayList<>();
infoList.add(mMockSubInfo);
@@ -997,7 +993,7 @@
List<DataProfile> profiles = List.of(mGeneralPurposeDataProfile,
mGeneralPurposeDataProfileAlternative, mImsCellularDataProfile,
mImsIwlanDataProfile, mEmergencyDataProfile, mFotaDataProfile,
- mTetheringDataProfile, mMmsOnWlanDataProfile, mLowLatencyDataProfile,
+ mTetheringDataProfile, mLowLatencyDataProfile,
mNtnDataProfile, mEsimBootstrapDataProfile,
mEsimBootstrapImsProfile, mEsimBootstrapRcsInfraStructureProfile);
@@ -1136,15 +1132,29 @@
}
private @NonNull TelephonyNetworkRequest createNetworkRequest(Integer... capabilities) {
+ return createNetworkRequest(null, capabilities);
+ }
+
+ private @NonNull TelephonyNetworkRequest createNetworkRequest(@Nullable Boolean restricted,
+ Integer... capabilities) {
NetworkCapabilities netCaps = new NetworkCapabilities();
for (int networkCapability : capabilities) {
netCaps.addCapability(networkCapability);
}
+ if (restricted != null) {
+ if (restricted) {
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ }
+ } else {
+ // Data Network uses the same to define its own capabilities.
+ netCaps.maybeMarkCapabilitiesRestricted();
+ }
+
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
- return new TelephonyNetworkRequest(nativeNetworkRequest, mPhone);
+ return new TelephonyNetworkRequest(nativeNetworkRequest, mPhone, mFeatureFlags);
}
// The purpose of this test is to make sure the network request insertion/removal works as
@@ -1405,7 +1415,7 @@
netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
- NetworkRequest.Type.REQUEST), mPhone));
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE);
List<DataNetwork> dataNetworkList = getDataNetworks();
@@ -1708,72 +1718,232 @@
}
@Test
- public void testNonTerrestrialNetworkChangedWithoutDataSupport() throws Exception {
- when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ public void testIsNetworkRequestSatisfiedByTransportCellularTransportRequest() {
mIsNonTerrestrialNetwork = true;
- // Data is not supported while using satellite
- mCarrierSupportedSatelliteServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VOICE);
+
+ // Data is not supported for cellular transport network request while using satellite
+ // network
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
- mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ // Set network request transport as Cellular in satellite network
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
processAllMessages();
- // Data with internet capability should not be allowed
- // when the device is using non-terrestrial network
- verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ // Verify data is not connected since Network request cannot satisfy by transport
+ verify(mMockedDataNetworkControllerCallback, never())
+ .onConnectedInternetDataNetworksChanged(any());
+
+ // However, WLAN network setup shouldn't be affected
+ doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
+ .getPreferredTransportByNetworkCapability(anyInt());
+ mDataNetworkControllerUT.obtainMessage(5 /*EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS*/,
+ DataEvaluation.DataEvaluationReason.PREFERRED_TRANSPORT_CHANGED).sendToTarget();
+ processAllMessages();
+ verify(mMockedDataNetworkControllerCallback).onConnectedInternetDataNetworksChanged(any());
mIsNonTerrestrialNetwork = false;
- mCarrierSupportedSatelliteServices.clear();
- serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
-
- // Verify data is restored.
- verifyInternetConnected();
}
@Test
- public void testNonTerrestrialNetworkWithDataSupport() throws Exception {
- when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ public void testMobileDataDisabledIsValidRestrictedRequestWithSatelliteInternetRequest() {
mIsNonTerrestrialNetwork = true;
- // Data is supported while using satellite
- mCarrierSupportedSatelliteServices.add(NetworkRegistrationInfo.SERVICE_TYPE_DATA);
+
+ //Mobile Data Disabled
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
+ processAllMessages();
+
+ // Data is not supported for cellular transport network request while using satellite
+ // network
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
- mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ // Set network request transport as Satellite with restricted capability + internet
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
processAllMessages();
- // Verify data is connected.
- verifyInternetConnected();
+ // Verify data is not connected since Network request cannot satisfy by transport
+ verify(mMockedDataNetworkControllerCallback, never())
+ .onConnectedInternetDataNetworksChanged(any());
mIsNonTerrestrialNetwork = false;
- mCarrierSupportedSatelliteServices.clear();
}
@Test
- public void testNonTerrestrialNetworkWithFlagDisabled() throws Exception {
- when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
-
+ public void testMobileDataDisabledIsValidRestrictedRequestWithTransportSatelliteMMSRequest()
+ throws Exception {
mIsNonTerrestrialNetwork = true;
- // Data is not supported while using satellite
- mCarrierSupportedSatelliteServices.add(NetworkRegistrationInfo.SERVICE_TYPE_VOICE);
+
+ // Data disabled
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
+ // Always allow MMS off
+ mDataNetworkControllerUT.getDataSettingsManager().setMobileDataPolicy(TelephonyManager
+ .MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, false);
+ processAllMessages();
+
+ // Data is not supported for cellular transport network request while using satellite
+ // network
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
- mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ // Set network request transport as Cellular+Satellite with restricted capability + mms
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
processAllMessages();
- // As feature is disabled, data is connected.
- verifyInternetConnected();
+ // Verify mms is not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
mIsNonTerrestrialNetwork = false;
- mCarrierSupportedSatelliteServices.clear();
}
+ @Test
+ public void testOnMmsAlwaysALlowedIsValidRestrictedRequestWithTransportSatelliteMMSRequest()
+ throws Exception {
+ mIsNonTerrestrialNetwork = true;
+
+ // Data disabled
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(
+ TelephonyManager.DATA_ENABLED_REASON_USER, false, mContext.getOpPackageName());
+ // Always allow MMS On
+ mDataNetworkControllerUT.getDataSettingsManager().setMobileDataPolicy(TelephonyManager
+ .MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, true);
+ processAllMessages();
+
+ // Data is not supported for cellular transport network request while using satellite
+ // network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ // Set network request transport as Cellular+Satellite with restricted capability + mms
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+ processAllMessages();
+
+ // Verify mms is connected if mms always allowed is on
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS);
+
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @Test
+ public void testIsNetworkRequestSatisfiedByTransportSatelliteTransportRequest_Terrestrial() {
+ // Set network request transport as satellite in satellite network
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+ processAllMessages();
+
+ // Verify data is not supported for satellite transport network request while using cellular
+ verify(mMockedDataNetworkControllerCallback, never())
+ .onConnectedInternetDataNetworksChanged(any());
+
+ }
+
+ @Test
+ public void testIsNetworkRequestSatisfiedByTransportSatelliteTransportRequest() {
+ mIsNonTerrestrialNetwork = true;
+
+ // Data is supported for satellite transport network request while using satellite network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ // Set network request transport as satellite while using satellite network
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+ processAllMessages();
+
+ // Verify data is connected since Network request satisfy by transport
+ verify(mMockedDataNetworkControllerCallback).onConnectedInternetDataNetworksChanged(any());
+
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @Test
+ public void testIsNetworkRequestSatisfiedByTransportNoTransportRequest() {
+ mIsNonTerrestrialNetwork = true;
+
+ // Data is supported for no transport network request while using satellite network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ // Set network request transport as no transport with Internet capability
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+ processAllMessages();
+
+ // Verify data is connected since Network request satisfy by transport
+ verify(mMockedDataNetworkControllerCallback).onConnectedInternetDataNetworksChanged(any());
+
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @Test
+ public void testIsNetworkCapabilitySatelliteAndCellularCapableImsCellularTransportRequest()
+ throws Exception {
+ mIsNonTerrestrialNetwork = true;
+
+ // IMS PDN is supported for cellular network request while using satellite network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ // Set network request transport as Cellular + IMS
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
+ new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+ processAllMessages();
+
+ // Verify ims is connected since, cellular network request for ims is allowed while using
+ // satellite network
+ verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_MMTEL);
+
+ mIsNonTerrestrialNetwork = false;
+ }
@Test
public void testRoamingDataChanged() throws Exception {
@@ -3156,12 +3326,20 @@
NetworkCapabilities.NET_CAPABILITY_IMS);
TelephonyNetworkRequest secondTnr = createNetworkRequest(
NetworkCapabilities.NET_CAPABILITY_IMS);
+ TelephonyNetworkRequest thirdTnr = new TelephonyNetworkRequest(
+ new NetworkRequest((new NetworkCapabilities.Builder())
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
+ .addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE)
+ .build(),
+ ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
mDataNetworkControllerUT.addNetworkRequest(firstTnr);
processAllMessages();
mDataNetworkControllerUT.removeNetworkRequest(firstTnr);
mDataNetworkControllerUT.addNetworkRequest(secondTnr);
+ mDataNetworkControllerUT.addNetworkRequest(thirdTnr);
processAllFutureMessages();
verify(mMockedWwanDataServiceManager, times(1)).setupDataCall(anyInt(),
@@ -3319,9 +3497,6 @@
// Verify retry is cleared on this network
assertThat(mDataNetworkControllerUT.getDataRetryManager()
.isAnyHandoverRetryScheduled(network)).isFalse();
- // Verify the data profile is still throttled
- assertThat(mDataNetworkControllerUT.getDataRetryManager().isDataProfileThrottled(
- network.getDataProfile(), AccessNetworkConstants.TRANSPORT_TYPE_WLAN)).isTrue();
}
@Test
@@ -3437,7 +3612,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
mDataNetworkControllerUT.addNetworkRequest(tnr);
processAllMessages();
@@ -3461,7 +3636,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
mDataNetworkControllerUT.addNetworkRequest(tnr);
processAllMessages();
@@ -3533,7 +3708,7 @@
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(
- new TelephonyNetworkRequest(nativeNetworkRequest, mPhone));
+ new TelephonyNetworkRequest(nativeNetworkRequest, mPhone, mFeatureFlags));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN);
@@ -3649,7 +3824,7 @@
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(
- new TelephonyNetworkRequest(nativeNetworkRequest, mPhone));
+ new TelephonyNetworkRequest(nativeNetworkRequest, mPhone, mFeatureFlags));
processAllMessages();
// Everything should be disconnected.
@@ -3687,7 +3862,7 @@
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(
- new TelephonyNetworkRequest(nativeNetworkRequest, mPhone));
+ new TelephonyNetworkRequest(nativeNetworkRequest, mPhone, mFeatureFlags));
processAllMessages();
// Everything should be disconnected.
@@ -3910,7 +4085,7 @@
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(
- new TelephonyNetworkRequest(nativeNetworkRequest, mPhone));
+ new TelephonyNetworkRequest(nativeNetworkRequest, mPhone, mFeatureFlags));
processAllMessages();
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
@@ -3934,7 +4109,7 @@
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(
- new TelephonyNetworkRequest(nativeNetworkRequest, mPhone));
+ new TelephonyNetworkRequest(nativeNetworkRequest, mPhone, mFeatureFlags));
processAllMessages();
verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
@@ -3988,18 +4163,54 @@
}
@Test
+ public void testNetworkValidationStatusChangeCallback() throws Exception {
+ // Request not restricted network
+ TelephonyNetworkRequest request = createNetworkRequest(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
+ TelephonyNetworkAgent agent = getPrivateField(getDataNetworks().get(0), "mNetworkAgent",
+ TelephonyNetworkAgent.class);
+ agent.onValidationStatus(1/*status*/, Uri.EMPTY);
+ processAllMessages();
+
+ // Verify notify
+ verify(mMockedDataNetworkControllerCallback)
+ .onInternetDataNetworkValidationStatusChanged(1);
+
+ // Request restricted network
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+ getDataNetworks().get(0).tearDown(DataNetwork.TEAR_DOWN_REASON_NONE);
+ mDataNetworkControllerUT.getDataSettingsManager().setDataEnabled(0, false, "");
+ processAllMessages();
+ clearInvocations(mMockedDataNetworkControllerCallback);
+ mDataNetworkControllerUT.addNetworkRequest(createNetworkRequest(
+ true, NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+ agent = getPrivateField(getDataNetworks().get(0), "mNetworkAgent",
+ TelephonyNetworkAgent.class);
+ agent.onValidationStatus(1/*status*/, Uri.EMPTY);
+ processAllMessages();
+
+ // Verify not notified
+ verify(mMockedDataNetworkControllerCallback, never())
+ .onInternetDataNetworkValidationStatusChanged(anyInt());
+ }
+
+ @Test
public void testImsGracefulTearDown() throws Exception {
setImsRegistered(true);
setRcsRegistered(true);
NetworkCapabilities netCaps = new NetworkCapabilities();
netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
+ netCaps.maybeMarkCapabilitiesRestricted();
netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
- nativeNetworkRequest, mPhone);
+ nativeNetworkRequest, mPhone, mFeatureFlags);
mDataNetworkControllerUT.addNetworkRequest(networkRequest);
@@ -4046,12 +4257,13 @@
// setup emergency data network.
NetworkCapabilities netCaps = new NetworkCapabilities();
netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
+ netCaps.maybeMarkCapabilitiesRestricted();
netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE);
NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps,
ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST);
TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
- nativeNetworkRequest, mPhone);
+ nativeNetworkRequest, mPhone, mFeatureFlags);
mDataNetworkControllerUT.addNetworkRequest(networkRequest);
processAllMessages();
@@ -4693,11 +4905,12 @@
ConnectivityManager.TYPE_MOBILE, 0, NetworkRequest.Type.REQUEST);
mDataNetworkControllerUT.addNetworkRequest(new TelephonyNetworkRequest(
- nativeNetworkRequest, mPhone));
+ nativeNetworkRequest, mPhone, mFeatureFlags));
processAllMessages();
// Intentionally create a new telephony request with the original native network request.
- TelephonyNetworkRequest request = new TelephonyNetworkRequest(nativeNetworkRequest, mPhone);
+ TelephonyNetworkRequest request = new TelephonyNetworkRequest(
+ nativeNetworkRequest, mPhone, mFeatureFlags);
mDataNetworkControllerUT.removeNetworkRequest(request);
processAllFutureMessages();
@@ -4788,7 +5001,7 @@
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
processAllMessages();
verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE,
NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY);
@@ -4797,7 +5010,7 @@
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
processAllMessages();
List<DataNetwork> dataNetworkList = getDataNetworks();
assertThat(dataNetworkList).hasSize(1);
@@ -4838,43 +5051,85 @@
}
@Test
- public void testAllowBringUpWithDifferentDataProfileForWlan() throws Exception {
- // Mock MMS preferred on WLAN
- doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
- .getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
-
- // Setup a default cellular network that's capable of MMS
- mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
- mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_IMS));
- processAllMessages();
- verifyConnectedNetworkHasDataProfile(mGeneralPurposeDataProfile);
-
- // Mock the designated MMS profile when WLAN is preferred
- doReturn(mMmsOnWlanDataProfile).when(mDataProfileManager).getDataProfileForNetworkRequest(
- any(TelephonyNetworkRequest.class), eq(TelephonyManager.NETWORK_TYPE_IWLAN),
- anyBoolean(), anyBoolean(), anyBoolean());
- setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager,
- createDataCallResponse(2, DataCallResponse.LINK_STATUS_ACTIVE));
-
- // Verify the designated MMS profile is used to satisfy MMS request
- mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_MMS));
- processAllMessages();
- verifyConnectedNetworkHasDataProfile(mMmsOnWlanDataProfile);
- }
-
- @Test
public void testNonTerrestrialNetwork() throws Exception {
- when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ TelephonyNetworkRequest request;
mIsNonTerrestrialNetwork = true;
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
- mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_RCS));
+ // By default, Test only support restricted network, regardless whether constrained.
+ // Verify not_restricted network not supported.
+ request = createNetworkRequest(false, NetworkCapabilities.NET_CAPABILITY_RCS);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
+ verifyAllDataDisconnected();
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+
+ // Verify restricted network is supported.
+ request = createNetworkRequest(true, NetworkCapabilities.NET_CAPABILITY_RCS);
+ mDataNetworkControllerUT.addNetworkRequest(request);
processAllMessages();
verifyConnectedNetworkHasDataProfile(mNtnDataProfile);
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+ getDataNetworks().get(0).tearDown(DataNetwork
+ .TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED);
+
+ // Test constrained network is supported, regardless whether it's restricted
+ processAllFutureMessages();
+ verifyAllDataDisconnected();
+ mCarrierConfig.putInt(CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+ CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED);
+ carrierConfigChanged();
+ // Verify not_restricted, not_constrained network not supported.
+ NetworkCapabilities netCaps = new NetworkCapabilities();
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
+ try {
+ netCaps.addCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+ } catch (Exception ignored) { }
+ request = new TelephonyNetworkRequest(new NetworkRequest(netCaps,
+ ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
+
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
+ verifyAllDataDisconnected();
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+
+ // Verify restricted, not_constrained network is supported.
+ netCaps = new NetworkCapabilities();
+ netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
+ netCaps.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ try {
+ netCaps.addCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+ } catch (Exception ignored) { }
+ request = new TelephonyNetworkRequest(new NetworkRequest(netCaps,
+ ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
+ mDataNetworkControllerUT.addNetworkRequest(request);
+ processAllMessages();
+ verifyConnectedNetworkHasDataProfile(mNtnDataProfile);
+ mDataNetworkControllerUT.removeNetworkRequest(request);
+ getDataNetworks().get(0).tearDown(DataNetwork
+ .TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED);
+
+ // TODO(enable after NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED become a default cap)
+ // Test not constrained network supported
+// processAllFutureMessages();
+// verifyAllDataDisconnected();
+// mCarrierConfig.putInt(CarrierConfigManager.KEY_SATELLITE_DATA_SUPPORT_MODE_INT,
+// CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL);
+// carrierConfigChanged();
+//
+// netCaps = new NetworkCapabilities();
+// netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
+// try {
+// netCaps.addCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED);
+// } catch (Exception ignored) {}
+// mDataNetworkControllerUT.addNetworkRequest(
+// new TelephonyNetworkRequest(new NetworkRequest(netCaps,
+// ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId,
+// NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags));
+// processAllMessages();
+// verifyConnectedNetworkHasDataProfile(mNtnDataProfile);
}
@Test
@@ -4929,7 +5184,8 @@
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ createNetworkRequest(true/*restricted*/,
+ NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
verifyConnectedNetworkHasDataProfile(mEsimBootstrapDataProfile);
@@ -4940,13 +5196,6 @@
.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 2);
processAllMessages();
verifyConnectedNetworkHasDataProfile(mEsimBootstrapImsProfile);
-
- serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
- mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_RCS));
- processAllMessages();
- verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
}
@Test
@@ -4985,7 +5234,7 @@
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ createNetworkRequest(true, NetworkCapabilities.NET_CAPABILITY_INTERNET));
processAllMessages();
// With allowed data limit unlimited, connection is allowed
verifyConnectedNetworkHasDataProfile(mEsimBootstrapDataProfile);
@@ -5031,8 +5280,7 @@
}
@Test
- public void testNtnNetworkOnProvisioningProfileClass_WithFlagEnabled() throws Exception {
- when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ public void testNtnNetworkOnProvisioningProfileClassWithFlagEnabled() throws Exception {
when(mFeatureFlags.esimBootstrapProvisioningFlag()).thenReturn(true);
// Allowed data limit Unlimited
mContextFixture.putIntResource(com.android.internal.R.integer
@@ -5044,7 +5292,7 @@
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
mDataNetworkControllerUT.addNetworkRequest(
- createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_RCS));
+ createNetworkRequest(true, NetworkCapabilities.NET_CAPABILITY_RCS));
processAllMessages();
assertThat(mDataNetworkControllerUT.isEsimBootStrapProvisioningActivated()).isTrue();
@@ -5053,8 +5301,7 @@
}
@Test
- public void testNonNtnNetworkOnProvisioningProfileClass_WithFlagEnabled() throws Exception {
- when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ public void testNonNtnNetworkOnProvisioningProfileClassWithFlagEnabled() throws Exception {
when(mFeatureFlags.esimBootstrapProvisioningFlag()).thenReturn(true);
doReturn(new SubscriptionInfoInternal.Builder().setId(1)
.setProfileClass(SubscriptionManager.PROFILE_CLASS_PROVISIONING).build())
@@ -5194,4 +5441,33 @@
verify(mMockedWwanDataServiceManager, never()).deactivateDataCall(anyInt(),
eq(DataService.REQUEST_REASON_NORMAL), any(Message.class));
}
+
+ @Test
+ public void testRadioOffTearDown() throws Exception {
+ testSetupDataNetwork();
+ doReturn(true).when(mSST).isPendingRadioPowerOffAfterDataOff();
+ mDataNetworkControllerUT.tearDownAllDataNetworks(
+ DataNetwork.TEAR_DOWN_REASON_AIRPLANE_MODE_ON);
+ processAllMessages();
+ verifyAllDataDisconnected();
+ verify(mMockedDataNetworkControllerCallback).onAnyDataNetworkExistingChanged(eq(false));
+
+ clearInvocations(mMockedDataNetworkControllerCallback);
+ mDataNetworkControllerUT.addNetworkRequest(
+ createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET));
+ processAllMessages();
+ verifyAllDataDisconnected();
+ verify(mMockedDataNetworkControllerCallback, never()).onAnyDataNetworkExistingChanged(
+ anyBoolean());
+ }
+
+ @Test
+ public void testGetInternetEvaluation() throws Exception {
+ testSetupDataNetwork();
+ doReturn(true).when(mSST).isPendingRadioPowerOffAfterDataOff();
+ assertThat(mDataNetworkControllerUT.getInternetEvaluation(false/*ignoreExistingNetworks*/)
+ .containsDisallowedReasons()).isFalse();
+ assertThat(mDataNetworkControllerUT.getInternetEvaluation(true/*ignoreExistingNetworks*/)
+ .containsDisallowedReasons()).isTrue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
index ebfc41a..7795e42 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -53,6 +53,7 @@
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation;
import android.telephony.Annotation.DataFailureCause;
+import android.telephony.CarrierConfigManager;
import android.telephony.DataFailCause;
import android.telephony.DataSpecificRegistrationInfo;
import android.telephony.LteVopsSupportInfo;
@@ -256,12 +257,18 @@
private void setSuccessfulSetupDataResponse(DataServiceManager dsm, int cid,
List<TrafficDescriptor> tds, Qos defaultQos) {
+ setSuccessfulSetupDataResponse(dsm, cid, tds, defaultQos,
+ PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED);
+ }
+
+ private void setSuccessfulSetupDataResponse(DataServiceManager dsm, int cid,
+ List<TrafficDescriptor> tds, Qos defaultQos, int netwokrValidationResult) {
doAnswer(invocation -> {
final Message msg = (Message) invocation.getArguments()[10];
DataCallResponse response = createDataCallResponse(
cid, DataCallResponse.LINK_STATUS_ACTIVE, tds, defaultQos,
- PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED);
+ netwokrValidationResult);
msg.getData().putParcelable("data_call_response", response);
msg.arg1 = DataServiceCallback.RESULT_SUCCESS;
msg.sendToTarget();
@@ -320,39 +327,47 @@
}
private void serviceStateChanged(@Annotation.NetworkType int networkType,
- @NetworkRegistrationInfo.RegistrationState int regState) {
- serviceStateChanged(networkType, regState, null);
+ @NetworkRegistrationInfo.RegistrationState int regState, boolean isNtn) {
+ serviceStateChanged(networkType, regState, null, isNtn);
}
private void serviceStateChanged(@Annotation.NetworkType int networkType,
@NetworkRegistrationInfo.RegistrationState int regState,
- DataSpecificRegistrationInfo dsri) {
- ServiceState ss = new ServiceState();
- ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ DataSpecificRegistrationInfo dsri, boolean isNtn) {
+ doReturn(isNtn).when(mServiceState).isUsingNonTerrestrialNetwork();
+
+ doReturn(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(networkType)
.setRegistrationState(regState)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
.setDataSpecificInfo(dsri)
- .build());
+ .setIsNonTerrestrialNetwork(isNtn)
+ .build()).when(mServiceState)
+ .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ doReturn(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
.setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN)
.setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME)
.setDomain(NetworkRegistrationInfo.DOMAIN_PS)
- .build());
+ .build()).when(mServiceState)
+ .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
- ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+ doReturn(new NetworkRegistrationInfo.Builder()
.setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
.setAccessNetworkTechnology(networkType)
.setRegistrationState(regState)
.setDomain(NetworkRegistrationInfo.DOMAIN_CS)
- .build());
- ss.setDataRoamingFromRegistration(regState
- == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
- doReturn(ss).when(mSST).getServiceState();
- doReturn(ss).when(mPhone).getServiceState();
+ .build()).when(mServiceState)
+ .getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ boolean isRoaming = regState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING;
+ doReturn(isRoaming).when(mServiceState).getDataRoamingFromRegistration();
+ doReturn(isRoaming).when(mServiceState).getDataRoaming();
if (mDataNetworkUT != null) {
mDataNetworkUT.obtainMessage(9/*EVENT_SERVICE_STATE_CHANGED*/).sendToTarget();
@@ -410,9 +425,16 @@
doReturn(FAKE_IMSI).when(mPhone).getSubscriberId();
doReturn(true).when(mDataNetworkController)
.isNetworkRequestExisting(any(TelephonyNetworkRequest.class));
+ doReturn(Set.of(NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_EIMS, NetworkCapabilities.NET_CAPABILITY_XCAP))
+ .when(mDataConfigManager).getForcedCellularTransportCapabilities();
+ doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_ONLY_RESTRICTED)
+ .when(mDataConfigManager).getSatelliteDataSupportMode();
+ doReturn(true).when(mFeatureFlags).carrierEnabledSatelliteFlag();
+ doReturn(true).when(mFeatureFlags).satelliteInternet();
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, false/*isNtn*/);
}
@After
@@ -446,7 +468,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
setSuccessfulSetupDataResponse(
mMockedWwanDataServiceManager, 123, Collections.emptyList(), mDefaultQos);
@@ -551,12 +573,13 @@
.build();
// Out of service
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, dsri);
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, dsri,
+ false/*isNtn*/);
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123);
@@ -597,7 +620,8 @@
.build();
// Out of service
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, dsri);
+ NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, dsri,
+ false/*isNtn*/);
DataCallResponse response = new DataCallResponse.Builder()
.setCause(0)
@@ -646,6 +670,19 @@
// The final network should not have NOT_SUSPENDED because the device is OOS.
assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)).isFalse();
+
+ // Verify recreation triggers notifyDataConnection with new network agent Id.
+ ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
+ ArgumentCaptor.forClass(PreciseDataConnectionState.class);
+
+ // 4 times connecting, connected, data state changed, re-create network agent
+ verify(mPhone, times(4)).notifyDataConnection(pdcsCaptor.capture());
+ List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues();
+ assertThat(pdcsList.get(0).getState()).isEqualTo(TelephonyManager.DATA_CONNECTING);
+ assertThat(pdcsList.get(1).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED);
+ assertThat(pdcsList.get(2).getState()).isEqualTo(TelephonyManager.DATA_SUSPENDED);
+ assertThat(pdcsList.get(3).getNetId())
+ .isNotEqualTo(pdcsList.get(2).getNetId());
}
@Test
@@ -653,7 +690,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123);
mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
@@ -742,7 +779,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
List<TrafficDescriptor> tds = List.of(
new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -777,7 +814,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
List<TrafficDescriptor> tds = List.of(
new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -810,7 +847,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
List<TrafficDescriptor> tds = List.of(
new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -843,7 +880,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
List<TrafficDescriptor> tds = List.of(
new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -877,7 +914,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
List<TrafficDescriptor> tds = List.of(
new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -962,7 +999,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 123);
@@ -1183,7 +1220,7 @@
TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
networkRequestList.add(networkRequest);
SimulatedCommands simulatedCommands2 = mock(SimulatedCommands.class);
@@ -1225,6 +1262,29 @@
}
@Test
+ public void testNetworkRequestDetachedBeforeConnected() throws Exception {
+ doReturn(true).when(mFeatureFlags).keepEmptyRequestsNetwork();
+ NetworkRequestList networkRequestList = new NetworkRequestList(new TelephonyNetworkRequest(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
+ .build(), mPhone, mFeatureFlags));
+ mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
+ mDataServiceManagers, mImsDataProfile, networkRequestList,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN, DataAllowedReason.NORMAL,
+ mDataNetworkCallback);
+ replaceInstance(DataNetwork.class, "mDataCallSessionStats",
+ mDataNetworkUT, mDataCallSessionStats);
+
+ // Remove the request before the network connect.
+ mDataNetworkUT.detachNetworkRequest(networkRequestList.getFirst(), false/*should retry*/);
+ setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123);
+ processAllMessages();
+
+ // Verify the request proceed to connected state even without requests.
+ assertThat(mDataNetworkUT.isConnected()).isTrue();
+ }
+
+ @Test
public void testAdminAndOwnerUids() throws Exception {
doReturn(ADMIN_UID2).when(mCarrierPrivilegesTracker).getCarrierServicePackageUid();
setupDataNetwork();
@@ -1238,7 +1298,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123);
@@ -1335,7 +1395,7 @@
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
// Data disabled
doReturn(false).when(mDataSettingsManager).isDataEnabled();
@@ -1371,14 +1431,14 @@
@Test
public void testRestrictedNetworkDataRoamingEnabled() throws Exception {
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING);
+ NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING, false/*isNtn*/);
NetworkRequestList networkRequestList = new NetworkRequestList();
// Restricted network request
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
// Data roaming disabled
doReturn(false).when(mDataSettingsManager).isDataRoamingEnabled();
@@ -1516,7 +1576,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
mDataServiceManagers, mInternetDataProfile, networkRequestList,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
@@ -1620,7 +1680,7 @@
LteVopsSupportInfo.LTE_STATUS_SUPPORTED))
.build();
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri, false/*isNtn*/);
assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_MMTEL)).isTrue();
@@ -1634,7 +1694,7 @@
.build();
logd("Trigger non VoPS");
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri, false/*isNtn*/);
// MMTEL should not be removed.
assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_MMTEL)).isTrue();
@@ -1651,7 +1711,7 @@
LteVopsSupportInfo.LTE_STATUS_SUPPORTED))
.build();
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri, false/*isNtn*/);
assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_MMTEL)).isTrue();
@@ -1665,7 +1725,7 @@
.build();
logd("Trigger non VoPS");
serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
- NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri);
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri, false/*isNtn*/);
// MMTEL should be removed to reflect the actual Vops status.
assertThat(mDataNetworkUT.getNetworkCapabilities().hasCapability(
NetworkCapabilities.NET_CAPABILITY_MMTEL)).isFalse();
@@ -1724,7 +1784,7 @@
TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder().addCapability(
- NetworkCapabilities.NET_CAPABILITY_SUPL).build(), mPhone);
+ NetworkCapabilities.NET_CAPABILITY_SUPL).build(), mPhone, mFeatureFlags);
mDataNetworkUT.attachNetworkRequests(new NetworkRequestList(networkRequest));
processAllMessages();
@@ -1747,7 +1807,7 @@
TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder().addCapability(
- NetworkCapabilities.NET_CAPABILITY_SUPL).build(), mPhone);
+ NetworkCapabilities.NET_CAPABILITY_SUPL).build(), mPhone, mFeatureFlags);
mDataNetworkUT.attachNetworkRequests(new NetworkRequestList(networkRequest));
processAllMessages();
@@ -1900,7 +1960,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
mDataServiceManagers, mInternetDataProfile, networkRequestList,
@@ -2044,7 +2104,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
mDataServiceManagers, m5gDataProfile, networkRequestList,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN, DataAllowedReason.NORMAL,
@@ -2141,7 +2201,7 @@
NetworkRequest.Builder builder = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL);
- networkRequestList.add(new TelephonyNetworkRequest(builder.build(), mPhone));
+ networkRequestList.add(new TelephonyNetworkRequest(builder.build(), mPhone, mFeatureFlags));
mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
mDataServiceManagers, mImsDataProfile, networkRequestList,
AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
@@ -2237,6 +2297,51 @@
.isEqualTo(PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED);
}
+ @Test
+ public void testHandoverWithSuccessNetworkValidation_FlagEnabled() throws Exception {
+ when(mFeatureFlags.networkValidation()).thenReturn(true);
+
+ setupDataNetwork();
+
+ setSuccessfulSetupDataResponse(
+ mMockedWlanDataServiceManager, 456, Collections.emptyList(), null,
+ PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS);
+ TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
+ replaceInstance(DataNetwork.class, "mNetworkAgent",
+ mDataNetworkUT, mockNetworkAgent);
+ // Now handover to IWLAN
+ mDataNetworkUT.startHandover(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, null);
+ processAllMessages();
+
+ verify(mMockedWwanDataServiceManager).startHandover(eq(123), any(Message.class));
+ verify(mLinkBandwidthEstimator).unregisterCallback(any(
+ LinkBandwidthEstimatorCallback.class));
+ assertThat(mDataNetworkUT.getTransport())
+ .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+ assertThat(mDataNetworkUT.getId()).isEqualTo(456);
+ verify(mDataNetworkCallback).onHandoverSucceeded(eq(mDataNetworkUT));
+
+ ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor =
+ ArgumentCaptor.forClass(PreciseDataConnectionState.class);
+ verify(mPhone, times(4)).notifyDataConnection(pdcsCaptor.capture());
+ List<PreciseDataConnectionState> pdcsList = pdcsCaptor.getAllValues();
+
+ assertThat(pdcsList).hasSize(4);
+ assertThat(pdcsList.get(0).getState()).isEqualTo(TelephonyManager.DATA_CONNECTING);
+ assertThat(pdcsList.get(1).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED);
+ assertThat(pdcsList.get(1).getNetworkValidationStatus())
+ .isEqualTo(PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED);
+ assertThat(pdcsList.get(2).getState())
+ .isEqualTo(TelephonyManager.DATA_HANDOVER_IN_PROGRESS);
+ assertThat(pdcsList.get(2).getNetworkValidationStatus())
+ .isEqualTo(PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED);
+ assertThat(pdcsList.get(3).getState()).isEqualTo(TelephonyManager.DATA_CONNECTED);
+ assertThat(pdcsList.get(3).getNetworkValidationStatus())
+ .isEqualTo(PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS);
+
+ verify(mDataNetworkCallback).onHandoverSucceeded(eq(mDataNetworkUT));
+ }
+
private void setupIwlanDataNetwork() throws Exception {
// setup iwlan data network over ims
doReturn(mIwlanNetworkRegistrationInfo).when(mServiceState).getNetworkRegistrationInfo(
@@ -2248,7 +2353,7 @@
NetworkRequestList networkRequestList = new NetworkRequestList();
networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .build(), mPhone));
+ .build(), mPhone, mFeatureFlags));
setSuccessfulSetupDataResponse(mMockedWlanDataServiceManager, 123);
mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
mDataServiceManagers, mImsDataProfile, networkRequestList,
@@ -2264,7 +2369,7 @@
NetworkRequest.Builder builder = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
if (isMmtel) builder.addCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL);
- networkRequestList.add(new TelephonyNetworkRequest(builder.build(), mPhone));
+ networkRequestList.add(new TelephonyNetworkRequest(builder.build(), mPhone, mFeatureFlags));
setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123);
@@ -2277,6 +2382,40 @@
processAllMessages();
}
+ private void setupNonTerrestrialDataNetwork() {
+ doReturn(true).when(mServiceState).isUsingNonTerrestrialNetwork();
+ NetworkRequestList networkRequestList = new NetworkRequestList();
+
+ networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+ .build(), mPhone, mFeatureFlags));
+ setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123);
+
+ mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
+ mDataServiceManagers, mInternetDataProfile, networkRequestList,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ DataAllowedReason.NORMAL, mDataNetworkCallback);
+ processAllMessages();
+
+ assertThat(mDataNetworkUT.isSatellite()).isTrue();
+ }
+
+ private void setupTerrestrialDataNetwork() {
+ NetworkRequestList networkRequestList = new NetworkRequestList();
+ networkRequestList.add(new TelephonyNetworkRequest(new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build(), mPhone, mFeatureFlags));
+ setSuccessfulSetupDataResponse(mMockedWwanDataServiceManager, 123);
+
+ mDataNetworkUT = new DataNetwork(mPhone, mFeatureFlags, Looper.myLooper(),
+ mDataServiceManagers, mInternetDataProfile, networkRequestList,
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
+ DataAllowedReason.NORMAL, mDataNetworkCallback);
+ processAllMessages();
+ }
+
@Test
public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception {
doReturn(true).when(mFeatureFlags).forceIwlanMms();
@@ -2293,6 +2432,32 @@
// Now QNS prefers MMS on IWLAN
doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).when(mAccessNetworksManager)
.getPreferredTransportByNetworkCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+ // Verify an mms apn that shares the same apn name doesn't count as an alternative.
+ ApnSetting mmsApnWithSameApn = new ApnSetting.Builder()
+ .setId(2164)
+ .setOperatorNumeric("12345")
+ .setEntryName("fake_mms_apn")
+ .setApnName("fake_apn")
+ .setApnTypeBitmask(ApnSetting.TYPE_MMS)
+ .setProtocol(ApnSetting.PROTOCOL_IPV6)
+ .setRoamingProtocol(ApnSetting.PROTOCOL_IP)
+ .setCarrierEnabled(true)
+ .setNetworkTypeBitmask((int) TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN)
+ .build();
+ doReturn(new DataProfile.Builder().setApnSetting(mmsApnWithSameApn)
+ .setTrafficDescriptor(new TrafficDescriptor("fake_apn", null))
+ .build()).when(mDataProfileManager).getDataProfileForNetworkRequest(
+ any(TelephonyNetworkRequest.class),
+ eq(TelephonyManager.NETWORK_TYPE_IWLAN), eq(false), eq(false), eq(false));
+ accessNetworksManagerCallbackArgumentCaptor.getValue()
+ .onPreferredTransportChanged(NetworkCapabilities.NET_CAPABILITY_MMS, false);
+ processAllMessages();
+
+ // Check if MMS capability remains intact.
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue();
+
+ // Verify MMS capability is removed if using a valid MMS alternative APN.
doReturn(mMmsDataProfile).when(mDataProfileManager).getDataProfileForNetworkRequest(
any(TelephonyNetworkRequest.class),
eq(TelephonyManager.NETWORK_TYPE_IWLAN), eq(false), eq(false), eq(false));
@@ -2355,4 +2520,140 @@
verify(mDataNetworkCallback).onQosSessionsChanged(newQosSessions);
}
+
+ @Test
+ public void testUnrestrictedSatelliteNetworkCapabilities() {
+ setupNonTerrestrialDataNetwork();
+ assertThat(mDataNetworkUT.isSatellite()).isTrue();
+
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isFalse();
+
+ // Test constrained traffic
+ doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_BANDWIDTH_CONSTRAINED)
+ .when(mDataConfigManager).getSatelliteDataSupportMode();
+ mDataNetworkUT.sendMessage(22/*EVENT_VOICE_CALL_STARTED*/); // update network capabilities
+ processAllMessages();
+
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isTrue();
+ try {
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)).isFalse();
+ } catch (Exception ignored) { }
+
+ // Test not constrained traffic
+ doReturn(CarrierConfigManager.SATELLITE_DATA_SUPPORT_ALL)
+ .when(mDataConfigManager).getSatelliteDataSupportMode();
+ mDataNetworkUT.sendMessage(22/*EVENT_VOICE_CALL_STARTED*/); // update network capabilities
+ processAllMessages();
+
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)).isTrue();
+ // TODO(enable after NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED become a default cap)
+// try {
+// assertThat(mDataNetworkUT.getNetworkCapabilities()
+// .hasCapability(DataUtils.NET_CAPABILITY_NOT_BANDWIDTH_CONSTRAINED)).isTrue();
+// } catch (Exception ignored) {}
+ }
+
+ @Test
+ public void testIsTransportSatelliteSupportNonImsNonTerrestrialNetwork() throws Exception {
+ // Service state at Non-terrestrial network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, true/*isNtn*/);
+
+ // set up data network with transport type satellite + Internet
+ setupNonTerrestrialDataNetwork();
+
+ //Check now transport type for the data network is satellite
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)).isTrue();
+ }
+
+ @Test
+ public void testIsTransportSatelliteSupportWithImsNonTerrestrialNetwork() throws Exception {
+ // Service state at Non-terrestrial network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, true/*isNtn*/);
+
+ // set up data network with transport type satellite + IMS
+ createImsDataNetwork(false/*isMmtel*/);
+
+ //Check transport type for the data network is Cellular for Ims at non-terrestrial network
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
+ }
+
+ @Test
+ public void testSatelliteTransportSupportedNonImsTerrestrialToNonTerrestrial()
+ throws Exception {
+ // Service state at terrestrial network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, false/*isNtn*/);
+
+ // set up data network with transport type cellular + Internet
+ setupTerrestrialDataNetwork();
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
+
+ // Service State change terrestrial to non-terrestrial
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, true/*isNtn*/);
+
+ // Make sure transport type for the data network is still Cellular
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)).isFalse();
+
+ // Disconnect the Data call
+ mDataNetworkUT.sendMessage(19/*EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE*/, 0/*Success*/);
+ processAllMessages();
+
+ // set up data network with transport type satellite + Internet
+ setupNonTerrestrialDataNetwork();
+
+ //Check now transport type for the data network is satellite
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)).isTrue();
+ }
+
+ @Test
+ public void testSatelliteTransportSupportedNonImsNonTerrestrialToTerrestrial()
+ throws Exception {
+ // Service state at non-terrestrial network
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, true/*isNtn*/);
+
+ // set up data network with transport type satellite + Internet
+ setupNonTerrestrialDataNetwork();
+
+ //Check now transport type for the data network is satellite
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)).isTrue();
+
+ // Service State change non-terrestrial to terrestrial
+ serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME, false/*isNtn*/);
+
+ // Make sure transport type for the data network is still satellite
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_SATELLITE)).isTrue();
+
+ // Make sure transport type for the data network is not cellular
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isFalse();
+
+ // Disconnect the Data call
+ mDataNetworkUT.sendMessage(19/*EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE*/, 0/*Success*/);
+ processAllMessages();
+
+ // set up data network with transport type cellular + Internet
+ setupTerrestrialDataNetwork();
+
+ //Check now transport type for the data network is cellular
+ assertThat(mDataNetworkUT.getNetworkCapabilities()
+ .hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
index 44d207d..30ce46f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataProfileManagerTest.java
@@ -888,7 +888,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataProfile dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
@@ -899,7 +899,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)
.build();
- tnr = new TelephonyNetworkRequest(request, mPhone);
+ tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
@@ -909,7 +909,7 @@
request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
.build();
- tnr = new TelephonyNetworkRequest(request, mPhone);
+ tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dp.canSatisfy(tnr.getCapabilities())).isTrue();
@@ -918,7 +918,7 @@
request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
.build();
- tnr = new TelephonyNetworkRequest(request, mPhone);
+ tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dp).isNull();
@@ -931,7 +931,7 @@
request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
.build();
- tnr = new TelephonyNetworkRequest(request, mPhone);
+ tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_NR, false, false , false);
assertThat(dp.canSatisfy(tnr.getCapabilities())).isTrue();
@@ -943,7 +943,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataProfile dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_GSM, false, false, false);
// Should not find data profile due to RAT incompatible.
@@ -955,7 +955,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN);
@@ -973,7 +973,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting()).isNull();
@@ -986,7 +986,7 @@
tnr = new TelephonyNetworkRequest(new NetworkRequest(new NetworkCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.addEnterpriseId(2), ConnectivityManager.TYPE_NONE,
- 0, NetworkRequest.Type.REQUEST), mPhone);
+ 0, NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting()).isNull();
@@ -1002,7 +1002,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting()).isNull();
@@ -1018,7 +1018,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting()).isNull();
@@ -1036,7 +1036,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataProfile dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_LTE, true, false, false);
@@ -1050,7 +1050,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN);
@@ -1090,7 +1090,7 @@
TelephonyNetworkRequest dunTnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dunDataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
dunTnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
DataNetwork dunInternetNetwork = Mockito.mock(DataNetwork.class);
@@ -1119,6 +1119,97 @@
}
@Test
+ public void testSetPreferredDataProfileBySubscriptionId() {
+ // NetworkRequest.
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build(), mPhone, mFeatureFlags);
+ // DataNetwork for internet
+ DataNetwork internetNetwork = Mockito.mock(DataNetwork.class);
+
+ // Step 1. With sudId 1, connect to internet and set as prefer APN.
+ // Test for SubId 1.
+ doReturn(1).when(mPhone).getSubId();
+
+ // Sim Loaded and loads profiles.
+ changeSimStateTo(TelephonyManager.SIM_STATE_LOADED);
+ mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
+ processAllMessages();
+
+ // Find DataProfile based on network request
+ DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
+ tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
+ assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN);
+ dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
+
+ // Connected to internet. At this time, This test expects that dataProfile is stored in
+ // mLastInternetDataProfiles for subid 1.
+ doReturn(dataProfile).when(internetNetwork).getDataProfile();
+ doReturn(new DataNetworkController.NetworkRequestList(List.of(tnr)))
+ .when(internetNetwork).getAttachedNetworkRequestList();
+ mDataNetworkControllerCallback.onConnectedInternetDataNetworksChanged(
+ Set.of(internetNetwork));
+ processAllMessages();
+
+ // After internet connected, preferred APN should be set
+ assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
+
+
+ // Step 2. test prefer apn for subId 2.
+ // Test for SubId 2.
+ doReturn(2).when(mPhone).getSubId();
+ // Sim Loaded and loads profiles.
+ changeSimStateTo(TelephonyManager.SIM_STATE_ABSENT);
+ changeSimStateTo(TelephonyManager.SIM_STATE_LOADED);
+ mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
+ processAllMessages();
+
+ // Find DataProfile based on network request
+ dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
+ tnr, TelephonyManager.NETWORK_TYPE_CDMA, false, false, false);
+ assertThat(dataProfile.getApnSetting().getApnName())
+ .isEqualTo(GENERAL_PURPOSE_APN_LEGACY_RAT);
+ dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
+ doReturn(dataProfile).when(internetNetwork).getDataProfile();
+
+ // APN reset
+ mPreferredApnId = -1;
+ mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
+ processAllMessages();
+
+ // Since a new subid has been loaded, preferred APN should be null regardless of the last
+ // internet connection of previous subid.
+ assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isFalse();
+
+
+ // Step 3. try again back to subId 1.
+ // Test for SubId 1.
+ doReturn(1).when(mPhone).getSubId();
+ // Sim Loaded and loads profiles.
+ changeSimStateTo(TelephonyManager.SIM_STATE_ABSENT);
+ changeSimStateTo(TelephonyManager.SIM_STATE_LOADED);
+ mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
+ processAllMessages();
+
+ // Find DataProfile based on network request
+ dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
+ tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
+ assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN);
+ dataProfile.setLastSetupTimestamp(SystemClock.elapsedRealtime());
+ doReturn(dataProfile).when(internetNetwork).getDataProfile();
+
+ // APN reset
+ mPreferredApnId = -1;
+ mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
+ processAllMessages();
+
+ // Since the old subid has been loaded, Even if preferapn for subid 1 is not in the db, the
+ // preferapn can be loaded by mLastInternetDataProfiles
+ assertThat(mDataProfileManagerUT.isDataProfilePreferred(dataProfile)).isTrue();
+ }
+
+ @Test
public void testSetInitialAttachDataProfile() {
ArgumentCaptor<DataProfile> dataProfileCaptor =
ArgumentCaptor.forClass(DataProfile.class);
@@ -1189,7 +1280,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile).isNull();
@@ -1198,7 +1289,7 @@
tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo("sos");
@@ -1207,7 +1298,7 @@
tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile).isEqualTo(null);
@@ -1237,7 +1328,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile).isNull();
@@ -1246,7 +1337,7 @@
tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo("sos");
@@ -1255,7 +1346,7 @@
tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile).isEqualTo(null);
@@ -1291,7 +1382,7 @@
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .build(), mPhone),
+ .build(), mPhone, mFeatureFlags),
TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(IMS_APN);
}
@@ -1301,7 +1392,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
// This should get the merged data profile after deduping.
DataProfile dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
@@ -1439,7 +1530,7 @@
public void testDefaultEmergencyDataProfileValid() {
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
@@ -1456,7 +1547,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(GENERAL_PURPOSE_APN);
@@ -1522,7 +1613,7 @@
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
changeSimStateTo(TelephonyManager.SIM_STATE_LOADED);
mDataProfileManagerUT.obtainMessage(2 /*EVENT_APN_DATABASE_CHANGED*/).sendToTarget();
processAllMessages();
@@ -1828,7 +1919,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataProfile dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
@@ -1852,7 +1943,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataProfile dp = mDataProfileManagerUT.getDataProfileForNetworkRequest(tnr,
TelephonyManager.NETWORK_TYPE_LTE, false, false, false);
@@ -1883,7 +1974,7 @@
// Verify the we can get the previously permanent failed data profile again.
assertThat(mDataProfileManagerUT.getDataProfileForNetworkRequest(
- new TelephonyNetworkRequest(request, mPhone),
+ new TelephonyNetworkRequest(request, mPhone, mFeatureFlags),
TelephonyManager.NETWORK_TYPE_LTE, false, false, false))
.isNotNull();
}
@@ -1902,7 +1993,7 @@
// flag is enabled at data profile, during esim bootstrap provisioning
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, true, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(
@@ -1912,7 +2003,7 @@
// is enabled at data profile, during esim bootstrap provisioning
tnr = new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, true, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo("IMS_APN");
@@ -1921,7 +2012,7 @@
// is disabled at data profile, during esim bootstrap provisioning
tnr = new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, true, false);
assertThat(dataProfile).isEqualTo(null);
@@ -1930,7 +2021,7 @@
// is disabled at data profile, during esim bootstrap provisioning
tnr = new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, true, false);
assertThat(dataProfile).isEqualTo(null);
@@ -1950,7 +2041,7 @@
// type
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, false, true, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(
@@ -1972,7 +2063,7 @@
// type
TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile dataProfile = mDataProfileManagerUT.getDataProfileForNetworkRequest(
tnr, TelephonyManager.NETWORK_TYPE_LTE, true, true, false);
assertThat(dataProfile.getApnSetting().getApnName()).isEqualTo(RCS_APN1);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
index 2541bd1..acfa16d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataRetryManagerTest.java
@@ -292,7 +292,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
mDataRetryManagerUT.evaluateDataSetupRetry(mDataProfile1,
@@ -316,7 +316,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
mDataRetryManagerUT.evaluateDataSetupRetry(mDataProfile3,
@@ -345,7 +345,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
mDataRetryManagerUT.evaluateDataSetupRetry(mDataProfile3,
@@ -432,7 +432,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
@@ -507,17 +507,38 @@
// Test: cancelPendingHandoverRetry
DataNetwork mockDn = Mockito.mock(DataNetwork.class);
+ NetworkRequest request = new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
+ .build();
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
+ DataNetworkController.NetworkRequestList
+ networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
+ doReturn(networkRequestList).when(mockDn).getAttachedNetworkRequestList();
+ doReturn(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).when(mockDn).getTransport();
+ doReturn(mDataProfile3).when(mockDn).getDataProfile();
Field field = DataRetryManager.class.getDeclaredField("mDataRetryEntries");
field.setAccessible(true);
List<DataRetryEntry> mDataRetryEntries =
(List<DataRetryEntry>) field.get(mDataRetryManagerUT);
- retry = new DataHandoverRetryEntry.Builder<>()
- .setDataNetwork(mockDn)
- .build();
- mDataRetryEntries.add(retry);
- mDataRetryManagerUT.cancelPendingHandoverRetry(mockDn);
+ mDataRetryManagerUT.evaluateDataHandoverRetry(mockDn, 123, 1000);
processAllMessages();
+ mDataRetryManagerUT.cancelPendingHandoverRetry(mockDn);
+ Mockito.clearInvocations(mDataRetryManagerCallbackMock);
+ processAllMessages();
+ retry = mDataRetryEntries.get(mDataRetryEntries.size() - 1);
+ ArgumentCaptor<List<ThrottleStatus>> throttleStatusCaptor =
+ ArgumentCaptor.forClass(List.class);
+ verify(mDataRetryManagerCallbackMock).onThrottleStatusChanged(
+ throttleStatusCaptor.capture());
+ assertThat(throttleStatusCaptor.getValue()).hasSize(1);
+ ThrottleStatus throttleStatus = throttleStatusCaptor.getValue().get(0);
+ assertThat(throttleStatus.getApnType()).isEqualTo(ApnSetting.TYPE_IMS);
+ assertThat(throttleStatus.getRetryType())
+ .isEqualTo(ThrottleStatus.RETRY_TYPE_HANDOVER);
+ assertThat(throttleStatus.getThrottleExpiryTimeMillis()).isEqualTo(-1);
+ assertThat(throttleStatus.getTransportType())
+ .isEqualTo(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
assertThat(mDataRetryManagerUT.isAnyHandoverRetryScheduled(mockDn)).isFalse();
assertThat(retry.getState()).isEqualTo(DataRetryEntry.RETRY_STATE_CANCELLED);
}
@@ -535,7 +556,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
mDataRetryManagerUT.evaluateDataSetupRetry(mDataProfile1,
@@ -568,7 +589,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
@@ -647,7 +668,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
@@ -709,7 +730,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
@@ -798,7 +819,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
mDataRetryManagerUT.evaluateDataSetupRetry(mDataProfile1,
@@ -839,7 +860,7 @@
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
- TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone);
+ TelephonyNetworkRequest tnr = new TelephonyNetworkRequest(request, mPhone, mFeatureFlags);
DataNetworkController.NetworkRequestList
networkRequestList = new DataNetworkController.NetworkRequestList(tnr);
@@ -853,7 +874,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
assertThat(mDataRetryManagerUT.isSimilarNetworkRequestRetryScheduled(tnr,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN)).isTrue();
assertThat(mDataRetryManagerUT.isSimilarNetworkRequestRetryScheduled(tnr,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataUtilsTest.java
index ea8a7d7..38de618 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataUtilsTest.java
@@ -18,24 +18,32 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.DataNetworkController.NetworkRequestList;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mockito;
import java.util.List;
public class DataUtilsTest extends TelephonyTest {
+ private FeatureFlags mFeatureFlags;
+
@Before
public void setUp() throws Exception {
logd("DataUtilsTest +Setup!");
super.setUp(getClass().getSimpleName());
+ mFeatureFlags = Mockito.mock(FeatureFlags.class);
+ doReturn(true).when(mFeatureFlags).satelliteInternet();
logd("DataUtilsTest -Setup!");
}
@@ -57,10 +65,13 @@
NetworkCapabilities.NET_CAPABILITY_ENTERPRISE,
NetworkCapabilities.NET_CAPABILITY_ENTERPRISE,
NetworkCapabilities.NET_CAPABILITY_ENTERPRISE,
+ NetworkCapabilities.NET_CAPABILITY_IMS,
+ NetworkCapabilities.NET_CAPABILITY_IMS,
};
int requestId = 0;
int enterpriseId = 1;
+ int transportType = NetworkCapabilities.TRANSPORT_CELLULAR;
TelephonyNetworkRequest networkRequest;
for (int netCap : netCaps) {
if (netCap == NetworkCapabilities.NET_CAPABILITY_ENTERPRISE) {
@@ -69,24 +80,31 @@
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.addEnterpriseId(enterpriseId).build(), -1, requestId++,
- NetworkRequest.Type.REQUEST), mPhone);
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
if (enterpriseId == 1) enterpriseId++;
+ } else if (netCap == NetworkCapabilities.NET_CAPABILITY_IMS) {
+ networkRequest = new TelephonyNetworkRequest(new NetworkRequest(
+ new NetworkCapabilities.Builder()
+ .addTransportType(transportType)
+ .addCapability(netCap).build(), -1, requestId++,
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
+ transportType = NetworkCapabilities.TRANSPORT_SATELLITE;
} else {
networkRequest = new TelephonyNetworkRequest(new NetworkRequest(
new NetworkCapabilities.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.addCapability(netCap).build(), -1, requestId++,
- NetworkRequest.Type.REQUEST), mPhone);
+ NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
}
requestList.add(networkRequest);
}
- assertThat(requestList).hasSize(8);
+ assertThat(requestList).hasSize(10);
List<NetworkRequestList> requestListList =
- DataUtils.getGroupedNetworkRequestList(requestList);
+ DataUtils.getGroupedNetworkRequestList(requestList, mFeatureFlags);
- assertThat(requestListList).hasSize(5);
+ assertThat(requestListList).hasSize(7);
requestList = requestListList.get(0);
assertThat(requestList).hasSize(1);
assertThat(requestList.get(0).hasCapability(
@@ -100,26 +118,40 @@
NetworkCapabilities.NET_CAPABILITY_MMS)).isTrue();
requestList = requestListList.get(2);
- assertThat(requestList).hasSize(2);
+ assertThat(requestList).hasSize(1);
assertThat(requestList.get(0).hasCapability(
- NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue();
- assertThat(requestList.get(1).hasCapability(
- NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue();
+ NetworkCapabilities.NET_CAPABILITY_IMS)).isTrue();
+ assertThat(requestList.get(0).getNativeNetworkRequest().hasTransport(
+ NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
requestList = requestListList.get(3);
assertThat(requestList).hasSize(1);
assertThat(requestList.get(0).hasCapability(
- NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)).isTrue();
- assertThat(requestList.get(0).getCapabilityDifferentiator() == 1).isTrue();
+ NetworkCapabilities.NET_CAPABILITY_IMS)).isTrue();
+ assertThat(requestList.get(0).getNativeNetworkRequest().hasTransport(
+ NetworkCapabilities.TRANSPORT_SATELLITE)).isTrue();
requestList = requestListList.get(4);
assertThat(requestList).hasSize(2);
assertThat(requestList.get(0).hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue();
+ assertThat(requestList.get(1).hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_INTERNET)).isTrue();
+
+ requestList = requestListList.get(5);
+ assertThat(requestList).hasSize(1);
+ assertThat(requestList.get(0).hasCapability(
NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)).isTrue();
- assertThat(requestList.get(0).getCapabilityDifferentiator() == 2).isTrue();
+ assertThat(requestList.get(0).getCapabilityDifferentiator()).isEqualTo(1);
+
+ requestList = requestListList.get(6);
+ assertThat(requestList).hasSize(2);
+ assertThat(requestList.get(0).hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)).isTrue();
+ assertThat(requestList.get(0).getCapabilityDifferentiator()).isEqualTo(2);
assertThat(requestList.get(1).hasCapability(
NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)).isTrue();
- assertThat(requestList.get(1).getCapabilityDifferentiator() == 2).isTrue();
+ assertThat(requestList.get(1).getCapabilityDifferentiator()).isEqualTo(2);
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/LinkBandwidthEstimatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/LinkBandwidthEstimatorTest.java
index d41be7d..dc4a58a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/LinkBandwidthEstimatorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/LinkBandwidthEstimatorTest.java
@@ -43,6 +43,7 @@
import android.net.NetworkCapabilities;
import android.os.Handler;
+import android.os.Looper;
import android.telephony.CellIdentityLte;
import android.telephony.ModemActivityInfo;
import android.telephony.NetworkRegistrationInfo;
@@ -116,7 +117,7 @@
when(mPhone.getSubId()).thenReturn(1);
when(mSignalStrength.getDbm()).thenReturn(-100);
when(mSignalStrength.getLevel()).thenReturn(1);
- mLBE = new LinkBandwidthEstimator(mPhone, mTelephonyFacade);
+ mLBE = new LinkBandwidthEstimator(mPhone, Looper.myLooper(), mTelephonyFacade);
mLBE.obtainMessage(MSG_DEFAULT_NETWORK_CHANGED, mNetworkCapabilities).sendToTarget();
mLBE.obtainMessage(MSG_SCREEN_STATE_CHANGED, false).sendToTarget();
mLBE.obtainMessage(MSG_ACTIVE_PHONE_CHANGED, 1).sendToTarget();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
index e011a60..2a1fedb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -23,9 +23,12 @@
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_SUCCESS;
import static android.telephony.TelephonyManager.SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED;
import static android.telephony.TelephonyManager.SIM_STATE_LOADED;
+import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED;
+import static android.telephony.ims.RegistrationManager.REGISTRATION_STATE_REGISTERED;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_CROSS_SIM;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
+import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
import static com.android.internal.telephony.data.AutoDataSwitchController.EVALUATION_REASON_VOICE_CALL_END;
import static com.android.internal.telephony.data.PhoneSwitcher.ECBM_DEFAULT_DATA_SWITCH_BASE_TIME_MS;
@@ -42,6 +45,7 @@
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -73,6 +77,7 @@
import androidx.test.filters.SmallTest;
+import com.android.ims.ImsException;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.CommandsInterface;
@@ -84,6 +89,8 @@
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.imsphone.ImsPhone;
+import com.android.internal.telephony.imsphone.ImsPhoneCall;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import org.junit.After;
@@ -126,6 +133,7 @@
private ISetOpportunisticDataCallback mSetOpptDataCallback1;
private ISetOpportunisticDataCallback mSetOpptDataCallback2;
PhoneSwitcher.ImsRegTechProvider mMockImsRegTechProvider;
+ PhoneSwitcher.ImsRegisterCallback mMockImsRegisterCallback;
private SubscriptionInfo mSubscriptionInfo;
private ISub mMockedIsub;
private AutoDataSwitchController mAutoDataSwitchController;
@@ -167,6 +175,7 @@
mSetOpptDataCallback1 = mock(ISetOpportunisticDataCallback.class);
mSetOpptDataCallback2 = mock(ISetOpportunisticDataCallback.class);
mMockImsRegTechProvider = mock(PhoneSwitcher.ImsRegTechProvider.class);
+ mMockImsRegisterCallback = mock(PhoneSwitcher.ImsRegisterCallback.class);
mSubscriptionInfo = mock(SubscriptionInfo.class);
mMockedIsub = mock(ISub.class);
mAutoDataSwitchController = mock(AutoDataSwitchController.class);
@@ -221,8 +230,8 @@
NetworkRequest internetNetworkRequest = addInternetNetworkRequest(null, 50);
assertFalse("phone active after request", mPhoneSwitcherUT
- .shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetNetworkRequest, mPhone), 0));
+ .shouldApplyNetworkRequest(new TelephonyNetworkRequest(
+ internetNetworkRequest, mPhone, mFeatureFlags), 0));
// not registered yet - shouldn't inc
verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
@@ -628,9 +637,9 @@
// Phone 0 (sub 1) should be activated as it has default data sub.
assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
// Set sub 2 as preferred sub should make phone 1 activated and phone 0 deactivated.
mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, null);
@@ -645,9 +654,9 @@
// switch shouldn't occur due to the higher priority event
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
assertEquals(2, mPhoneSwitcherUT.getAutoSelectedDataSubId());
@@ -657,9 +666,9 @@
assertEquals(2, mPhoneSwitcherUT.getActiveDataSubId());
assertEquals(2, mPhoneSwitcherUT.getAutoSelectedDataSubId());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
}
@Test
@@ -751,13 +760,13 @@
verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
verify(mActivePhoneSwitchHandler, never()).sendMessageAtTime(any(), anyLong());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(mmsRequest, mPhone), 0));
+ new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(mmsRequest, mPhone), 1));
+ new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 1));
// Set sub 2 as preferred sub should make phone 1 preferredDataModem
doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
@@ -773,13 +782,13 @@
processAllMessages();
verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(mmsRequest, mPhone), 0));
+ new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 0));
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(mmsRequest, mPhone), 1));
+ new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 1));
clearInvocations(mMockRadioConfig);
clearInvocations(mActivePhoneSwitchHandler);
@@ -796,13 +805,13 @@
processAllMessages();
verify(mActivePhoneSwitchHandler, times(2)).sendMessageAtTime(any(), anyLong());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(mmsRequest, mPhone), 0));
+ new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(mmsRequest, mPhone), 1));
+ new TelephonyNetworkRequest(mmsRequest, mPhone, mFeatureFlags), 1));
// SetDataAllowed should never be triggered.
verify(mCommandsInterface0, never()).setDataAllowed(anyBoolean(), any());
@@ -871,6 +880,11 @@
mPhoneSwitcherUT.mImsRegTechProvider = mMockImsRegTechProvider;
}
+ private void mockImsRegisterCallback(int phoneId) throws ImsException {
+ doNothing().when(mMockImsRegisterCallback).setCallback(any(), eq(phoneId), any(), any());
+ mPhoneSwitcherUT.mImsRegisterCallback = mMockImsRegisterCallback;
+ }
+
@Test
@SmallTest
public void testNonDefaultDataPhoneInCall_ImsCallOnLte_shouldSwitchDds() throws Exception {
@@ -1038,9 +1052,9 @@
setDefaultDataSubId(1);
NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
clearInvocations(mMockRadioConfig);
setAllPhonesInactive();
// Initialization done.
@@ -1050,18 +1064,18 @@
notifyPhoneAsInCall(mPhone2);
verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
// Phone2 has active call, and data is on. So data switch to it.
doReturn(true).when(mPhone).isUserDataEnabled();
notifyDataEnabled(true);
verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
clearInvocations(mMockRadioConfig);
// Phone2(nDDS) call ended. But Phone1 having cross-SIM call. Don't switch.
@@ -1070,9 +1084,9 @@
notifyPhoneAsInactive(mPhone2);
verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
// Phone(DDS) call ended.
// Honor auto data switch's suggestion: if DDS is OOS, auto switch to Phone2(nDDS).
@@ -1083,9 +1097,9 @@
// verify immediately switch back to DDS upon call ends
verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
// verify the attempt to do auto data switch to Phone2(nDDS)
processAllFutureMessages();
@@ -1098,9 +1112,9 @@
notifyPhoneAsInHoldingCall(mPhone2);
verify(mMockRadioConfig, never()).setPreferredDataModem(anyInt(), any());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
}
@Test
@@ -1115,9 +1129,9 @@
setDefaultDataSubId(1);
NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
clearInvocations(mMockRadioConfig);
setAllPhonesInactive();
// Initialization done.
@@ -1127,17 +1141,17 @@
notifyPhoneAsInCall(mPhone2);
verify(mMockRadioConfig).setPreferredDataModem(eq(1), any());
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
// During the active call, user turns off data, should immediately switch back to DDS
notifyDataEnabled(false);
verify(mMockRadioConfig).setPreferredDataModem(eq(0), any());
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
}
@Test
@@ -1165,16 +1179,16 @@
setDefaultDataSubId(1);
NetworkRequest internetRequest = addInternetNetworkRequest(2, 50);
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
// Restricted network request will should be applied.
internetRequest = addInternetNetworkRequest(2, 50, true);
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
}
@Test
@@ -1518,6 +1532,53 @@
}
@Test
+ public void testSetPreferredDataCallback_voiceCall() throws Exception {
+ doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
+ initialize();
+ setAllPhonesInactive();
+
+ // Phone 0 has sub 1, phone 1 has sub 2.
+ // Sub 1 is default data sub.
+ // Both are active subscriptions are active sub, as they are in both active slots.
+ setSlotIndexToSubId(0, 1);
+ setSlotIndexToSubId(1, 2);
+ setDefaultDataSubId(1);
+ assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
+
+ doReturn(new SubscriptionInfoInternal.Builder(mSubscriptionManagerService
+ .getSubscriptionInfoInternal(2)).setOpportunistic(1).build())
+ .when(mSubscriptionManagerService).getSubscriptionInfoInternal(2);
+
+ // First temporarily switched to the opportunistic sub 2
+ mPhoneSwitcherUT.trySetOpportunisticDataSubscription(2, false, mSetOpptDataCallback1);
+ processAllMessages();
+ mPhoneSwitcherUT.mValidationCallback.onNetworkAvailable(null, 2);
+ processAllMessages();
+ verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
+
+ // Voice call led back to default sub 1
+ doReturn(mImsPhone).when(mPhone).getImsPhone();
+ doReturn(true).when(mPhone).isUserDataEnabled();
+ doReturn(true).when(mDataSettingsManager).isDataEnabled();
+ mockImsRegTech(0, REGISTRATION_TECH_LTE);
+ notifyPhoneAsInCall(mPhone);
+
+ assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
+ assertEquals(2, mPhoneSwitcherUT.getAutoSelectedDataSubId());
+
+ // CBRS set preferred data back to default during the phone call
+ clearInvocations(mSetOpptDataCallback1);
+ mPhoneSwitcherUT.trySetOpportunisticDataSubscription(SubscriptionManager
+ .DEFAULT_SUBSCRIPTION_ID, false, mSetOpptDataCallback1);
+ processAllMessages();
+
+ verify(mSetOpptDataCallback1).onComplete(SET_OPPORTUNISTIC_SUB_SUCCESS);
+ assertEquals(1, mPhoneSwitcherUT.getActiveDataSubId());
+ assertEquals(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ mPhoneSwitcherUT.getAutoSelectedDataSubId());
+ }
+
+ @Test
@SmallTest
public void testMultiSimConfigChange() throws Exception {
doReturn(true).when(mMockRadioConfig).isSetPreferredDataCommandSupported();
@@ -1558,9 +1619,9 @@
setDefaultDataSubId(1);
NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
clearInvocations(mMockRadioConfig);
setAllPhonesInactive();
// Initialization done.
@@ -1599,9 +1660,9 @@
setDefaultDataSubId(1);
NetworkRequest internetRequest = addInternetNetworkRequest(null, 50);
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 0));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 0));
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), 1));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), 1));
clearInvocations(mMockRadioConfig);
setAllPhonesInactive();
// Initialization done.
@@ -1709,6 +1770,101 @@
verify(mCommandsInterface1, never()).setDataAllowed(anyBoolean(), any());
}
+ @Test
+ @SmallTest
+ public void testRegisterForImsRegistrationCallback() throws Exception {
+ initialize();
+ setAllPhonesInactive();
+
+ // Phone 0 has sub 1, phone 1 has sub 2.
+ // Sub 1 is default data sub.
+ // Both are active subscriptions are active sub, as they are in both active slots.
+ setSlotIndexToSubId(0, 1);
+ setSlotIndexToSubId(1, 2);
+ setDefaultDataSubId(1);
+ processAllMessages();
+
+ // Phone 0 should be the default data phoneId.
+ assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
+
+ doReturn(true).when(mPhone).isUserDataEnabled();
+ mockImsRegTech(0, REGISTRATION_TECH_LTE);
+ mockImsRegisterCallback(0);
+ mockImsRegisterCallback(1);
+
+ notifyImsRegistrationTechChange(mPhone);
+
+ // Verify that the callback is re-registered when the IMS registration callback is called.
+ verify(mMockImsRegisterCallback, times(2)).setCallback(any(), anyInt(), any(), any());
+ }
+
+ @Test
+ @SmallTest
+ public void testReceivingImsRegistrationTech() throws Exception {
+ doReturn(true).when(mFeatureFlags).changeMethodOfObtainingImsRegistrationRadioTech();
+
+ // Set up input and output for testing
+ ImsPhone testImsPhone = mock(ImsPhone.class);
+ doReturn(testImsPhone).when(mPhone).getImsPhone();
+ doReturn(testImsPhone).when(mPhone2).getImsPhone();
+ ImsPhoneCall testImsPhoneCall = mock(ImsPhoneCall.class);
+ doReturn(Call.State.IDLE).when(testImsPhoneCall).getState();
+ doReturn(true).when(testImsPhoneCall).isIdle();
+ doReturn(testImsPhoneCall).when(testImsPhone).getForegroundCall();
+ doReturn(testImsPhoneCall).when(testImsPhone).getBackgroundCall();
+ doReturn(testImsPhoneCall).when(testImsPhone).getRingingCall();
+
+ doNothing().when(testImsPhone).registerForImsRegistrationChanges(any(), anyInt(), any());
+
+ initialize();
+ setAllPhonesInactive();
+
+ // Phone 0 has sub 1, phone 1 has sub 2.
+ // Sub 1 is default data sub.
+ // Both are active subscriptions are active sub, as they are in both active slots.
+ setSlotIndexToSubId(0, 1);
+ setSlotIndexToSubId(1, 2);
+ setDefaultDataSubId(1);
+ processAllMessages();
+
+ // Phone 0 should be the default data phoneId.
+ assertEquals(0, mPhoneSwitcherUT.getPreferredDataPhoneId());
+
+ doReturn(true).when(mPhone).isUserDataEnabled();
+ mockImsRegTech(0, REGISTRATION_TECH_NONE);
+ mockImsRegisterCallback(0);
+ mockImsRegisterCallback(1);
+
+ AsyncResult ar = new AsyncResult(null, new ImsPhone.ImsRegistrationRadioTechInfo(
+ 0, REGISTRATION_TECH_LTE, REGISTRATION_STATE_REGISTERED), null);
+ notifyImsRegistrationTechChangeWithAsyncResult(ar);
+
+ // Verify cached IMS registration tech is LTE
+ assertTrue(REGISTRATION_TECH_LTE == mPhoneSwitcherUT.mImsRegistrationRadioTechMap.get(0));
+
+ ar = new AsyncResult(null, new ImsPhone.ImsRegistrationRadioTechInfo(
+ 0, REGISTRATION_TECH_IWLAN, REGISTRATION_STATE_REGISTERED), null);
+ notifyImsRegistrationTechChangeWithAsyncResult(ar);
+
+ // Verify cached IMS registration tech is WiFi
+ assertTrue(REGISTRATION_TECH_IWLAN
+ == mPhoneSwitcherUT.mImsRegistrationRadioTechMap.get(0));
+
+ ar = new AsyncResult(null, new ImsPhone.ImsRegistrationRadioTechInfo(
+ 0, REGISTRATION_TECH_NONE, REGISTRATION_STATE_NOT_REGISTERED), null);
+ notifyImsRegistrationTechChangeWithAsyncResult(ar);
+
+ // Verify cached IMS registration tech is NONE
+ assertTrue(REGISTRATION_TECH_NONE == mPhoneSwitcherUT.mImsRegistrationRadioTechMap.get(0));
+
+ // Verify there is no crash
+ notifyImsRegistrationTechChangeWithAsyncResult(null);
+
+ // Verify that the callback is not re-registered
+ // when the IMS registration callback is called.
+ verify(mMockImsRegisterCallback, never()).setCallback(any(), anyInt(), any(), any());
+ }
+
/* Private utility methods start here */
private void prepareIdealAutoSwitchCondition() {
@@ -1815,6 +1971,12 @@
processAllMessages();
}
+ private void notifyImsRegistrationTechChangeWithAsyncResult(AsyncResult ar) {
+ mPhoneSwitcherUT.sendMessage(
+ mPhoneSwitcherUT.obtainMessage(EVENT_IMS_RADIO_TECH_CHANGED, ar));
+ processAllMessages();
+ }
+
private Message getEcbmRegistration(Phone phone) {
ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
@@ -1862,10 +2024,10 @@
if (defaultDataSub == (i + 1)) {
// sub id is always phoneId+1 for testing
assertTrue(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), i));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), i));
} else {
assertFalse(mPhoneSwitcherUT.shouldApplyNetworkRequest(
- new TelephonyNetworkRequest(internetRequest, mPhone), i));
+ new TelephonyNetworkRequest(internetRequest, mPhone, mFeatureFlags), i));
}
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java
index ad99eaf..e1a0eac 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkFactoryTest.java
@@ -135,7 +135,8 @@
}
private void activatePhoneInPhoneSwitcher(int phoneId, NetworkRequest nr, boolean active) {
- TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest(nr, mPhone);
+ TelephonyNetworkRequest networkRequest =
+ new TelephonyNetworkRequest(nr, mPhone, mFeatureFlags);
doReturn(active).when(mPhoneSwitcher).shouldApplyNetworkRequest(
eq(networkRequest), eq(phoneId));
mTelephonyNetworkFactoryUT.mInternalHandler.sendEmptyMessage(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
index 26a9fde..9f11a3a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/TelephonyNetworkRequestTest.java
@@ -18,6 +18,9 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
@@ -123,7 +126,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build();
TelephonyNetworkRequest internetRequest =
- new TelephonyNetworkRequest(nativeRequest, mPhone);
+ new TelephonyNetworkRequest(nativeRequest, mPhone, mFeatureFlags);
assertThat(internetRequest.getNativeNetworkRequest()).isEqualTo(nativeRequest);
}
@@ -132,11 +135,11 @@
TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
TelephonyNetworkRequest imsRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
assertThat(internetRequest.getPriority()).isEqualTo(20);
assertThat(imsRequest.getPriority()).isEqualTo(40);
@@ -152,7 +155,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
.setNetworkSpecifier(telephonyNetworkSpecifier)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
assertThat(internetRequest.getNetworkSpecifier()).isEqualTo(telephonyNetworkSpecifier);
}
@@ -164,19 +167,13 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
- .build(), mPhone);
- assertThat(internetRequest.getCapabilities()).isEqualTo(
- new int[]{NetworkCapabilities.NET_CAPABILITY_INTERNET,
- NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED,
- NetworkCapabilities.NET_CAPABILITY_TRUSTED,
- NetworkCapabilities.NET_CAPABILITY_NOT_VPN,
- NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED});
+ .build(), mPhone, mFeatureFlags);
+ assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_TRUSTED))
+ .isTrue();
assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN))
.isTrue();
assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET))
.isTrue();
- assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN))
- .isTrue();
assertThat(internetRequest.hasCapability(
NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)).isTrue();
assertThat(internetRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS))
@@ -191,7 +188,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
assertThat(request.getApnTypeNetworkCapability())
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_SUPL);
@@ -200,7 +197,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
assertThat(request.getApnTypeNetworkCapability())
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_FOTA);
@@ -209,7 +206,7 @@
.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
assertThat(request.getApnTypeNetworkCapability())
.isEqualTo(NetworkCapabilities.NET_CAPABILITY_EIMS);
}
@@ -219,7 +216,7 @@
TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
NetworkCapabilities caps = new NetworkCapabilities.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
@@ -233,7 +230,7 @@
TelephonyNetworkRequest rcsRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
caps = new NetworkCapabilities.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
@@ -250,15 +247,15 @@
TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
TelephonyNetworkRequest mmsRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
TelephonyNetworkRequest rcsRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_RCS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile internetDataProfile = new DataProfile.Builder()
.setApnSetting(INTERNET_APN_SETTING)
.build();
@@ -281,12 +278,12 @@
TelephonyNetworkRequest enterpriseRequest1 = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
TelephonyNetworkRequest enterpriseRequest2 = new TelephonyNetworkRequest(
new NetworkRequest(new NetworkCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.addEnterpriseId(2), ConnectivityManager.TYPE_NONE,
- 0, NetworkRequest.Type.REQUEST), mPhone);
+ 0, NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
DataProfile enterpriseDataProfile1 = new DataProfile.Builder()
.setTrafficDescriptor(new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -309,18 +306,18 @@
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
TelephonyNetworkRequest enterpriseRequest2 = new TelephonyNetworkRequest(
new NetworkRequest(new NetworkCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_ENTERPRISE)
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addEnterpriseId(2), ConnectivityManager.TYPE_NONE,
- 0, NetworkRequest.Type.REQUEST), mPhone);
+ 0, NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
TelephonyNetworkRequest internetRequest = new TelephonyNetworkRequest(
new NetworkRequest(new NetworkCapabilities()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET),
ConnectivityManager.TYPE_NONE,
- 0, NetworkRequest.Type.REQUEST), mPhone);
+ 0, NetworkRequest.Type.REQUEST), mPhone, mFeatureFlags);
DataProfile enterpriseDataProfile = new DataProfile.Builder()
.setApnSetting(ENTERPRISE_APN_SETTING)
@@ -342,12 +339,12 @@
TelephonyNetworkRequest urllcRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
TelephonyNetworkRequest embbRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile urllcDataProfile = new DataProfile.Builder()
.setTrafficDescriptor(new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -364,12 +361,12 @@
TelephonyNetworkRequest urllcRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_LATENCY)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
TelephonyNetworkRequest embbRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile embbDataProfile = new DataProfile.Builder()
.setTrafficDescriptor(new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -386,12 +383,12 @@
TelephonyNetworkRequest cbsRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_CBS)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
TelephonyNetworkRequest embbRequest = new TelephonyNetworkRequest(
new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_PRIORITIZE_BANDWIDTH)
- .build(), mPhone);
+ .build(), mPhone, mFeatureFlags);
DataProfile cbsDataProfile = new DataProfile.Builder()
.setTrafficDescriptor(new TrafficDescriptor(null, new TrafficDescriptor.OsAppId(
@@ -402,4 +399,92 @@
assertThat(cbsRequest.canBeSatisfiedBy(cbsDataProfile)).isTrue();
assertThat(embbRequest.canBeSatisfiedBy(cbsDataProfile)).isFalse();
}
+
+ @Test
+ public void testSatelliteNetworkRequest() {
+ when(mFeatureFlags.satelliteInternet()).thenReturn(true);
+ TelephonyNetworkRequest satelliteRequest = new TelephonyNetworkRequest(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .addTransportType(NetworkCapabilities.TRANSPORT_SATELLITE)
+ .build(), mPhone, mFeatureFlags);
+
+ TelephonyNetworkRequest generalRequest = new TelephonyNetworkRequest(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build(), mPhone, mFeatureFlags);
+
+ ApnSetting satelliteInternetApn = new ApnSetting.Builder()
+ .setEntryName("apn")
+ .setApnName("apn")
+ .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
+ .setCarrierEnabled(true)
+ .setInfrastructureBitmask(ApnSetting.INFRASTRUCTURE_SATELLITE)
+ .build();
+
+ ApnSetting cellularInternetApn = new ApnSetting.Builder()
+ .setEntryName("apn")
+ .setApnName("apn")
+ .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
+ .setCarrierEnabled(true)
+ .setInfrastructureBitmask(ApnSetting.INFRASTRUCTURE_CELLULAR)
+ .build();
+
+ DataProfile satelliteInternetDataProfile = new DataProfile.Builder()
+ .setApnSetting(satelliteInternetApn)
+ .build();
+
+ DataProfile cellularInternetDataProfile = new DataProfile.Builder()
+ .setApnSetting(cellularInternetApn)
+ .build();
+
+ assertThat(satelliteRequest.canBeSatisfiedBy(satelliteInternetDataProfile)).isTrue();
+ assertThat(generalRequest.canBeSatisfiedBy(satelliteInternetDataProfile)).isTrue();
+ assertThat(satelliteRequest.canBeSatisfiedBy(cellularInternetDataProfile)).isFalse();
+ assertThat(generalRequest.canBeSatisfiedBy(cellularInternetDataProfile)).isTrue();
+ }
+
+ @Test
+ public void testCellularNetworkRequest() {
+ doReturn(true).when(mFeatureFlags).satelliteInternet();
+ TelephonyNetworkRequest cellularRequest = new TelephonyNetworkRequest(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+ .build(), mPhone, mFeatureFlags);
+
+ TelephonyNetworkRequest generalRequest = new TelephonyNetworkRequest(
+ new NetworkRequest.Builder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+ .build(), mPhone, mFeatureFlags);
+
+ ApnSetting satelliteInternetApn = new ApnSetting.Builder()
+ .setEntryName("apn")
+ .setApnName("apn")
+ .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
+ .setCarrierEnabled(true)
+ .setInfrastructureBitmask(ApnSetting.INFRASTRUCTURE_SATELLITE)
+ .build();
+
+ ApnSetting cellularInternetApn = new ApnSetting.Builder()
+ .setEntryName("apn")
+ .setApnName("apn")
+ .setApnTypeBitmask(ApnSetting.TYPE_DEFAULT)
+ .setCarrierEnabled(true)
+ .setInfrastructureBitmask(ApnSetting.INFRASTRUCTURE_CELLULAR)
+ .build();
+
+ DataProfile satelliteInternetDataProfile = new DataProfile.Builder()
+ .setApnSetting(satelliteInternetApn)
+ .build();
+
+ DataProfile cellularInternetDataProfile = new DataProfile.Builder()
+ .setApnSetting(cellularInternetApn)
+ .build();
+
+ assertThat(cellularRequest.canBeSatisfiedBy(satelliteInternetDataProfile)).isFalse();
+ assertThat(generalRequest.canBeSatisfiedBy(satelliteInternetDataProfile)).isTrue();
+ assertThat(cellularRequest.canBeSatisfiedBy(cellularInternetDataProfile)).isTrue();
+ assertThat(generalRequest.canBeSatisfiedBy(cellularInternetDataProfile)).isTrue();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
index 47f8ce2..5fd7a77 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionConnectionTest.java
@@ -22,6 +22,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@@ -42,8 +43,10 @@
import android.telecom.PhoneAccount;
import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
+import android.telephony.DisconnectCause;
import android.telephony.DomainSelectionService;
import android.telephony.EmergencyRegistrationResult;
+import android.telephony.PreciseDisconnectCause;
import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
import android.testing.AndroidTestingRunner;
@@ -773,6 +776,26 @@
verify(mDomainSelectionController, times(1)).selectDomain(any(), eq(transportCallback));
}
+ @Test
+ @SmallTest
+ public void testSetDisconnectCause() throws Exception {
+ mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
+ mDomainSelectionController);
+
+ assertEquals(DisconnectCause.NOT_VALID, mDsc.getDisconnectCause());
+ assertEquals(PreciseDisconnectCause.NOT_VALID, mDsc.getPreciseDisconnectCause());
+ assertEquals(mPhone.getPhoneId(), mDsc.getPhoneId());
+
+ String reason = "No SIM or SIM error";
+ mDsc.setDisconnectCause(DisconnectCause.ICC_ERROR,
+ PreciseDisconnectCause.NO_VALID_SIM, reason);
+
+ assertEquals(DisconnectCause.ICC_ERROR, mDsc.getDisconnectCause());
+ assertEquals(PreciseDisconnectCause.NO_VALID_SIM, mDsc.getPreciseDisconnectCause());
+ assertEquals(reason, mDsc.getReasonMessage());
+ assertEquals(mPhone.getPhoneId(), mDsc.getPhoneId());
+ }
+
private DomainSelectionConnection createConnection(Phone phone, int selectorType,
boolean isEmergency, DomainSelectionController controller) throws Exception {
DomainSelectionConnection dsc = new DomainSelectionConnection(phone,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java
index f5ccdd6..a55ad69 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/domainselection/DomainSelectionControllerTest.java
@@ -16,8 +16,11 @@
package com.android.internal.telephony.domainselection;
+import static android.telephony.DomainSelectionService.SELECTOR_TYPE_CALLING;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
@@ -36,6 +39,8 @@
import android.os.Looper;
import android.os.RemoteException;
import android.telephony.DomainSelectionService;
+import android.telephony.TelephonyManager;
+import android.test.mock.MockContext;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -71,6 +76,8 @@
}
};
+ Context mTestContext;
+
// Mocked classes
IDomainSelectionServiceController mMockServiceControllerBinder;
Context mMockContext;
@@ -84,9 +91,40 @@
public void setUp() throws Exception {
super.setUp(this.getClass().getSimpleName());
+ when(mTelephonyManager.getSupportedModemCount()).thenReturn(2);
mMockContext = mock(Context.class);
+ mTestContext = new MockContext() {
+ @Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ if (serviceClass == TelephonyManager.class) {
+ return Context.TELEPHONY_SERVICE;
+ }
+ return super.getSystemServiceName(serviceClass);
+ }
+
+ @Override
+ public Object getSystemService(String name) {
+ switch (name) {
+ case (Context.TELEPHONY_SERVICE) : {
+ return mTelephonyManager;
+ }
+ }
+ return super.getSystemService(name);
+ }
+
+ @Override
+ public boolean bindService(Intent service, ServiceConnection conn, int flags) {
+ return mMockContext.bindService(service, conn, flags);
+ }
+
+ @Override
+ public void unbindService(ServiceConnection conn) {
+ mMockContext.unbindService(conn);
+ }
+ };
+
mMockServiceControllerBinder = mock(IDomainSelectionServiceController.class);
- mTestController = new DomainSelectionController(mMockContext,
+ mTestController = new DomainSelectionController(mTestContext,
Looper.getMainLooper(), BIND_RETRY);
mHandler = mTestController.getHandlerForTest();
@@ -264,6 +302,17 @@
verify(mMockContext, times(1)).bindService(any(), any(), anyInt());
}
+ @SmallTest
+ @Test
+ public void testGetDomainSelectionConnection() throws Exception {
+ when(mPhone.getPhoneId()).thenReturn(1);
+ DomainSelectionConnection dsc = mTestController.getDomainSelectionConnection(
+ mPhone, SELECTOR_TYPE_CALLING, false);
+
+ assertNotNull(dsc);
+ assertTrue(dsc instanceof NormalCallDomainSelectionConnection);
+ }
+
private void bindAndNullServiceError() {
ServiceConnection connection = bindService(mTestComponentName);
connection.onNullBinding(mTestComponentName);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
index 3eb7659..f05099d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/EmergencyStateTrackerTest.java
@@ -36,6 +36,7 @@
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyVararg;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -49,10 +50,12 @@
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.PersistableBundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
@@ -69,9 +72,12 @@
import androidx.test.filters.SmallTest;
import com.android.internal.telephony.Call;
+import com.android.internal.telephony.CallStateException;
+import com.android.internal.telephony.Connection;
import com.android.internal.telephony.GsmCdmaPhone;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.data.PhoneSwitcher;
@@ -112,6 +118,9 @@
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
MockitoAnnotations.initMocks(this);
+
+ doReturn(TelephonyManager.SIM_STATE_READY)
+ .when(mTelephonyManagerProxy).getSimState(anyInt());
}
@After
@@ -254,6 +263,46 @@
verify(testPhone).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any());
}
+ @Test
+ @SmallTest
+ public void startEmergencyCall_radioOff_turnOnRadioHangupCallTurnOffRadio() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ true /* isSuplDdsSwitchRequiredForEmergencyCall */);
+ // Create test Phones and set radio off
+ Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ false /* isRadioOn */);
+ setConfigForDdsSwitch(testPhone, null,
+ CarrierConfigManager.Gps.SUPL_EMERGENCY_MODE_TYPE_DP_ONLY, "150");
+ ServiceState ss = mock(ServiceState.class);
+ doReturn(ss).when(mSST).getServiceState();
+ NetworkRegistrationInfo nri = new NetworkRegistrationInfo.Builder()
+ .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+ .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+ .build();
+ doReturn(nri).when(ss).getNetworkRegistrationInfo(anyInt(), anyInt());
+ CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(testPhone,
+ mTestConnection1, false);
+
+ // startEmergencyCall should trigger radio on
+ ArgumentCaptor<RadioOnStateListener.Callback> callback = ArgumentCaptor
+ .forClass(RadioOnStateListener.Callback.class);
+ verify(mRadioOnHelper).triggerRadioOnAndListen(callback.capture(), eq(true), eq(testPhone),
+ eq(false), eq(DEFAULT_WAIT_FOR_IN_SERVICE_TIMEOUT_MS));
+
+ // Hangup the call
+ emergencyStateTracker.endCall(mTestConnection1);
+
+ // onTimeout and isOkToCall should return true even in case radion is off
+ assertTrue(callback.getValue()
+ .isOkToCall(testPhone, ServiceState.STATE_POWER_OFF, false));
+ assertTrue(callback.getValue()
+ .onTimeout(testPhone, ServiceState.STATE_POWER_OFF, false));
+
+ callback.getValue().onComplete(null, true);
+
+ assertFalse(future.isDone());
+ }
+
/**
* Test that if startEmergencyCall fails to turn on radio, then it's future completes with
* DisconnectCause.POWER_OFF.
@@ -571,6 +620,9 @@
assertTrue(emergencyStateTracker.isInEcm());
assertFalse(emergencyStateTracker.isInCdmaEcm());
assertTrue(emergencyStateTracker.isInImsEcm());
+
+ assertTrue(emergencyStateTracker.isInEcm(testPhone));
+ assertFalse(emergencyStateTracker.isInEcm(getPhone(1)));
}
/**
@@ -1106,7 +1158,7 @@
assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_CS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_CS, true);
verify(phone0).exitEmergencyMode(any(Message.class));
assertFalse(emergencyStateTracker.isInEmergencyMode());
@@ -1116,6 +1168,39 @@
@Test
@SmallTest
+ public void testEndSmsForMultipartMessage() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ false,
+ /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(phone0, E_REG_RESULT);
+ CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
+ TEST_SMS_ID, false);
+ processAllMessages();
+
+ assertTrue(emergencyStateTracker.isInEmergencyMode());
+ verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ assertTrue(emergencyStateTracker.getEmergencyRegistrationResult().equals(E_REG_RESULT));
+ // Expect: DisconnectCause#NOT_DISCONNECTED.
+ assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
+ Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
+
+ // First SMS part of multipart message.
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_CS, false);
+
+ // exitEmergencyMode is not called and it's still in emergency mode.
+ assertTrue(emergencyStateTracker.isInEmergencyMode());
+
+ // Last SMS part is sent successfully.
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_CS, true);
+
+ verify(phone0).exitEmergencyMode(any(Message.class));
+ assertFalse(emergencyStateTracker.isInEmergencyMode());
+ }
+
+ @Test
+ @SmallTest
public void testEndSmsAndEnterEmergencySmsCallbackMode() {
EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
/* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
@@ -1134,7 +1219,7 @@
assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
verify(mCarrierConfigManager).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
@@ -1166,7 +1251,7 @@
EmergencyStateTracker.EMERGENCY_TYPE_SMS, MODE_EMERGENCY_WWAN);
// When MO SMS fails while in SCBM.
- emergencyStateTracker.endSms(TEST_SMS_ID_2, false, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID_2, false, DOMAIN_PS, true);
verify(mCarrierConfigManager).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
@@ -1198,7 +1283,7 @@
EmergencyStateTracker.EMERGENCY_TYPE_SMS, MODE_EMERGENCY_WWAN);
// When MO SMS is successfully sent while in SCBM.
- emergencyStateTracker.endSms(TEST_SMS_ID_2, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID_2, true, DOMAIN_PS, true);
verify(mCarrierConfigManager, times(2)).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
@@ -1627,7 +1712,7 @@
Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
assertFalse(emergencyStateTracker.isInScbm());
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
assertTrue(emergencyStateTracker.isInScbm());
assertTrue(emergencyStateTracker.isInEmergencyMode());
@@ -1749,7 +1834,7 @@
assertFalse(smsFuture.isDone());
assertFalse(callFuture.isDone());
- emergencyStateTracker.endSms(TEST_SMS_ID, false, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, false, DOMAIN_PS, true);
// Response message for setEmergencyMode by SMS.
Message msg = smsCaptor.getValue();
@@ -1983,7 +2068,7 @@
assertTrue(emergencyStateTracker.isInEmergencyMode());
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
processAllMessages();
assertFalse(emergencyStateTracker.isInEmergencyMode());
@@ -2020,7 +2105,7 @@
assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
assertTrue(emergencyStateTracker.isInEmergencyMode());
@@ -2067,7 +2152,7 @@
assertTrue(emergencyStateTracker.isInEcm());
assertFalse(emergencyStateTracker.isInEmergencyCall());
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
processAllMessages();
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
@@ -2122,7 +2207,7 @@
emergencyStateTracker.onEmergencyTransportChanged(
EmergencyStateTracker.EMERGENCY_TYPE_SMS, MODE_EMERGENCY_WWAN);
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
processAllMessages();
// Enter emergency callback mode and emergency mode changed by SMS end.
@@ -2171,7 +2256,7 @@
assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
assertTrue(emergencyStateTracker.isInEmergencyMode());
@@ -2227,7 +2312,7 @@
assertFalse(emergencyStateTracker.isInEmergencyCall());
setScbmTimerValue(phone0, TEST_ECM_EXIT_TIMEOUT_MS + 100);
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
processAllMessages();
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
@@ -2289,7 +2374,7 @@
assertFalse(emergencyStateTracker.isInEmergencyCall());
setScbmTimerValue(phone0, TEST_ECM_EXIT_TIMEOUT_MS - 100);
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
processAllMessages();
verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_CALLBACK), any(Message.class));
@@ -2324,6 +2409,8 @@
false /* isRadioOn */);
when(phone.getSubId()).thenReturn(1);
setEcmSupportedConfig(phone, true);
+ PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(phone.getSubId());
+ doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyVararg());
EmergencyStateTracker testEst = setupEmergencyStateTracker(
false /* isSuplDdsSwitchRequiredForEmergencyCall */);
@@ -2344,6 +2431,7 @@
// Verify carrier config for valid subscription
assertTrue(testEst.isEmergencyCallbackModeSupported(phone));
+ // onCarrierConfigurationChanged is not called yet.
// SIM removed
when(phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
setEcmSupportedConfig(phone, false);
@@ -2372,7 +2460,35 @@
// Verify saved config for valid subscription
assertTrue(testEst.isEmergencyCallbackModeSupported(phone));
- // Insert SIM again, but emergency callback mode not supported
+ // Insert SIM in PIN locked again, but emergency callback mode not supported
+ doReturn(TelephonyManager.SIM_STATE_PIN_REQUIRED)
+ .when(mTelephonyManagerProxy).getSimState(anyInt());
+ when(phone.getSubId()).thenReturn(1);
+ setEcmSupportedConfig(phone, false);
+
+ // onCarrierConfigChanged with valid subscription
+ carrierConfigChangeListener.onCarrierConfigChanged(
+ phone.getPhoneId(), phone.getSubId(),
+ TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
+
+ // Verify carrier config for valid subscription in PIN locked state, saved configuration
+ assertTrue(testEst.isEmergencyCallbackModeSupported(phone));
+
+ // SIM removed again
+ when(phone.getSubId()).thenReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+ setEcmSupportedConfig(phone, false);
+
+ // onCarrierConfigChanged with invalid subscription
+ carrierConfigChangeListener.onCarrierConfigChanged(
+ phone.getPhoneId(), phone.getSubId(),
+ TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
+
+ // Verify saved config for valid subscription
+ assertTrue(testEst.isEmergencyCallbackModeSupported(phone));
+
+ // Insert SIM, PIN verified, again, but emergency callback mode not supported
+ doReturn(TelephonyManager.SIM_STATE_READY)
+ .when(mTelephonyManagerProxy).getSimState(anyInt());
when(phone.getSubId()).thenReturn(1);
setEcmSupportedConfig(phone, false);
@@ -2559,6 +2675,502 @@
verify(testPhone).exitEmergencyMode(any(Message.class));
}
+ /**
+ * Test that the EmergencyStateTracker rejects incoming call when starting an emergency call.
+ */
+ @Test
+ @SmallTest
+ public void testRejectRingingCall() {
+ Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ false /* isRadioOn */);
+ when(phone.getSubId()).thenReturn(1);
+ Connection c = mock(Connection.class);
+ Call call = mock(Call.class);
+ doReturn(c).when(call).getLatestConnection();
+ doReturn(Call.State.INCOMING).when(call).getState();
+ doReturn(call).when(phone).getRingingCall();
+ setEcmSupportedConfig(phone, true);
+
+ EmergencyStateTracker testEst = setupEmergencyStateTracker(
+ false /* isSuplDdsSwitchRequiredForEmergencyCall */);
+
+ // There is an ongoing emergency call.
+ CompletableFuture<Integer> future = testEst.startEmergencyCall(phone,
+ mTestConnection1, false);
+
+ assertNotNull(future);
+
+ // Verify rejecting ringing call.
+ try {
+ verify(call).hangup();
+ } catch (CallStateException e) {
+ }
+ }
+
+ /**
+ * Test that the EmergencyStateTracker rejects incoming call if there is an emergency call
+ * in dialing state.
+ */
+ @Test
+ @SmallTest
+ public void testRejectNewIncomingCall() {
+ Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ false /* isRadioOn */);
+ when(phone.getSubId()).thenReturn(1);
+ setEcmSupportedConfig(phone, true);
+
+ EmergencyStateTracker testEst = setupEmergencyStateTracker(
+ false /* isSuplDdsSwitchRequiredForEmergencyCall */);
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(phone).registerForNewRingingConnection(handlerCaptor.capture(),
+ intCaptor.capture(), any());
+ assertNotNull(handlerCaptor.getValue());
+ assertNotNull(intCaptor.getValue());
+
+ // There is an ongoing emergency call.
+ CompletableFuture<Integer> future = testEst.startEmergencyCall(phone,
+ mTestConnection1, false);
+
+ assertNotNull(future);
+
+ Connection c = mock(Connection.class);
+ Call call = mock(Call.class);
+ doReturn(call).when(c).getCall();
+
+ Message msg = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue());
+ AsyncResult.forMessage(msg, c, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ // Verify rejecting incoming call.
+ try {
+ verify(call).hangup();
+ } catch (CallStateException e) {
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void testNotRejectNewIncomingCall() {
+ Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ false /* isRadioOn */);
+ when(phone.getSubId()).thenReturn(1);
+ setEcmSupportedConfig(phone, true);
+
+ EmergencyStateTracker unused = setupEmergencyStateTracker(
+ false /* isSuplDdsSwitchRequiredForEmergencyCall */);
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(phone).registerForNewRingingConnection(handlerCaptor.capture(),
+ intCaptor.capture(), any());
+ assertNotNull(handlerCaptor.getValue());
+ assertNotNull(intCaptor.getValue());
+
+ // There is no ongoing emergency call.
+
+ Connection c = mock(Connection.class);
+ Call call = mock(Call.class);
+ doReturn(call).when(c).getCall();
+
+ Message msg = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue());
+ AsyncResult.forMessage(msg, c, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ // Verify not rejecting incoming call.
+ try {
+ verify(call, never()).hangup();
+ } catch (CallStateException e) {
+ }
+ }
+
+ /**
+ * Test that the EmergencyStateTracker rejects incoming call when starting
+ * a normal routing emergency call.
+ */
+ @Test
+ @SmallTest
+ public void testNormalRoutingEmergencyCallRejectRingingCall() {
+ Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ false /* isRadioOn */);
+ when(phone.getSubId()).thenReturn(1);
+ Connection c = mock(Connection.class);
+ Call call = mock(Call.class);
+ doReturn(c).when(call).getLatestConnection();
+ doReturn(Call.State.DISCONNECTING).when(call).getState();
+ doReturn(call).when(phone).getRingingCall();
+ setEcmSupportedConfig(phone, true);
+
+ EmergencyStateTracker testEst = setupEmergencyStateTracker(
+ false /* isSuplDdsSwitchRequiredForEmergencyCall */);
+
+ // There is an ongoing normal routing emergency call.
+ testEst.startNormalRoutingEmergencyCall(phone, mTestConnection1, result -> {});
+
+ // Verify rejecting ringing call.
+ try {
+ verify(call).hangup();
+ } catch (CallStateException e) {
+ }
+ }
+
+
+ /**
+ * Test that the EmergencyStateTracker rejects incoming call if there is
+ * a normal routing emergency call in dialing state.
+ */
+ @Test
+ @SmallTest
+ public void testNormalRoutingRejectNewIncomingCall() {
+ Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ false /* isRadioOn */);
+ when(phone.getSubId()).thenReturn(1);
+ setEcmSupportedConfig(phone, true);
+
+ EmergencyStateTracker testEst = setupEmergencyStateTracker(
+ false /* isSuplDdsSwitchRequiredForEmergencyCall */);
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(phone).registerForNewRingingConnection(handlerCaptor.capture(),
+ intCaptor.capture(), any());
+ assertNotNull(handlerCaptor.getValue());
+ assertNotNull(intCaptor.getValue());
+
+ // There is an ongoing normal routing emergency call.
+ testEst.startNormalRoutingEmergencyCall(phone, mTestConnection1, result -> {});
+
+ Connection c = mock(Connection.class);
+ Call call = mock(Call.class);
+ doReturn(call).when(c).getCall();
+
+ Message msg = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue());
+ AsyncResult.forMessage(msg, c, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ // Verify rejecting incoming call.
+ try {
+ verify(call).hangup();
+ } catch (CallStateException e) {
+ }
+ }
+
+ @Test
+ @SmallTest
+ public void testNormalRoutingDiscardedNotRejectNewIncomingCall() {
+ Phone phone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ false /* isRadioOn */);
+ when(phone.getSubId()).thenReturn(1);
+ setEcmSupportedConfig(phone, true);
+
+ EmergencyStateTracker testEst = setupEmergencyStateTracker(
+ false /* isSuplDdsSwitchRequiredForEmergencyCall */);
+
+ ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
+ ArgumentCaptor<Integer> intCaptor = ArgumentCaptor.forClass(Integer.class);
+
+ verify(phone).registerForNewRingingConnection(handlerCaptor.capture(),
+ intCaptor.capture(), any());
+ assertNotNull(handlerCaptor.getValue());
+ assertNotNull(intCaptor.getValue());
+
+ // Start normal routing emergency call.
+ testEst.startNormalRoutingEmergencyCall(phone, mTestConnection1, result -> {});
+
+ // Discard normal routing emergency call.
+ testEst.endNormalRoutingEmergencyCall(mTestConnection1);
+
+ Connection c = mock(Connection.class);
+ Call call = mock(Call.class);
+ doReturn(call).when(c).getCall();
+
+ Message msg = Message.obtain(handlerCaptor.getValue(), intCaptor.getValue());
+ AsyncResult.forMessage(msg, c, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ // Verify not rejecting incoming call.
+ try {
+ verify(call, never()).hangup();
+ } catch (CallStateException e) {
+ }
+ }
+
+ /**
+ * Test that emergency call state changes are sent.
+ */
+ @Test
+ @SmallTest
+ public void testSendEmergencyCallStateChanges() {
+ mContextFixture.getCarrierConfigBundle().putBoolean(
+ CarrierConfigManager.KEY_CARRIER_CONFIG_APPLIED_BOOL, true);
+ // Setup EmergencyStateTracker
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ // Create test Phone
+ Phone testPhone = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+ /* isRadioOn= */ true);
+ when(testPhone.getSubId()).thenReturn(1);
+ ArgumentCaptor<CarrierConfigManager.CarrierConfigChangeListener> listenerArgumentCaptor =
+ ArgumentCaptor.forClass(CarrierConfigManager.CarrierConfigChangeListener.class);
+ CarrierConfigManager cfgManager = (CarrierConfigManager) mContext
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+
+ verify(cfgManager).registerCarrierConfigChangeListener(any(),
+ listenerArgumentCaptor.capture());
+
+ CarrierConfigManager.CarrierConfigChangeListener carrierConfigChangeListener =
+ listenerArgumentCaptor.getAllValues().get(0);
+
+ assertNotNull(carrierConfigChangeListener);
+
+ PersistableBundle bundle = mCarrierConfigManager.getConfigForSubId(testPhone.getSubId());
+ bundle.putBoolean(CarrierConfigManager.KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL,
+ true);
+ doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt(), anyVararg());
+ // onCarrierConfigChanged with valid subscription
+ carrierConfigChangeListener.onCarrierConfigChanged(
+ testPhone.getPhoneId(), testPhone.getSubId(),
+ TelephonyManager.UNKNOWN_CARRIER_ID, TelephonyManager.UNKNOWN_CARRIER_ID);
+
+ // Start emergency call
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ mTestConnection1, false);
+
+ // Verify intent is sent that emergency call state is changed
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext, times(1)).sendStickyBroadcastAsUser(
+ intentCaptor.capture(), eq(UserHandle.ALL));
+ Intent intent = intentCaptor.getValue();
+ assertNotNull(intent);
+ assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED, intent.getAction());
+ assertTrue(intent.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, true));
+
+ // End emergency call
+ emergencyStateTracker.endCall(mTestConnection1);
+
+ // Verify intent is sent that emergency call state is changed
+ verify(mContext, times(2)).sendStickyBroadcastAsUser(
+ intentCaptor.capture(), eq(UserHandle.ALL));
+ intent = intentCaptor.getValue();
+ assertNotNull(intent);
+ assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED, intent.getAction());
+ assertFalse(intent.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, false));
+ }
+
+ /**
+ * Test that emergency call state change is reset after crash.
+ */
+ @Test
+ @SmallTest
+ public void testResetEmergencyCallStateChanges() {
+ Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED);
+ intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, true);
+ doReturn(intent).when(mContext).registerReceiver(eq(null), any(),
+ eq(Context.RECEIVER_NOT_EXPORTED));
+ // Setup EmergencyStateTracker
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ emergencyStateTracker.maybeResetEmergencyCallStateChangedIntent();
+
+ ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
+
+ verify(mContext).registerReceiver(eq(null), filterCaptor.capture(),
+ eq(Context.RECEIVER_NOT_EXPORTED));
+
+ IntentFilter filter = filterCaptor.getValue();
+
+ assertNotNull(filter);
+ assertTrue(filter.hasAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED));
+
+ ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
+
+ // Verify intent is sent that emergency call state is changed
+ verify(mContext).sendStickyBroadcastAsUser(
+ intentCaptor.capture(), eq(UserHandle.ALL));
+ intent = intentCaptor.getValue();
+ assertNotNull(intent);
+ assertEquals(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED, intent.getAction());
+ assertFalse(intent.getBooleanExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, false));
+ }
+
+ /**
+ * Test that emergency call state is not reset after crash
+ * if it's already reset.
+ */
+ @Test
+ @SmallTest
+ public void testResetEmergencyCallStateChangesAlreadyReset() {
+ Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED);
+ intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, false);
+ doReturn(intent).when(mContext).registerReceiver(eq(null), any(),
+ eq(Context.RECEIVER_NOT_EXPORTED));
+ // Setup EmergencyStateTracker
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ emergencyStateTracker.maybeResetEmergencyCallStateChangedIntent();
+
+ ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
+
+ verify(mContext).registerReceiver(eq(null), filterCaptor.capture(),
+ eq(Context.RECEIVER_NOT_EXPORTED));
+
+ IntentFilter filter = filterCaptor.getValue();
+
+ assertNotNull(filter);
+ assertTrue(filter.hasAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED));
+
+ // Verify intent is not sent.
+ verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
+ }
+
+ /**
+ * Test that emergency call state is not reset after crash
+ * if it has never been sent.
+ */
+ @Test
+ @SmallTest
+ public void testResetEmergencyCallStateChangesNotSent() {
+ doReturn(null).when(mContext).registerReceiver(eq(null), any(),
+ eq(Context.RECEIVER_NOT_EXPORTED));
+ // Setup EmergencyStateTracker
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ emergencyStateTracker.maybeResetEmergencyCallStateChangedIntent();
+
+ ArgumentCaptor<IntentFilter> filterCaptor = ArgumentCaptor.forClass(IntentFilter.class);
+
+ verify(mContext).registerReceiver(eq(null), filterCaptor.capture(),
+ eq(Context.RECEIVER_NOT_EXPORTED));
+
+ IntentFilter filter = filterCaptor.getValue();
+
+ assertNotNull(filter);
+ assertTrue(filter.hasAction(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED));
+
+ // Verify intent is not sent.
+ verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
+ }
+
+ @Test
+ @SmallTest
+ public void testEnsureExecutionOrderOfExitEmergencyModeThenSetEmergencyMode() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ true,
+ /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(phone0, E_REG_RESULT);
+
+ // First trial
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection1, false);
+ processAllMessages();
+
+ assertTrue(emergencyStateTracker.isInEmergencyMode());
+ assertTrue(emergencyStateTracker.isInEmergencyCall());
+ verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+ emergencyStateTracker.endCall(mTestConnection1);
+ processAllMessages();
+
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ verify(phone0).exitEmergencyMode(msgCaptor.capture());
+
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(msg);
+
+ // Second trial
+ CompletableFuture<Integer> future = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection2, false);
+ processAllMessages();
+
+ assertFalse(future.isDone());
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ AsyncResult.forMessage(msg, null, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ }
+
+ @Test
+ @SmallTest
+ public void testEnsureExecutionOrderOfExitEmergencyModeThenSetEmergencyModeWithSms() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ /* isSuplDdsSwitchRequiredForEmergencyCall= */ true);
+ Phone phone0 = setupTestPhoneForEmergencyCall(/* isRoaming= */ false,
+ /* isRadioOn= */ true);
+ setUpAsyncResultForSetEmergencyMode(phone0, E_REG_RESULT);
+ CompletableFuture<Integer> future = emergencyStateTracker.startEmergencySms(phone0,
+ TEST_SMS_ID, false);
+ processAllMessages();
+
+ assertTrue(emergencyStateTracker.isInEmergencyMode());
+ verify(phone0).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ assertTrue(emergencyStateTracker.getEmergencyRegistrationResult().equals(E_REG_RESULT));
+ // Expect: DisconnectCause#NOT_DISCONNECTED.
+ assertEquals(future.getNow(DisconnectCause.ERROR_UNSPECIFIED),
+ Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
+
+ ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_CS, true);
+
+ verify(phone0).exitEmergencyMode(msgCaptor.capture());
+
+ Message msg = msgCaptor.getValue();
+
+ assertNotNull(msg);
+
+ // Dial emergency call
+ future = emergencyStateTracker.startEmergencyCall(phone0,
+ mTestConnection2, false);
+ processAllMessages();
+
+ assertFalse(future.isDone());
+ verify(phone0, times(1)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+
+ AsyncResult.forMessage(msg, null, null);
+ msg.sendToTarget();
+ processAllMessages();
+
+ verify(phone0, times(2)).setEmergencyMode(eq(MODE_EMERGENCY_WWAN), any(Message.class));
+ }
+
+ /**
+ * Test that the EmergencyStateTracker waits for the delayed radio power off.
+ */
+ @Test
+ @SmallTest
+ public void startEmergencyCall_delayedRadioOff_waitForRadioOff() {
+ EmergencyStateTracker emergencyStateTracker = setupEmergencyStateTracker(
+ true /* isSuplDdsSwitchRequiredForEmergencyCall */);
+ // Create test Phones and set radio on
+ Phone testPhone = setupTestPhoneForEmergencyCall(false /* isRoaming */,
+ true /* isRadioOn */);
+
+ // Airplane mode is ON, but radio power state is still ON
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
+
+ CompletableFuture<Integer> unused = emergencyStateTracker.startEmergencyCall(testPhone,
+ mTestConnection1, false);
+
+ // Wait for the radio off for all phones
+ verify(mSST, times(2)).registerForVoiceRegStateOrRatChanged(any(), anyInt(), any());
+ verify(mRadioOnHelper, never()).triggerRadioOnAndListen(any(), anyBoolean(), any(),
+ anyBoolean(), eq(0));
+ }
+
private EmergencyStateTracker setupEmergencyStateTracker(
boolean isSuplDdsSwitchRequiredForEmergencyCall) {
doReturn(mPhoneSwitcher).when(mPhoneSwitcherProxy).getPhoneSwitcher();
@@ -2664,7 +3276,7 @@
Integer.valueOf(DisconnectCause.NOT_DISCONNECTED));
// Expect: entering SCBM.
- emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS);
+ emergencyStateTracker.endSms(TEST_SMS_ID, true, DOMAIN_PS, true);
verify(mCarrierConfigManager).getConfigForSubId(anyInt(),
eq(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT));
diff --git a/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java b/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
index 5a6fdc2..037f82c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/emergency/RadioOnStateListenerTest.java
@@ -205,7 +205,7 @@
verify(mCallback).onComplete(eq(mListener), eq(false));
verify(mMockPhone, times(2)).setRadioPower(eq(true), eq(false), eq(false), eq(false));
verify(mSatelliteController, never()).requestSatelliteEnabled(
- anyInt(), eq(false), eq(false), any());
+ anyInt(), eq(false), eq(false), eq(false), any());
}
@Test
@@ -225,7 +225,7 @@
verify(mCallback).onComplete(eq(mListener), eq(false));
verify(mMockPhone, times(2)).setRadioPower(eq(true), eq(true), eq(true), eq(false));
verify(mSatelliteController, never()).requestSatelliteEnabled(
- anyInt(), eq(false), eq(false), any());
+ anyInt(), eq(false), eq(false), eq(false), any());
}
@Test
@@ -246,7 +246,7 @@
verify(mCallback).onComplete(eq(mListener), eq(false));
verify(mMockPhone, times(2)).setRadioPower(eq(true), eq(true), eq(true), eq(false));
verify(mSatelliteController, times(2)).requestSatelliteEnabled(
- anyInt(), eq(false), eq(false), any());
+ anyInt(), eq(false), eq(false), eq(false), any());
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
index cc4b180..e374551 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/euicc/EuiccControllerTest.java
@@ -231,6 +231,7 @@
Settings.Global.EUICC_PROVISIONED, 0);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.EUICC_PROVISIONED, 0);
+ setHasManageDevicePolicyManagedSubscriptionsPermission(false);
}
@After
@@ -895,7 +896,7 @@
@Test
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
- public void testDownloadSubscription_adminPermission_usingSwitchAfterDownload()
+ public void testDownloadSubscription_adminPermission_usingSwitchAfterDownload_fails()
throws Exception {
mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasWriteEmbeddedPermission(false);
@@ -910,18 +911,99 @@
when(mPackageManager.getPackageInfo(eq(PACKAGE_NAME), anyInt())).thenReturn(pi);
setCanManageSubscriptionOnTargetSim(false /* isTargetEuicc */, false /* hasPrivileges */);
- callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
+ callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */,
+ true /* complete */,
12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
- verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR,
- 0 /* detailedCode */);
+ verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 0 /* detailedCode */);
verify(mMockConnector, never()).downloadSubscription(anyInt(), anyInt(),
any(), anyBoolean(), anyBoolean(), any(), any());
}
@Test
@DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
- public void testDownloadSubscription_onlyAdminManagedAllowed_callerNotAdmin_throws()
+ public void testDownloadSubscription_profileOwner_usingSwitchAfterDownload_fails()
+ throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
+ setHasWriteEmbeddedPermission(false);
+ setHasManageDevicePolicyManagedSubscriptionsPermission(true);
+ setUpUiccSlotData();
+ GetDownloadableSubscriptionMetadataResult result =
+ new GetDownloadableSubscriptionMetadataResult(EuiccService.RESULT_OK,
+ SUBSCRIPTION_WITH_METADATA);
+ doReturn(true).when(mDevicePolicyManager).isProfileOwnerApp(PACKAGE_NAME);
+ doReturn(false).when(mDevicePolicyManager).isOrganizationOwnedDeviceWithManagedProfile();
+ doReturn(false).when(mDevicePolicyManager).isDeviceOwnerApp(PACKAGE_NAME);
+ prepareGetDownloadableSubscriptionMetadataCall(true /* complete */, result);
+ PackageInfo pi = new PackageInfo();
+ pi.packageName = PACKAGE_NAME;
+ when(mPackageManager.getPackageInfo(eq(PACKAGE_NAME), anyInt())).thenReturn(pi);
+ setCanManageSubscriptionOnTargetSim(false /* isTargetEuicc */, false /* hasPrivileges */);
+
+ callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */,
+ true /* complete */,
+ 12345, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
+
+ verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 0 /* detailedCode */);
+ verify(mMockConnector, never()).downloadSubscription(anyInt(), anyInt(), any(),
+ anyBoolean(), anyBoolean(), any(), any());
+ }
+
+ @Test
+ @DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
+ public void testDownloadSubscription_orgOwnedProfileOwner_usingSwitchAfterDownload_success()
+ throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
+ setHasWriteEmbeddedPermission(false);
+ setHasManageDevicePolicyManagedSubscriptionsPermission(true);
+ setUpUiccSlotData();
+ GetDownloadableSubscriptionMetadataResult result =
+ new GetDownloadableSubscriptionMetadataResult(EuiccService.RESULT_OK,
+ SUBSCRIPTION_WITH_METADATA);
+ doReturn(true).when(mDevicePolicyManager).isProfileOwnerApp(PACKAGE_NAME);
+ doReturn(true).when(mDevicePolicyManager).isOrganizationOwnedDeviceWithManagedProfile();
+ doReturn(false).when(mDevicePolicyManager).isDeviceOwnerApp(PACKAGE_NAME);
+ prepareGetDownloadableSubscriptionMetadataCall(true /* complete */, result);
+ PackageInfo pi = new PackageInfo();
+ pi.packageName = PACKAGE_NAME;
+ when(mPackageManager.getPackageInfo(eq(PACKAGE_NAME), anyInt())).thenReturn(pi);
+
+ callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
+ EuiccService.RESULT_OK, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
+
+ verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0 /* detailedCode */);
+ assertFalse(mController.mCalledRefreshSubscriptionsAndSendResult);
+ }
+
+ @Test
+ @DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
+ public void testDownloadSubscription_deviceOwner_usingSwitchAfterDownload_success()
+ throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
+ setHasWriteEmbeddedPermission(false);
+ setHasManageDevicePolicyManagedSubscriptionsPermission(true);
+ setUpUiccSlotData();
+ GetDownloadableSubscriptionMetadataResult result =
+ new GetDownloadableSubscriptionMetadataResult(EuiccService.RESULT_OK,
+ SUBSCRIPTION_WITH_METADATA);
+ doReturn(false).when(mDevicePolicyManager).isProfileOwnerApp(PACKAGE_NAME);
+ doReturn(false).when(mDevicePolicyManager).isOrganizationOwnedDeviceWithManagedProfile();
+ doReturn(true).when(mDevicePolicyManager).isDeviceOwnerApp(PACKAGE_NAME);
+ prepareGetDownloadableSubscriptionMetadataCall(true /* complete */, result);
+ PackageInfo pi = new PackageInfo();
+ pi.packageName = PACKAGE_NAME;
+ when(mPackageManager.getPackageInfo(eq(PACKAGE_NAME), anyInt())).thenReturn(pi);
+
+ callDownloadSubscription(SUBSCRIPTION, true /* switchAfterDownload */, true /* complete */,
+ EuiccService.RESULT_OK, 0 /* resolvableError */, PACKAGE_NAME /* callingPackage */);
+
+ verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK, 0 /* detailedCode */);
+ assertFalse(mController.mCalledRefreshSubscriptionsAndSendResult);
+ }
+
+ @Test
+ @DisableCompatChanges({EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS})
+ public void testDownloadSubscription_onlyAdminManagedAllowed_callerNotAdmin_error()
throws Exception {
mSetFlagsRule.enableFlags(Flags.FLAG_ESIM_MANAGEMENT_ENABLED);
setHasManageDevicePolicyManagedSubscriptionsPermission(false);
@@ -930,15 +1012,10 @@
.when(mUserManager)
.hasUserRestriction(UserManager.DISALLOW_SIM_GLOBALLY);
- assertThrows(SecurityException.class,
- () ->
- callDownloadSubscription(
- SUBSCRIPTION,
- false /* switchAfterDownload */,
- true /* complete */,
- EuiccService.RESULT_OK,
- 0 /* resolvableError */,
- "whatever" /* callingPackage */));
+ callDownloadSubscription(SUBSCRIPTION, false /* switchAfterDownload */, true /* complete */,
+ 12345, 0 /* resolvableError */, "whatever" /* callingPackage */);
+
+ verifyIntentSent(EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 0 /* detailedCode */);
assertFalse(mController.mCalledRefreshSubscriptionsAndSendResult);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
index 17a428b..4db0bc9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
@@ -20,12 +20,15 @@
import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
+import android.content.Context;
import android.os.AsyncResult;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
@@ -332,6 +335,44 @@
eq(com.android.internal.R.string.mmiErrorNotSupported));
}
+ @Test
+ public void testFacCode() {
+ // Put a valid FAC code into the carrier config.
+ CarrierConfigManager ccm = (CarrierConfigManager) mGsmCdmaPhoneUT.getContext()
+ .getSystemService(Context.CARRIER_CONFIG_SERVICE);
+ PersistableBundle cc = ccm.getConfigForSubId(0);
+ cc.putStringArray(CarrierConfigManager.KEY_FEATURE_ACCESS_CODES_STRING_ARRAY,
+ new String[] {"112"});
+
+ // Try using a dial string with the FAC; this should result in a NULL GsmMmiCode.
+ GsmMmiCode validFac = GsmMmiCode.newFromDialString("#112#6505551212*", mGsmCdmaPhoneUT,
+ null, null);
+ assertNull(validFac);
+
+ // Try using a dial string with the FAC; this should result in a NULL GsmMmiCode.
+ // Note this case is somewhat contrived, however the GsmMmiCode parsing does allow non-digit
+ // characters, so we will here too.
+ GsmMmiCode validFac2 = GsmMmiCode.newFromDialString("#112#650-555-1212*", mGsmCdmaPhoneUT,
+ null, null);
+ assertNull(validFac2);
+
+ // Try using a dial string with a different made up FAC; this one is not in the carrier
+ // config so should just return an MMI code.
+ GsmMmiCode invalidFac = GsmMmiCode.newFromDialString("#113#6505551212*", mGsmCdmaPhoneUT,
+ null, null);
+ assertNotNull(invalidFac);
+
+ // Now try the carrier config FAC code, but it's formatted as if it a USSD.
+ GsmMmiCode ussd = GsmMmiCode.newFromDialString("*#112*6505551212#", mGsmCdmaPhoneUT,
+ null, null);
+ assertNotNull(ussd);
+
+ // Now try the carrier config FAC code, but it's not a valid FAC formatted string
+ GsmMmiCode invalidFormat = GsmMmiCode.newFromDialString("*#112*6505551212", mGsmCdmaPhoneUT,
+ null, null);
+ assertNull(invalidFormat);
+ }
+
private void setCarrierSupportsCallerIdVerticalServiceCodesCarrierConfig() {
final PersistableBundle bundle = new PersistableBundle();
bundle.putBoolean(CarrierConfigManager
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
index 7e65048..4abf33f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsResolverTest.java
@@ -62,6 +62,7 @@
import com.android.ims.ImsFeatureBinderRepository;
import com.android.internal.telephony.PhoneConfigurationManager;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
import org.junit.Before;
@@ -113,6 +114,7 @@
private BroadcastReceiver mTestBootCompleteReceiver;
private ImsServiceFeatureQueryManager.Listener mDynamicQueryListener;
private PersistableBundle[] mCarrierConfigs;
+ private FeatureFlags mFeatureFlags;
@Before
@Override
@@ -127,6 +129,7 @@
mMockQueryManagerFactory = mock(ImsResolver.ImsDynamicQueryManagerFactory.class);
mMockQueryManager = mock(ImsServiceFeatureQueryManager.class);
mMockRepo = mock(ImsFeatureBinderRepository.class);
+ mFeatureFlags = mock(FeatureFlags.class);
}
@After
@@ -1969,7 +1972,7 @@
}
mTestImsResolver = new ImsResolver(mMockContext, deviceMmTelPkgName, deviceRcsPkgName,
- numSlots, mMockRepo, Looper.myLooper());
+ numSlots, mMockRepo, Looper.myLooper(), mFeatureFlags);
mTestImsResolver.setSubscriptionManagerProxy(mTestSubscriptionManagerProxy);
mTestImsResolver.setTelephonyManagerProxy(mTestTelephonyManagerProxy);
@@ -2008,7 +2011,7 @@
@Override
public ImsServiceController create(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
- ImsFeatureBinderRepository r) {
+ ImsFeatureBinderRepository r, FeatureFlags featureFlags) {
when(controller.getComponentName()).thenReturn(componentName);
return controller;
}
@@ -2118,7 +2121,7 @@
@Override
public ImsServiceController create(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
- ImsFeatureBinderRepository r) {
+ ImsFeatureBinderRepository r, FeatureFlags featureFlags) {
return controllerMap.get(componentName.getPackageName());
}
});
@@ -2136,7 +2139,7 @@
@Override
public ImsServiceController create(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
- ImsFeatureBinderRepository r) {
+ ImsFeatureBinderRepository r, FeatureFlags featureFlags) {
if (TEST_DEVICE_DEFAULT_NAME.getPackageName().equals(
componentName.getPackageName())) {
when(deviceController.getComponentName()).thenReturn(componentName);
@@ -2163,7 +2166,7 @@
@Override
public ImsServiceController create(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
- ImsFeatureBinderRepository r) {
+ ImsFeatureBinderRepository r, FeatureFlags featureFlags) {
if (TEST_DEVICE_DEFAULT_NAME.getPackageName().equals(
componentName.getPackageName())) {
when(deviceController.getComponentName()).thenReturn(componentName);
@@ -2195,7 +2198,7 @@
@Override
public ImsServiceController create(Context context, ComponentName componentName,
ImsServiceController.ImsServiceControllerCallbacks callbacks,
- ImsFeatureBinderRepository r) {
+ ImsFeatureBinderRepository r, FeatureFlags featureFlags) {
if (TEST_DEVICE_DEFAULT_NAME.getPackageName().equals(
componentName.getPackageName())) {
when(deviceController1.getComponentName()).thenReturn(componentName);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
index 0b6aa9f..65b73fb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
@@ -57,6 +57,7 @@
import com.android.ims.ImsFeatureContainer;
import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.ims.internal.IImsServiceFeatureCallback;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
import org.junit.Before;
@@ -126,6 +127,7 @@
IImsRegistration mMockRcsRegistration;
IImsServiceController mMockServiceControllerBinder;
ImsServiceController.ImsServiceControllerCallbacks mMockCallbacks;
+ FeatureFlags mFeatureFlags;
Context mMockContext;
private final ComponentName mTestComponentName = new ComponentName("TestPkg",
@@ -146,11 +148,12 @@
mMockRcsRegistration = mock(IImsRegistration.class);
mMockServiceControllerBinder = mock(IImsServiceController.class);
mMockCallbacks = mock(ImsServiceController.ImsServiceControllerCallbacks.class);
+ mFeatureFlags = mock(FeatureFlags.class);
mMockContext = mock(Context.class);
mRepo = new ImsFeatureBinderRepository();
mTestImsServiceController = new ImsServiceController(mMockContext, mTestComponentName,
- mMockCallbacks, mHandler, REBIND_RETRY, mRepo);
+ mMockCallbacks, mHandler, REBIND_RETRY, mRepo, mFeatureFlags);
when(mMockContext.bindService(any(), any(), anyInt())).thenReturn(true);
when(mMockServiceControllerBinder.createMmTelFeature(anyInt(), anyInt()))
.thenReturn(mMockMmTelFeature);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
index 6c4493b..58eca5d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneConnectionTest.java
@@ -40,6 +40,8 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
@@ -57,6 +59,7 @@
import com.android.internal.telephony.Call;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.GsmCdmaCall;
+import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.imsphone.ImsPhone.ImsDialArgs;
@@ -95,6 +98,8 @@
mForeGroundCall = mock(ImsPhoneCall.class);
mBackGroundCall = mock(ImsPhoneCall.class);
mRingGroundCall = mock(ImsPhoneCall.class);
+ mTelephonyManager = mock(TelephonyManager.class);
+ mCarrierConfigManager = mock(CarrierConfigManager.class);
replaceInstance(Handler.class, "mLooper", mImsCT, Looper.myLooper());
replaceInstance(ImsPhoneCallTracker.class, "mForegroundCall", mImsCT, mForeGroundCall);
replaceInstance(ImsPhoneCallTracker.class, "mBackgroundCall", mImsCT, mBackGroundCall);
@@ -103,6 +108,10 @@
mImsCallProfile.mCallExtras = mBundle;
doReturn(ImsPhoneCall.State.IDLE).when(mForeGroundCall).getState();
+
+ // By default, turn off the business composer
+ setUserEnabledBusinessComposer(false);
+ setCarrierConfigBusinessComposer(false);
}
@After
@@ -431,6 +440,97 @@
ImsPhoneConnection.toTelecomVerificationStatus(90210));
}
+ /**
+ * Assert the helper method
+ * {@link ImsPhoneConnection#isBusinessOnlyCallComposerEnabledByUser(Phone)} is Working As
+ * Intended.
+ */
+ @Test
+ @SmallTest
+ public void testIsBusinessOnlyCallComposerEnabledByUser() {
+ mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
+ assertFalse(mConnectionUT.isBusinessOnlyCallComposerEnabledByUser(mImsPhone));
+ setUserEnabledBusinessComposer(true);
+ assertTrue(mConnectionUT.isBusinessOnlyCallComposerEnabledByUser(mImsPhone));
+ setUserEnabledBusinessComposer(false);
+ assertFalse(mConnectionUT.isBusinessOnlyCallComposerEnabledByUser(mImsPhone));
+ }
+
+ /**
+ * Assert the helper method
+ * {@link ImsPhoneConnection#isBusinessComposerEnabledByConfig(Phone)} is Working As
+ * Intended.
+ */
+ @Test
+ @SmallTest
+ public void testBusinessComposerEnabledByCarrierConfig() {
+ mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
+ assertFalse(mConnectionUT.isBusinessComposerEnabledByConfig(mImsPhone));
+ setCarrierConfigBusinessComposer(true);
+ assertTrue(mConnectionUT.isBusinessComposerEnabledByConfig(mImsPhone));
+ setCarrierConfigBusinessComposer(false);
+ assertFalse(mConnectionUT.isBusinessComposerEnabledByConfig(mImsPhone));
+ }
+
+ /**
+ * Verify that the {@link ImsPhoneConnection#getIsBusinessComposerFeatureEnabled()} only
+ * returns true when it is enabled by the CarrierConfigManager and user.
+ */
+ @Test
+ @SmallTest
+ public void testIncomingImsCallSetsTheBusinessComposerFeatureStatus() {
+ mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
+ assertFalse(mConnectionUT.getIsBusinessComposerFeatureEnabled());
+
+ setUserEnabledBusinessComposer(true);
+ setCarrierConfigBusinessComposer(false);
+ mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
+ assertFalse(mConnectionUT.getIsBusinessComposerFeatureEnabled());
+
+ setUserEnabledBusinessComposer(false);
+ setCarrierConfigBusinessComposer(true);
+ mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
+ assertFalse(mConnectionUT.getIsBusinessComposerFeatureEnabled());
+
+ setUserEnabledBusinessComposer(true);
+ setCarrierConfigBusinessComposer(true);
+ mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
+ assertTrue(mConnectionUT.getIsBusinessComposerFeatureEnabled());
+ }
+
+ /**
+ * If the business composer feature is off but ImsCallProfile extras still injected by the lower
+ * layer, Telephony should NOT inject the telecom call extras.
+ */
+ @Test
+ @SmallTest
+ public void testMaybeInjectBusinessExtrasWithFeatureOff() {
+ setUserEnabledBusinessComposer(false);
+ setCarrierConfigBusinessComposer(false);
+ mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
+ assertFalse(mConnectionUT.getIsBusinessComposerFeatureEnabled());
+ Bundle businessExtras = getBusinessExtras();
+ mConnectionUT.maybeInjectBusinessComposerExtras(businessExtras);
+ assertFalse(businessExtras.containsKey(android.telecom.Call.EXTRA_IS_BUSINESS_CALL));
+ assertFalse(businessExtras.containsKey(android.telecom.Call.EXTRA_ASSERTED_DISPLAY_NAME));
+ }
+
+ /**
+ * Verify if the business composer feature is on, telephony is injecting the telecom call extras
+ */
+ @Test
+ @SmallTest
+ public void testMaybeInjectBusinessExtrasWithFeatureOn() {
+ setUserEnabledBusinessComposer(true);
+ setCarrierConfigBusinessComposer(true);
+ mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
+ assertTrue(mConnectionUT.getIsBusinessComposerFeatureEnabled());
+ Bundle businessExtras = getBusinessExtras();
+ mConnectionUT.maybeInjectBusinessComposerExtras(businessExtras);
+ assertTrue(businessExtras.containsKey(android.telecom.Call.EXTRA_IS_BUSINESS_CALL));
+ assertTrue(businessExtras.containsKey(android.telecom.Call.EXTRA_ASSERTED_DISPLAY_NAME));
+ }
+
@Test
@SmallTest
public void testSetRedirectingAddress() {
@@ -481,4 +581,32 @@
latch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
assertTrue(receivedCountCallback[0]);
}
+
+ private void setUserEnabledBusinessComposer(boolean isEnabled) {
+ when(mPhone.getContext()).thenReturn(mContext);
+ when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
+ if (isEnabled) {
+ when(mTelephonyManager.getCallComposerStatus()).thenReturn(
+ TelephonyManager.CALL_COMPOSER_STATUS_BUSINESS_ONLY);
+ } else {
+ when(mTelephonyManager.getCallComposerStatus()).thenReturn(
+ TelephonyManager.CALL_COMPOSER_STATUS_OFF);
+ }
+ }
+
+ private void setCarrierConfigBusinessComposer(boolean isEnabled) {
+ when(mPhone.getContext()).thenReturn(mContext);
+ when(mContext.getSystemService(CarrierConfigManager.class)).thenReturn(
+ mCarrierConfigManager);
+ PersistableBundle b = new PersistableBundle();
+ b.putBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, isEnabled);
+ when(mCarrierConfigManager.getConfigForSubId(mPhone.getSubId())).thenReturn(b);
+ }
+
+ private Bundle getBusinessExtras() {
+ Bundle businessExtras = new Bundle();
+ businessExtras.putBoolean(ImsCallProfile.EXTRA_IS_BUSINESS_CALL, true);
+ businessExtras.putString(ImsCallProfile.EXTRA_ASSERTED_DISPLAY_NAME, "Google");
+ return businessExtras;
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
index 14cff4b..992f50a 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java
@@ -73,6 +73,7 @@
import android.os.Message;
import android.os.PersistableBundle;
import android.sysprop.TelephonyProperties;
+import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
@@ -284,6 +285,14 @@
doReturn(Call.State.INCOMING).when(mRingingCall).getState();
assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("2"));
verify(mImsCT).acceptCall(ImsCallProfile.CALL_TYPE_VOICE);
+
+ // Verify b/286499659, fixed media type
+ doReturn(true).when(mFeatureFlags).answerAudioOnlyWhenAnsweringViaMmiCode();
+ doReturn(Call.State.IDLE).when(mForegroundCall).getState();
+ doReturn(Call.State.IDLE).when(mBackgroundCall).getState();
+ doReturn(Call.State.INCOMING).when(mRingingCall).getState();
+ assertEquals(true, mImsPhoneUT.handleInCallMmiCommands("2"));
+ verify(mImsCT).acceptCall(VideoProfile.STATE_AUDIO_ONLY);
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java
index d63dc3c..7374aef 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataCallSessionStatsTest.java
@@ -19,7 +19,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -32,11 +34,13 @@
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
+import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import org.junit.After;
import org.junit.Before;
@@ -94,7 +98,7 @@
@Test
@SmallTest
public void testSetupDataCallOnCellularIms_success() {
- mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
mDataCallSessionStats.onSetupDataCallResponse(
mDefaultImsResponse,
TelephonyManager.NETWORK_TYPE_LTE,
@@ -120,7 +124,7 @@
@Test
@SmallTest
public void testSetupDataCallOnIwlan_success() {
- mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
mDataCallSessionStats.onSetupDataCallResponse(
mDefaultImsResponse,
TelephonyManager.NETWORK_TYPE_IWLAN,
@@ -149,7 +153,7 @@
public void testSetupDataCallOnCrossSimCalling_success() {
doReturn(mCellularNetworkCapabilities)
.when(mDefaultNetworkMonitor).getNetworkCapabilities();
- mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
mDataCallSessionStats.onSetupDataCallResponse(
mDefaultImsResponse,
TelephonyManager.NETWORK_TYPE_IWLAN,
@@ -176,7 +180,7 @@
@Test
@SmallTest
public void testSetupDataCallOnCellularIms_failure() {
- mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
mDataCallSessionStats.onSetupDataCallResponse(
mDefaultImsResponse,
TelephonyManager.NETWORK_TYPE_LTE,
@@ -199,7 +203,7 @@
@Test
@SmallTest
public void testHandoverFromCellularToIwlan_success() {
- mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
mDataCallSessionStats.onSetupDataCallResponse(
mDefaultImsResponse,
TelephonyManager.NETWORK_TYPE_LTE,
@@ -225,7 +229,7 @@
@Test
@SmallTest
public void testHandoverFromCellularToCrossSimCalling_success() {
- mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
mDataCallSessionStats.onSetupDataCallResponse(
mDefaultImsResponse,
TelephonyManager.NETWORK_TYPE_LTE,
@@ -254,7 +258,7 @@
@Test
@SmallTest
public void testHandoverFromCellularToIwlan_failure() {
- mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
mDataCallSessionStats.onSetupDataCallResponse(
mDefaultImsResponse,
TelephonyManager.NETWORK_TYPE_LTE,
@@ -286,7 +290,7 @@
@Test
@SmallTest
public void testSetupDataCallOnIwlan_success_thenOOS() {
- mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS);
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
mDataCallSessionStats.onSetupDataCallResponse(
mDefaultImsResponse,
TelephonyManager.NETWORK_TYPE_IWLAN,
@@ -308,4 +312,100 @@
assertTrue(stats.oosAtEnd);
assertFalse(stats.ongoing);
}
+
+ @Test
+ public void testIsNtn() {
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.setTimeMillis(60000L);
+ mDataCallSessionStats.conclude();
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage).addDataCallSession(callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertTrue(stats.isNtn);
+
+ reset(mPersistAtomsStorage);
+
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any()))
+ .thenReturn(false);
+
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.setTimeMillis(60000L);
+ mDataCallSessionStats.conclude();
+
+
+ verify(mPersistAtomsStorage).addDataCallSession(callCaptor.capture());
+ stats = callCaptor.getValue();
+
+ assertFalse(stats.isNtn);
+ }
+
+ @Test
+ public void testIsProvisioningProfile() {
+ SubscriptionInfoInternal mSubInfoInternal = new SubscriptionInfoInternal.Builder()
+ .setProfileClass(mSubscriptionManager.PROFILE_CLASS_PROVISIONING).build();
+
+ when(mSubscriptionManagerService.getSubscriptionInfoInternal(mPhone.getSubId()))
+ .thenReturn(mSubInfoInternal);
+
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_IWLAN,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.setTimeMillis(60000L);
+ mDataCallSessionStats.conclude();
+
+ ArgumentCaptor<DataCallSession> callCaptor =
+ ArgumentCaptor.forClass(DataCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addDataCallSession(
+ callCaptor.capture());
+ DataCallSession stats = callCaptor.getValue();
+
+ assertTrue(stats.isProvisioningProfile);
+
+ reset(mPersistAtomsStorage);
+
+ mSubInfoInternal = new SubscriptionInfoInternal.Builder()
+ .setProfileClass(mSubscriptionManager.PROFILE_CLASS_OPERATIONAL).build();
+
+ when(mSubscriptionManagerService.getSubscriptionInfoInternal(mPhone.getSubId()))
+ .thenReturn(mSubInfoInternal);
+
+ mDataCallSessionStats.onSetupDataCall(ApnSetting.TYPE_IMS, false);
+ mDataCallSessionStats.onSetupDataCallResponse(
+ mDefaultImsResponse,
+ TelephonyManager.NETWORK_TYPE_IWLAN,
+ ApnSetting.TYPE_IMS,
+ ApnSetting.PROTOCOL_IP,
+ DataFailCause.NONE);
+
+ mDataCallSessionStats.setTimeMillis(60000L);
+ mDataCallSessionStats.conclude();
+ verify(mPersistAtomsStorage).addDataCallSession(callCaptor.capture());
+ stats = callCaptor.getValue();
+
+ assertFalse(stats.isProvisioningProfile);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/DataNetworkValidationStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataNetworkValidationStatsTest.java
new file mode 100644
index 0000000..b9493b9
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/DataNetworkValidationStatsTest.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.metrics;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.telephony.PreciseDataConnectionState;
+import android.telephony.SignalStrength;
+import android.telephony.TelephonyManager;
+import android.telephony.data.ApnSetting;
+
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyStatsLog;
+import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.nano.PersistAtomsProto;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+/** Test DataNetworkValidationStats */
+public class DataNetworkValidationStatsTest extends TelephonyTest {
+
+ /** Initial time at starting tests */
+ private static final Long STARTED_TIME_IN_MILLIS = 5000000L;
+
+ private TestableDataNetworkValidationStats mDataNetworkValidationStats;
+
+ /** Test Class for override elapsed time */
+ private static class TestableDataNetworkValidationStats extends DataNetworkValidationStats {
+ private long mSystemClockInMillis;
+ TestableDataNetworkValidationStats(Phone phone) {
+ super(phone);
+ mSystemClockInMillis = STARTED_TIME_IN_MILLIS;
+ }
+
+ @Override
+ protected long getTimeMillis() {
+ return mSystemClockInMillis;
+ }
+
+ public void elapseTimeInMillis(long elapse) {
+ mSystemClockInMillis += elapse;
+ }
+ }
+
+ @Before
+ public void setup() throws Exception {
+ super.setUp(getClass().getSimpleName());
+
+ mDataNetworkValidationStats = new TestableDataNetworkValidationStats(mPhone);
+ doReturn(SignalStrength.SIGNAL_STRENGTH_GREAT).when(mSignalStrength).getLevel();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mDataNetworkValidationStats = null;
+ super.tearDown();
+ }
+
+ @Test
+ public void testRequestDataNetworkValidation() {
+ mDataNetworkValidationStats.onRequestNetworkValidation(ApnSetting.TYPE_IMS);
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void testOnUpdateNetworkValidationStateWithSuccessStatus() {
+
+ // Test
+ mDataNetworkValidationStats.onRequestNetworkValidation(ApnSetting.TYPE_IMS);
+ mDataNetworkValidationStats.elapseTimeInMillis(100L);
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ // Verify that atom was logged
+ ArgumentCaptor<PersistAtomsProto.DataNetworkValidation> captor =
+ ArgumentCaptor.forClass(PersistAtomsProto.DataNetworkValidation.class);
+ verify(mPersistAtomsStorage, times(1)).addDataNetworkValidation(
+ captor.capture());
+ PersistAtomsProto.DataNetworkValidation proto = captor.getValue();
+
+ // Make sure variables
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__NETWORK_TYPE__NETWORK_TYPE_LTE,
+ proto.networkType);
+ assertEquals(ApnSetting.TYPE_IMS, proto.apnTypeBitmask);
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__SIGNAL_STRENGTH__SIGNAL_STRENGTH_GREAT,
+ proto.signalStrength);
+ assertEquals(TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_SUCCESS,
+ proto.validationResult);
+ assertEquals(100L, proto.elapsedTimeInMillis);
+ assertFalse(proto.handoverAttempted);
+ assertEquals(1, proto.networkValidationCount);
+ }
+
+ @Test
+ public void testOnUpdateNetworkValidationStateWithFailureStatus() {
+
+ // Test
+ mDataNetworkValidationStats.onRequestNetworkValidation(ApnSetting.TYPE_EMERGENCY);
+ mDataNetworkValidationStats.elapseTimeInMillis(100L);
+ mDataNetworkValidationStats.onHandoverAttempted();
+ mDataNetworkValidationStats.elapseTimeInMillis(100L);
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS,
+ TelephonyManager.NETWORK_TYPE_IWLAN);
+
+ // Verify that atom was logged
+ ArgumentCaptor<PersistAtomsProto.DataNetworkValidation> captor =
+ ArgumentCaptor.forClass(PersistAtomsProto.DataNetworkValidation.class);
+ verify(mPersistAtomsStorage, times(1)).addDataNetworkValidation(
+ captor.capture());
+ PersistAtomsProto.DataNetworkValidation proto = captor.getValue();
+
+ // Make sure variables
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__NETWORK_TYPE__NETWORK_TYPE_IWLAN,
+ proto.networkType);
+ assertEquals(ApnSetting.TYPE_EMERGENCY, proto.apnTypeBitmask);
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__SIGNAL_STRENGTH__SIGNAL_STRENGTH_GREAT,
+ proto.signalStrength);
+ assertEquals(TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_SUCCESS,
+ proto.validationResult);
+ assertEquals(200L, proto.elapsedTimeInMillis);
+ assertTrue(proto.handoverAttempted);
+ assertEquals(1, proto.networkValidationCount);
+ }
+
+ @Test
+ public void testOnUpdateNetworkValidationStateWithInProgressStatus() {
+
+ // Test
+ mDataNetworkValidationStats.onRequestNetworkValidation(ApnSetting.TYPE_IMS);
+ mDataNetworkValidationStats.elapseTimeInMillis(100L);
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ PreciseDataConnectionState.NETWORK_VALIDATION_NOT_REQUESTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ // Verify
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void testOnUpdateNetworkValidationStateWithNotRequestedStatus() {
+
+ // Test
+ mDataNetworkValidationStats.onRequestNetworkValidation(ApnSetting.TYPE_IMS);
+ mDataNetworkValidationStats.elapseTimeInMillis(100L);
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ PreciseDataConnectionState.NETWORK_VALIDATION_NOT_REQUESTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ // Verify
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void testOnUpdateNetworkValidationStateWithUnsupportedStatus() {
+
+ // Set up
+ doReturn(SignalStrength.SIGNAL_STRENGTH_POOR).when(mSignalStrength).getLevel();
+
+ // Test
+ mDataNetworkValidationStats.onRequestNetworkValidation(ApnSetting.TYPE_IMS);
+ mDataNetworkValidationStats.elapseTimeInMillis(300L);
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED,
+ TelephonyManager.NETWORK_TYPE_LTE);
+
+ // Verify that atom was logged
+ ArgumentCaptor<PersistAtomsProto.DataNetworkValidation> captor =
+ ArgumentCaptor.forClass(PersistAtomsProto.DataNetworkValidation.class);
+ verify(mPersistAtomsStorage, times(1)).addDataNetworkValidation(
+ captor.capture());
+ PersistAtomsProto.DataNetworkValidation proto = captor.getValue();
+
+ // Make sure variables
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__NETWORK_TYPE__NETWORK_TYPE_LTE,
+ proto.networkType);
+ assertEquals(ApnSetting.TYPE_IMS, proto.apnTypeBitmask);
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__SIGNAL_STRENGTH__SIGNAL_STRENGTH_POOR,
+ proto.signalStrength);
+ assertEquals(TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_NOT_SUPPORTED,
+ proto.validationResult);
+ assertEquals(300L, proto.elapsedTimeInMillis);
+ assertFalse(proto.handoverAttempted);
+ assertEquals(1, proto.networkValidationCount);
+ }
+
+
+ @Test
+ public void testOnDataNetworkDisconnected() {
+
+ // Set up
+ doReturn(SignalStrength.SIGNAL_STRENGTH_POOR).when(mSignalStrength).getLevel();
+
+ // Test
+ mDataNetworkValidationStats.onRequestNetworkValidation(ApnSetting.TYPE_IMS);
+ mDataNetworkValidationStats.elapseTimeInMillis(300L);
+ mDataNetworkValidationStats.onDataNetworkDisconnected(TelephonyManager.NETWORK_TYPE_LTE);
+
+ // Verify that atom was logged
+ ArgumentCaptor<PersistAtomsProto.DataNetworkValidation> captor =
+ ArgumentCaptor.forClass(PersistAtomsProto.DataNetworkValidation.class);
+ verify(mPersistAtomsStorage, times(1)).addDataNetworkValidation(
+ captor.capture());
+ PersistAtomsProto.DataNetworkValidation proto = captor.getValue();
+
+ // Make sure variables
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__NETWORK_TYPE__NETWORK_TYPE_LTE,
+ proto.networkType);
+ assertEquals(ApnSetting.TYPE_IMS, proto.apnTypeBitmask);
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__SIGNAL_STRENGTH__SIGNAL_STRENGTH_POOR,
+ proto.signalStrength);
+ assertEquals(TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_UNSPECIFIED,
+ proto.validationResult);
+ assertEquals(300L, proto.elapsedTimeInMillis);
+ assertFalse(proto.handoverAttempted);
+ assertEquals(1, proto.networkValidationCount);
+ }
+
+ @Test
+ public void testOnUpdateNetworkValidationState_DupStatus() {
+
+ // Test
+ mDataNetworkValidationStats.onRequestNetworkValidation(ApnSetting.TYPE_IMS);
+ mDataNetworkValidationStats.elapseTimeInMillis(100L);
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ PreciseDataConnectionState.NETWORK_VALIDATION_IN_PROGRESS,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ mDataNetworkValidationStats.elapseTimeInMillis(100L);
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS,
+ TelephonyManager.NETWORK_TYPE_UMTS);
+ mDataNetworkValidationStats.elapseTimeInMillis(100L);
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ PreciseDataConnectionState.NETWORK_VALIDATION_FAILURE,
+ TelephonyManager.NETWORK_TYPE_NR);
+
+ // Verify that atom was logged
+ ArgumentCaptor<PersistAtomsProto.DataNetworkValidation> captor =
+ ArgumentCaptor.forClass(PersistAtomsProto.DataNetworkValidation.class);
+ verify(mPersistAtomsStorage, times(1)).addDataNetworkValidation(
+ captor.capture());
+ PersistAtomsProto.DataNetworkValidation proto = captor.getValue();
+
+ // Make sure variables
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__NETWORK_TYPE__NETWORK_TYPE_UMTS,
+ proto.networkType);
+ assertEquals(ApnSetting.TYPE_IMS, proto.apnTypeBitmask);
+ assertEquals(
+ TelephonyStatsLog.DATA_NETWORK_VALIDATION__SIGNAL_STRENGTH__SIGNAL_STRENGTH_GREAT,
+ proto.signalStrength);
+ assertEquals(TelephonyStatsLog
+ .DATA_NETWORK_VALIDATION__VALIDATION_RESULT__VALIDATION_RESULT_SUCCESS,
+ proto.validationResult);
+ assertEquals(200L, proto.elapsedTimeInMillis);
+ assertFalse(proto.handoverAttempted);
+ assertEquals(1, proto.networkValidationCount);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
index 0426737..04b45b3 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
@@ -16,9 +16,13 @@
package com.android.internal.telephony.metrics;
+import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS;
+import static com.android.internal.telephony.TelephonyStatsLog.CARRIER_ROAMING_SATELLITE_SESSION;
import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_DATA_SERVICE_SWITCH;
import static com.android.internal.telephony.TelephonyStatsLog.CELLULAR_SERVICE_STATE;
import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SHORT_CODE_SMS;
+import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_CONFIG_UPDATER;
+import static com.android.internal.telephony.TelephonyStatsLog.SATELLITE_ENTITLEMENT;
import static com.android.internal.telephony.TelephonyStatsLog.SIM_SLOT_STATE;
import static com.android.internal.telephony.TelephonyStatsLog.SUPPORTED_RADIO_ACCESS_FAMILY;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE;
@@ -45,9 +49,13 @@
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement;
import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage;
import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession;
import com.android.internal.telephony.uicc.IccCardStatus.CardState;
@@ -70,8 +78,8 @@
.setCoolDownMillis(24L * 3600L * 1000L)
.build();
private static final long MIN_COOLDOWN_MILLIS = 23L * 3600L * 1000L;
- private static final long CELL_SERVICE_MIN_COOLDOWN_MILLIS =
- IS_DEBUGGABLE ? 4L * 60L * 1000L : MIN_COOLDOWN_MILLIS;
+ private static final long POWER_CORRELATED_MIN_COOLDOWN_MILLIS =
+ IS_DEBUGGABLE ? 4L * 60L * 1000L : 5L * 3600L * 1000L;
private static final long MIN_CALLS_PER_BUCKET = 5L;
// NOTE: these fields are currently 32-bit internally and padded to 64-bit by TelephonyManager
@@ -115,7 +123,7 @@
mFeatureFlags = mock(FeatureFlags.class);
mMetricsCollector =
new MetricsCollector(mContext, mPersistAtomsStorage,
- mDeviceStateHelper, mVonrHelper, mFeatureFlags);
+ mDeviceStateHelper, mVonrHelper, mDefaultNetworkMonitor, mFeatureFlags);
doReturn(mSST).when(mSecondPhone).getServiceStateTracker();
doReturn(mServiceStateStats).when(mSST).getServiceStateStats();
}
@@ -402,6 +410,9 @@
@SmallTest
public void onPullAtom_cellularServiceState_tooFrequent() throws Exception {
doReturn(null).when(mPersistAtomsStorage).getCellularServiceStates(anyLong());
+ mContextFixture.putIntResource(
+ com.android.internal.R.integer.config_metrics_pull_cooldown_millis,
+ (int) POWER_CORRELATED_MIN_COOLDOWN_MILLIS);
List<StatsEvent> actualAtoms = new ArrayList<>();
int result = mMetricsCollector.onPullAtom(CELLULAR_SERVICE_STATE, actualAtoms);
@@ -409,7 +420,7 @@
assertThat(actualAtoms).hasSize(0);
assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
verify(mPersistAtomsStorage, times(1)).getCellularServiceStates(
- eq(CELL_SERVICE_MIN_COOLDOWN_MILLIS));
+ eq(POWER_CORRELATED_MIN_COOLDOWN_MILLIS));
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -469,4 +480,178 @@
assertThat(actualAtoms).hasSize(4);
assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
}
+
+ @Test
+ public void onPullAtom_carrierRoamingSatelliteSession_empty() {
+ doReturn(new CarrierRoamingSatelliteSession[0]).when(mPersistAtomsStorage)
+ .getCarrierRoamingSatelliteSessionStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(0);
+ assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
+ }
+
+ @Test
+ public void onPullAtom_carrierRoamingSatelliteSession_tooFrequent() {
+ doReturn(null).when(mPersistAtomsStorage)
+ .getCarrierRoamingSatelliteSessionStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(0);
+ assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
+ verify(mPersistAtomsStorage, times(1))
+ .getCarrierRoamingSatelliteSessionStats(eq(MIN_COOLDOWN_MILLIS));
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onPullAtom_carrierRoamingSatelliteSession_multipleAtoms() {
+ CarrierRoamingSatelliteSession carrierRoamingSatelliteSession =
+ new CarrierRoamingSatelliteSession();
+ doReturn(new CarrierRoamingSatelliteSession[] {carrierRoamingSatelliteSession,
+ carrierRoamingSatelliteSession, carrierRoamingSatelliteSession,
+ carrierRoamingSatelliteSession})
+ .when(mPersistAtomsStorage)
+ .getCarrierRoamingSatelliteSessionStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_SESSION, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(4);
+ assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
+ }
+
+ @Test
+ public void onPullAtom_carrierRoamingSatelliteControllerStats_empty() {
+ doReturn(new CarrierRoamingSatelliteControllerStats[0]).when(mPersistAtomsStorage)
+ .getCarrierRoamingSatelliteControllerStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS,
+ actualAtoms);
+
+ assertThat(actualAtoms).hasSize(0);
+ assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
+ }
+
+ @Test
+ public void onPullAtom_carrierRoamingSatelliteControllerStats_multipleAtoms() {
+ CarrierRoamingSatelliteControllerStats carrierRoamingSatelliteControllerStats =
+ new CarrierRoamingSatelliteControllerStats();
+ doReturn(new CarrierRoamingSatelliteControllerStats[] {
+ carrierRoamingSatelliteControllerStats})
+ .when(mPersistAtomsStorage)
+ .getCarrierRoamingSatelliteControllerStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS,
+ actualAtoms);
+
+ assertThat(actualAtoms).hasSize(1);
+ assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
+ }
+
+ @Test
+ public void onPullAtom_carrierRoamingSatelliteControllerStats_tooFrequent() {
+ doReturn(null).when(mPersistAtomsStorage)
+ .getCarrierRoamingSatelliteControllerStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(CARRIER_ROAMING_SATELLITE_CONTROLLER_STATS,
+ actualAtoms);
+
+ assertThat(actualAtoms).hasSize(0);
+ assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
+ verify(mPersistAtomsStorage, times(1))
+ .getCarrierRoamingSatelliteControllerStats(eq(MIN_COOLDOWN_MILLIS));
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onPullAtom_satelliteEntitlement_empty() {
+ doReturn(new SatelliteEntitlement[0]).when(mPersistAtomsStorage)
+ .getSatelliteEntitlementStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(0);
+ assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
+ }
+
+ @Test
+ public void onPullAtom_satelliteEntitlement_tooFrequent() {
+ doReturn(null).when(mPersistAtomsStorage).getSatelliteEntitlementStats(
+ anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(0);
+ assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
+ verify(mPersistAtomsStorage, times(1))
+ .getSatelliteEntitlementStats(eq(MIN_COOLDOWN_MILLIS));
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onPullAtom_satelliteEntitlement_multipleAtoms() {
+ SatelliteEntitlement satelliteEntitlement = new SatelliteEntitlement();
+ doReturn(new SatelliteEntitlement[] {satelliteEntitlement, satelliteEntitlement,
+ satelliteEntitlement, satelliteEntitlement})
+ .when(mPersistAtomsStorage)
+ .getSatelliteEntitlementStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(SATELLITE_ENTITLEMENT, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(4);
+ assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
+ }
+
+ @Test
+ public void onPullAtom_satelliteConfigUpdater_empty() {
+ doReturn(new SatelliteConfigUpdater[0]).when(mPersistAtomsStorage)
+ .getSatelliteConfigUpdaterStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(0);
+ assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
+ }
+
+ @Test
+ public void onPullAtom_satelliteConfigUpdater_tooFrequent() {
+ doReturn(null).when(mPersistAtomsStorage).getSatelliteConfigUpdaterStats(
+ anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(0);
+ assertThat(result).isEqualTo(StatsManager.PULL_SKIP);
+ verify(mPersistAtomsStorage, times(1))
+ .getSatelliteConfigUpdaterStats(eq(MIN_COOLDOWN_MILLIS));
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onPullAtom_satelliteConfigUpdater_multipleAtoms() {
+ SatelliteConfigUpdater satelliteConfigUpdater = new SatelliteConfigUpdater();
+ doReturn(new SatelliteConfigUpdater[] {satelliteConfigUpdater, satelliteConfigUpdater,
+ satelliteConfigUpdater, satelliteConfigUpdater})
+ .when(mPersistAtomsStorage)
+ .getSatelliteConfigUpdaterStats(anyLong());
+ List<StatsEvent> actualAtoms = new ArrayList<>();
+
+ int result = mMetricsCollector.onPullAtom(SATELLITE_CONFIG_UPDATER, actualAtoms);
+
+ assertThat(actualAtoms).hasSize(4);
+ assertThat(result).isEqualTo(StatsManager.PULL_SUCCESS);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
index 475c90b..8ee3a37 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -16,13 +16,27 @@
package com.android.internal.telephony.metrics;
+import static android.telephony.SmsManager.RESULT_ERROR_NONE;
+import static android.telephony.SmsManager.RESULT_RIL_SMS_SEND_FAIL_RETRY;
import static android.telephony.TelephonyManager.NETWORK_TYPE_BITMASK_GPRS;
import static android.telephony.TelephonyManager.NETWORK_TYPE_BITMASK_GSM;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+import static com.android.internal.telephony.SmsResponse.NO_ERROR_CODE;
import static com.android.internal.telephony.TelephonyStatsLog.GBA_EVENT__FAILED_REASON__FEATURE_NOT_READY;
import static com.android.internal.telephony.TelephonyStatsLog.GBA_EVENT__FAILED_REASON__UNKNOWN;
+import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__ERROR__SMS_ERROR_GENERIC;
+import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__ERROR__SMS_SUCCESS;
+import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP;
+import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP2;
+import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP;
+import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP2;
+import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TYPE__SMS_TYPE_NORMAL;
+import static com.android.internal.telephony.TelephonyStatsLog.INCOMING_SMS__SMS_TYPE__SMS_TYPE_SMS_PP;
+import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR;
+import static com.android.internal.telephony.TelephonyStatsLog.OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_SUCCESS;
import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__ERROR;
import static com.android.internal.telephony.TelephonyStatsLog.RCS_ACS_PROVISIONING_STATS__RESPONSE_TYPE__PROVISIONING_XML;
import static com.android.internal.telephony.TelephonyStatsLog.RCS_CLIENT_PROVISIONING_STATS__EVENT__CLIENT_PARAMS_SENT;
@@ -31,6 +45,10 @@
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO;
import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT;
+import static com.android.internal.telephony.satellite.SatelliteConstants.ACCESS_CONTROL_TYPE_CURRENT_LOCATION;
+import static com.android.internal.telephony.satellite.SatelliteConstants.ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE;
+import static com.android.internal.telephony.satellite.SatelliteConstants.CONFIG_DATA_SOURCE_CONFIG_UPDATER;
+import static com.android.internal.telephony.satellite.SatelliteConstants.CONFIG_DATA_SOURCE_DEVICE_CONFIG;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
@@ -49,10 +67,13 @@
import android.content.Context;
import android.os.Build;
import android.telephony.DisconnectCause;
+import android.telephony.PreciseDataConnectionState;
import android.telephony.SatelliteProtoEnums;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyProtoEnums;
+import android.telephony.data.ApnSetting;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.SipDelegateManager;
@@ -60,9 +81,12 @@
import com.android.internal.telephony.TelephonyStatsLog;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
import com.android.internal.telephony.nano.PersistAtomsProto.DataCallSession;
+import com.android.internal.telephony.nano.PersistAtomsProto.DataNetworkValidation;
import com.android.internal.telephony.nano.PersistAtomsProto.GbaEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsDedicatedBearerListenerEvent;
@@ -70,12 +94,17 @@
import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationServiceDescStats;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationStats;
import com.android.internal.telephony.nano.PersistAtomsProto.ImsRegistrationTermination;
+import com.android.internal.telephony.nano.PersistAtomsProto.IncomingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingShortCodeSms;
+import com.android.internal.telephony.nano.PersistAtomsProto.OutgoingSms;
import com.android.internal.telephony.nano.PersistAtomsProto.PersistAtoms;
import com.android.internal.telephony.nano.PersistAtomsProto.PresenceNotifyEvent;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsAcsProvisioningStats;
import com.android.internal.telephony.nano.PersistAtomsProto.RcsClientProvisioningStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteAccessController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision;
@@ -106,6 +135,7 @@
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Queue;
+import java.util.concurrent.TimeUnit;
public class PersistAtomsStorageTest extends TelephonyTest {
private static final String TEST_FILE = "PersistAtomsStorageTest.pb";
@@ -235,6 +265,14 @@
private SipTransportSession mSipTransportSession2;
private SipTransportSession[] mSipTransportSession;
+ private IncomingSms mIncomingSms1;
+ private IncomingSms mIncomingSms2;
+ private IncomingSms[] mIncomingSms;
+
+ private OutgoingSms mOutgoingSms1;
+ private OutgoingSms mOutgoingSms2;
+ private OutgoingSms[] mOutgoingSms;
+
private OutgoingShortCodeSms mOutgoingShortCodeSms1;
private OutgoingShortCodeSms mOutgoingShortCodeSms2;
private OutgoingShortCodeSms[] mOutgoingShortCodeSms;
@@ -263,6 +301,32 @@
private SatelliteSosMessageRecommender mSatelliteSosMessageRecommender2;
private SatelliteSosMessageRecommender[] mSatelliteSosMessageRecommenders;
+ private DataNetworkValidation mDataNetworkValidationLte1;
+ private DataNetworkValidation mDataNetworkValidationLte2;
+ private DataNetworkValidation mDataNetworkValidationIwlan1;
+ private DataNetworkValidation mDataNetworkValidationIwlan2;
+ private DataNetworkValidation[] mDataNetworkValidations;
+
+ private CarrierRoamingSatelliteSession mCarrierRoamingSatelliteSession1;
+ private CarrierRoamingSatelliteSession mCarrierRoamingSatelliteSession2;
+ private CarrierRoamingSatelliteSession[] mCarrierRoamingSatelliteSessions;
+
+ private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats1;
+ private CarrierRoamingSatelliteControllerStats mCarrierRoamingSatelliteControllerStats2;
+ private CarrierRoamingSatelliteControllerStats[] mCarrierRoamingSatelliteControllerStats;
+
+ private SatelliteEntitlement mSatelliteEntitlement1;
+ private SatelliteEntitlement mSatelliteEntitlement2;
+ private SatelliteEntitlement[] mSatelliteEntitlements;
+
+ private SatelliteConfigUpdater mSatelliteConfigUpdater1;
+ private SatelliteConfigUpdater mSatelliteConfigUpdater2;
+ private SatelliteConfigUpdater[] mSatelliteConfigUpdaters;
+
+ private SatelliteAccessController mSatelliteAccessController1;
+ private SatelliteAccessController mSatelliteAccessController2;
+ private SatelliteAccessController[] mSatelliteAccessControllers;
+
private void makeTestData() {
// MO call with SRVCC (LTE to UMTS)
mCall1Proto = new VoiceCallSession();
@@ -946,6 +1010,97 @@
mSipTransportSession =
new SipTransportSession[] {mSipTransportSession1, mSipTransportSession2};
+ generateTestSmsData();
+ generateTestSatelliteData();
+ }
+
+ private void generateTestSmsData() {
+ mIncomingSms1 = new IncomingSms();
+ mIncomingSms1.smsFormat = INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP;
+ mIncomingSms1.smsTech = INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP;
+ mIncomingSms1.rat = TelephonyManager.NETWORK_TYPE_LTE;
+ mIncomingSms1.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_NORMAL;
+ mIncomingSms1.totalParts = 1;
+ mIncomingSms1.receivedParts = 1;
+ mIncomingSms1.blocked = false;
+ mIncomingSms1.error = INCOMING_SMS__ERROR__SMS_SUCCESS;
+ mIncomingSms1.isRoaming = false;
+ mIncomingSms1.simSlotIndex = 0;
+ mIncomingSms1.isMultiSim = false;
+ mIncomingSms1.isEsim = false;
+ mIncomingSms1.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+ mIncomingSms1.messageId = 0;
+ mIncomingSms1.count = 1;
+ mIncomingSms1.isManagedProfile = false;
+ mIncomingSms1.isNtn = false;
+ mIncomingSms1.isEmergency = true;
+
+ mIncomingSms2 = new IncomingSms();
+ mIncomingSms2.smsFormat = INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP2;
+ mIncomingSms2.smsTech = INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP2;
+ mIncomingSms2.rat = TelephonyManager.NETWORK_TYPE_CDMA;
+ mIncomingSms2.smsType = INCOMING_SMS__SMS_TYPE__SMS_TYPE_SMS_PP;
+ mIncomingSms2.totalParts = 2;
+ mIncomingSms2.receivedParts = 2;
+ mIncomingSms2.blocked = true;
+ mIncomingSms2.error = INCOMING_SMS__ERROR__SMS_ERROR_GENERIC;
+ mIncomingSms2.isRoaming = true;
+ mIncomingSms2.simSlotIndex = 1;
+ mIncomingSms2.isMultiSim = true;
+ mIncomingSms2.isEsim = true;
+ mIncomingSms2.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+ mIncomingSms2.messageId = 1;
+ mIncomingSms2.count = 2;
+ mIncomingSms2.isManagedProfile = true;
+ mIncomingSms2.isNtn = true;
+ mIncomingSms2.isEmergency = true;
+
+ mIncomingSms = new IncomingSms[] {mIncomingSms1, mIncomingSms2};
+
+ mOutgoingSms1 = new OutgoingSms();
+ mOutgoingSms1.smsFormat = INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP;
+ mOutgoingSms1.smsTech = INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP;
+ mOutgoingSms1.rat = TelephonyManager.NETWORK_TYPE_LTE;
+ mOutgoingSms1.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_SUCCESS;
+ mOutgoingSms1.errorCode = NO_ERROR_CODE;
+ mOutgoingSms1.isRoaming = false;
+ mOutgoingSms1.isFromDefaultApp = true;
+ mOutgoingSms1.simSlotIndex = 0;
+ mOutgoingSms1.isMultiSim = false;
+ mOutgoingSms1.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+ mOutgoingSms1.messageId = 0;
+ mOutgoingSms1.retryId = 0;
+ mOutgoingSms1.intervalMillis = 0;
+ mOutgoingSms1.count = 1;
+ mOutgoingSms1.sendErrorCode = RESULT_ERROR_NONE;
+ mOutgoingSms1.networkErrorCode = NO_ERROR_CODE;
+ mOutgoingSms1.isManagedProfile = false;
+ mOutgoingSms1.isEmergency = false;
+ mOutgoingSms1.isNtn = false;
+
+ mOutgoingSms2 = new OutgoingSms();
+ mOutgoingSms2.smsFormat = INCOMING_SMS__SMS_FORMAT__SMS_FORMAT_3GPP2;
+ mOutgoingSms2.smsTech = INCOMING_SMS__SMS_TECH__SMS_TECH_CS_3GPP2;
+ mOutgoingSms2.rat = TelephonyManager.NETWORK_TYPE_CDMA;
+ mOutgoingSms2.sendResult = OUTGOING_SMS__SEND_RESULT__SMS_SEND_RESULT_ERROR;
+ mOutgoingSms2.errorCode = NO_ERROR_CODE;
+ mOutgoingSms2.isRoaming = true;
+ mOutgoingSms2.isFromDefaultApp = false;
+ mOutgoingSms2.simSlotIndex = 1;
+ mOutgoingSms2.isMultiSim = true;
+ mOutgoingSms2.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+ mOutgoingSms2.messageId = 1;
+ mOutgoingSms2.retryId = 1;
+ mOutgoingSms2.intervalMillis = 10;
+ mOutgoingSms2.count = 2;
+ mOutgoingSms2.sendErrorCode = RESULT_RIL_SMS_SEND_FAIL_RETRY;
+ mOutgoingSms2.networkErrorCode = NO_ERROR_CODE;
+ mOutgoingSms2.isManagedProfile = true;
+ mOutgoingSms2.isEmergency = true;
+ mOutgoingSms2.isNtn = true;
+
+ mOutgoingSms = new OutgoingSms[] {mOutgoingSms1, mOutgoingSms2};
+
mOutgoingShortCodeSms1 = new OutgoingShortCodeSms();
mOutgoingShortCodeSms1.category = 1;
mOutgoingShortCodeSms1.xmlVersion = 30;
@@ -960,6 +1115,8 @@
mOutgoingShortCodeSms2};
generateTestSatelliteData();
+
+ generateTestDataNetworkValidationsData();
}
private void generateTestSatelliteData() {
@@ -981,6 +1138,14 @@
mSatelliteController1.totalServiceUptimeSec = 60 * 60 * 24 * 7;
mSatelliteController1.totalBatteryConsumptionPercent = 7;
mSatelliteController1.totalBatteryChargedTimeSec = 60 * 60 * 3 * 1;
+ mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsSuccess = 3;
+ mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsFail = 1;
+ mSatelliteController1.countOfDemoModeOutgoingDatagramSuccess = 4;
+ mSatelliteController1.countOfDemoModeOutgoingDatagramFail = 2;
+ mSatelliteController1.countOfDemoModeIncomingDatagramSuccess = 3;
+ mSatelliteController1.countOfDemoModeIncomingDatagramFail = 2;
+ mSatelliteController1.countOfDatagramTypeKeepAliveSuccess = 1;
+ mSatelliteController1.countOfDatagramTypeKeepAliveFail = 2;
mSatelliteController2 = new SatelliteController();
mSatelliteController2.countOfSatelliteServiceEnablementsSuccess = 2 + 1;
@@ -999,7 +1164,15 @@
mSatelliteController2.countOfDeprovisionFail = 16;
mSatelliteController2.totalServiceUptimeSec = 60 * 60 * 12;
mSatelliteController2.totalBatteryConsumptionPercent = 14;
- mSatelliteController1.totalBatteryChargedTimeSec = 60 * 60 * 3;
+ mSatelliteController2.totalBatteryChargedTimeSec = 60 * 60 * 3;
+ mSatelliteController2.countOfDemoModeSatelliteServiceEnablementsSuccess = 5;
+ mSatelliteController2.countOfDemoModeSatelliteServiceEnablementsFail = 4;
+ mSatelliteController2.countOfDemoModeOutgoingDatagramSuccess = 3;
+ mSatelliteController2.countOfDemoModeOutgoingDatagramFail = 7;
+ mSatelliteController2.countOfDemoModeIncomingDatagramSuccess = 2;
+ mSatelliteController2.countOfDemoModeIncomingDatagramFail = 3;
+ mSatelliteController2.countOfDatagramTypeKeepAliveSuccess = 4;
+ mSatelliteController2.countOfDatagramTypeKeepAliveFail = 5;
// SatelliteController atom has one data point
mSatelliteControllers =
@@ -1013,6 +1186,17 @@
mSatelliteSession1.satelliteTechnology =
SatelliteProtoEnums.NT_RADIO_TECHNOLOGY_PROPRIETARY;
mSatelliteSession1.count = 1;
+ mSatelliteSession1.satelliteServiceTerminationResult =
+ SatelliteProtoEnums.SATELLITE_ERROR_NONE;
+ mSatelliteSession1.initializationProcessingTimeMillis = 100;
+ mSatelliteSession1.terminationProcessingTimeMillis = 200;
+ mSatelliteSession1.sessionDurationSeconds = 3;
+ mSatelliteSession1.countOfOutgoingDatagramSuccess = 1;
+ mSatelliteSession1.countOfOutgoingDatagramFailed = 0;
+ mSatelliteSession1.countOfIncomingDatagramSuccess = 1;
+ mSatelliteSession1.countOfIncomingDatagramFailed = 0;
+ mSatelliteSession1.isDemoMode = false;
+ mSatelliteSession1.maxNtnSignalStrengthLevel = 2;
mSatelliteSession2 = new SatelliteSession();
mSatelliteSession2.satelliteServiceInitializationResult =
@@ -1020,6 +1204,17 @@
mSatelliteSession2.satelliteTechnology =
SatelliteProtoEnums.NT_RADIO_TECHNOLOGY_NB_IOT_NTN;
mSatelliteSession2.count = 1;
+ mSatelliteSession2.satelliteServiceTerminationResult =
+ SatelliteProtoEnums.SATELLITE_ERROR_NONE;
+ mSatelliteSession2.initializationProcessingTimeMillis = 300;
+ mSatelliteSession2.terminationProcessingTimeMillis = 100;
+ mSatelliteSession2.sessionDurationSeconds = 10;
+ mSatelliteSession2.countOfOutgoingDatagramSuccess = 0;
+ mSatelliteSession2.countOfOutgoingDatagramFailed = 2;
+ mSatelliteSession2.countOfIncomingDatagramSuccess = 0;
+ mSatelliteSession2.countOfIncomingDatagramFailed = 1;
+ mSatelliteSession2.isDemoMode = true;
+ mSatelliteSession2.maxNtnSignalStrengthLevel = 4;
mSatelliteSessions =
new SatelliteSession[] {
@@ -1030,11 +1225,13 @@
mSatelliteIncomingDatagram1.resultCode = SatelliteProtoEnums.SATELLITE_ERROR_NONE;
mSatelliteIncomingDatagram1.datagramSizeBytes = 1 * 1024;
mSatelliteIncomingDatagram1.datagramTransferTimeMillis = 3 * 1000;
+ mSatelliteIncomingDatagram1.isDemoMode = false;
mSatelliteIncomingDatagram2 = new SatelliteIncomingDatagram();
mSatelliteIncomingDatagram2.resultCode = SatelliteProtoEnums.SATELLITE_MODEM_ERROR;
mSatelliteIncomingDatagram2.datagramSizeBytes = 512;
mSatelliteIncomingDatagram2.datagramTransferTimeMillis = 1 * 1000;
+ mSatelliteIncomingDatagram1.isDemoMode = true;
mSatelliteIncomingDatagrams =
new SatelliteIncomingDatagram[] {
@@ -1047,6 +1244,7 @@
mSatelliteOutgoingDatagram1.resultCode = SatelliteProtoEnums.SATELLITE_ERROR_NONE;
mSatelliteOutgoingDatagram1.datagramSizeBytes = 1 * 1024;
mSatelliteOutgoingDatagram1.datagramTransferTimeMillis = 3 * 1000;
+ mSatelliteOutgoingDatagram1.isDemoMode = false;
mSatelliteOutgoingDatagram2 = new SatelliteOutgoingDatagram();
mSatelliteOutgoingDatagram2.datagramType =
@@ -1054,6 +1252,7 @@
mSatelliteOutgoingDatagram2.resultCode = SatelliteProtoEnums.SATELLITE_MODEM_ERROR;
mSatelliteOutgoingDatagram2.datagramSizeBytes = 512;
mSatelliteOutgoingDatagram2.datagramTransferTimeMillis = 1 * 1000;
+ mSatelliteOutgoingDatagram1.isDemoMode = true;
mSatelliteOutgoingDatagrams =
new SatelliteOutgoingDatagram[] {
@@ -1104,6 +1303,187 @@
new SatelliteSosMessageRecommender[] {
mSatelliteSosMessageRecommender1, mSatelliteSosMessageRecommender2
};
+
+ mCarrierRoamingSatelliteSession1 = new CarrierRoamingSatelliteSession();
+ mCarrierRoamingSatelliteSession1.carrierId = 1;
+ mCarrierRoamingSatelliteSession1.isNtnRoamingInHomeCountry = false;
+ mCarrierRoamingSatelliteSession1.totalSatelliteModeTimeSec = 60;
+ mCarrierRoamingSatelliteSession1.numberOfSatelliteConnections = 3;
+ mCarrierRoamingSatelliteSession1.avgDurationOfSatelliteConnectionSec = 20;
+ mCarrierRoamingSatelliteSession1.satelliteConnectionGapMinSec = 2;
+ mCarrierRoamingSatelliteSession1.satelliteConnectionGapAvgSec = 5;
+ mCarrierRoamingSatelliteSession1.satelliteConnectionGapMaxSec = 8;
+ mCarrierRoamingSatelliteSession1.rsrpAvg = 3;
+ mCarrierRoamingSatelliteSession1.rsrpMedian = 2;
+ mCarrierRoamingSatelliteSession1.rssnrAvg = 5;
+ mCarrierRoamingSatelliteSession1.rssnrMedian = 3;
+ mCarrierRoamingSatelliteSession1.countOfIncomingSms = 2;
+ mCarrierRoamingSatelliteSession1.countOfOutgoingSms = 4;
+ mCarrierRoamingSatelliteSession1.countOfIncomingMms = 1;
+ mCarrierRoamingSatelliteSession1.countOfOutgoingMms = 1;
+
+ mCarrierRoamingSatelliteSession2 = new CarrierRoamingSatelliteSession();
+ mCarrierRoamingSatelliteSession2.carrierId = 2;
+ mCarrierRoamingSatelliteSession2.isNtnRoamingInHomeCountry = true;
+ mCarrierRoamingSatelliteSession2.totalSatelliteModeTimeSec = 120;
+ mCarrierRoamingSatelliteSession2.numberOfSatelliteConnections = 5;
+ mCarrierRoamingSatelliteSession2.avgDurationOfSatelliteConnectionSec = 20;
+ mCarrierRoamingSatelliteSession2.satelliteConnectionGapMinSec = 2;
+ mCarrierRoamingSatelliteSession2.satelliteConnectionGapAvgSec = 5;
+ mCarrierRoamingSatelliteSession2.satelliteConnectionGapMaxSec = 8;
+ mCarrierRoamingSatelliteSession2.rsrpAvg = 3;
+ mCarrierRoamingSatelliteSession2.rsrpMedian = 2;
+ mCarrierRoamingSatelliteSession2.rssnrAvg = 8;
+ mCarrierRoamingSatelliteSession2.rssnrMedian = 15;
+ mCarrierRoamingSatelliteSession2.countOfIncomingSms = 2;
+ mCarrierRoamingSatelliteSession2.countOfOutgoingSms = 4;
+ mCarrierRoamingSatelliteSession2.countOfIncomingMms = 1;
+ mCarrierRoamingSatelliteSession2.countOfOutgoingMms = 1;
+
+ mCarrierRoamingSatelliteSessions = new CarrierRoamingSatelliteSession[] {
+ mCarrierRoamingSatelliteSession1, mCarrierRoamingSatelliteSession2};
+
+ mCarrierRoamingSatelliteControllerStats1 = new CarrierRoamingSatelliteControllerStats();
+ mCarrierRoamingSatelliteControllerStats1.configDataSource =
+ SatelliteProtoEnums.CONFIG_DATA_SOURCE_ENTITLEMENT;
+ mCarrierRoamingSatelliteControllerStats1.countOfEntitlementStatusQueryRequest = 2;
+ mCarrierRoamingSatelliteControllerStats1.countOfSatelliteConfigUpdateRequest = 1;
+ mCarrierRoamingSatelliteControllerStats1.countOfSatelliteNotificationDisplayed = 1;
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMinSec = 2;
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapAvgSec = 3;
+ mCarrierRoamingSatelliteControllerStats1.satelliteSessionGapMaxSec = 4;
+
+ mCarrierRoamingSatelliteControllerStats2 = new CarrierRoamingSatelliteControllerStats();
+ mCarrierRoamingSatelliteControllerStats2.configDataSource =
+ SatelliteProtoEnums.CONFIG_DATA_SOURCE_CONFIG_UPDATER;
+ mCarrierRoamingSatelliteControllerStats2.countOfEntitlementStatusQueryRequest = 4;
+ mCarrierRoamingSatelliteControllerStats2.countOfSatelliteConfigUpdateRequest = 1;
+ mCarrierRoamingSatelliteControllerStats2.countOfSatelliteNotificationDisplayed = 1;
+ mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMinSec = 5;
+ mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapAvgSec = 10;
+ mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMaxSec = 15;
+
+ // CarrierRoamingSatelliteController has one data point
+ mCarrierRoamingSatelliteControllerStats = new CarrierRoamingSatelliteControllerStats[] {
+ mCarrierRoamingSatelliteControllerStats1};
+
+ mSatelliteEntitlement1 = new SatelliteEntitlement();
+ mSatelliteEntitlement1.carrierId = 1;
+ mSatelliteEntitlement1.result = 0;
+ mSatelliteEntitlement1.entitlementStatus =
+ SatelliteProtoEnums.SATELLITE_ENTITLEMENT_STATUS_ENABLED;
+ mSatelliteEntitlement1.isRetry = false;
+ mSatelliteEntitlement1.count = 1;
+
+ mSatelliteEntitlement2 = new SatelliteEntitlement();
+ mSatelliteEntitlement2.carrierId = 2;
+ mSatelliteEntitlement2.result = 1;
+ mSatelliteEntitlement2.entitlementStatus =
+ SatelliteProtoEnums.SATELLITE_ENTITLEMENT_STATUS_DISABLED;
+ mSatelliteEntitlement1.isRetry = true;
+ mSatelliteEntitlement2.count = 1;
+
+ mSatelliteEntitlements = new SatelliteEntitlement[] {mSatelliteEntitlement1,
+ mSatelliteEntitlement2};
+
+ mSatelliteConfigUpdater1 = new SatelliteConfigUpdater();
+ mSatelliteConfigUpdater1.configVersion = 1;
+ mSatelliteConfigUpdater1.oemConfigResult = SatelliteProtoEnums.CONFIG_UPDATE_RESULT_SUCCESS;
+ mSatelliteConfigUpdater1.carrierConfigResult =
+ SatelliteProtoEnums.CONFIG_UPDATE_RESULT_CARRIER_DATA_INVALID_PLMN;
+ mSatelliteConfigUpdater1.count = 1;
+
+ mSatelliteConfigUpdater2 = new SatelliteConfigUpdater();
+ mSatelliteConfigUpdater2.configVersion = 2;
+ mSatelliteConfigUpdater2.oemConfigResult =
+ SatelliteProtoEnums.CONFIG_UPDATE_RESULT_DEVICE_DATA_INVALID_COUNTRY_CODE;
+ mSatelliteConfigUpdater2.carrierConfigResult =
+ SatelliteProtoEnums.CONFIG_UPDATE_RESULT_SUCCESS;
+ mSatelliteConfigUpdater2.count = 1;
+
+ mSatelliteConfigUpdaters = new SatelliteConfigUpdater[] {mSatelliteConfigUpdater1,
+ mSatelliteConfigUpdater2};
+
+ mSatelliteAccessController1 = new SatelliteAccessController();
+ mSatelliteAccessController1.accessControlType = ACCESS_CONTROL_TYPE_NETWORK_COUNTRY_CODE;
+ mSatelliteAccessController1.locationQueryTimeMillis = TimeUnit.SECONDS.toMillis(1);
+ mSatelliteAccessController1.onDeviceLookupTimeMillis = TimeUnit.SECONDS.toMillis(2);
+ mSatelliteAccessController1.totalCheckingTimeMillis = TimeUnit.SECONDS.toMillis(3);
+ mSatelliteAccessController1.isAllowed = true;
+ mSatelliteAccessController1.isEmergency = false;
+ mSatelliteAccessController1.resultCode = SATELLITE_RESULT_SUCCESS;
+ mSatelliteAccessController1.countryCodes = new String[]{"AB", "CD"};
+ mSatelliteAccessController1.configDataSource = CONFIG_DATA_SOURCE_DEVICE_CONFIG;
+
+ mSatelliteAccessController2 = new SatelliteAccessController();
+ mSatelliteAccessController1.accessControlType = ACCESS_CONTROL_TYPE_CURRENT_LOCATION;
+ mSatelliteAccessController1.locationQueryTimeMillis = TimeUnit.SECONDS.toMillis(4);
+ mSatelliteAccessController2.onDeviceLookupTimeMillis = TimeUnit.SECONDS.toMillis(5);
+ mSatelliteAccessController2.totalCheckingTimeMillis = TimeUnit.SECONDS.toMillis(6);
+ mSatelliteAccessController2.isAllowed = false;
+ mSatelliteAccessController2.isEmergency = true;
+ mSatelliteAccessController2.resultCode = SATELLITE_RESULT_SUCCESS;
+ mSatelliteAccessController2.countryCodes = new String[]{"EF", "GH"};
+ mSatelliteAccessController2.configDataSource = CONFIG_DATA_SOURCE_CONFIG_UPDATER;
+
+ mSatelliteAccessControllers = new SatelliteAccessController[]{
+ mSatelliteAccessController1, mSatelliteAccessController2
+ };
+ }
+
+ private void generateTestDataNetworkValidationsData() {
+
+ // for LTE #1
+ mDataNetworkValidationLte1 = new DataNetworkValidation();
+ mDataNetworkValidationLte1.networkType = TelephonyManager.NETWORK_TYPE_LTE;
+ mDataNetworkValidationLte1.apnTypeBitmask = ApnSetting.TYPE_IMS;
+ mDataNetworkValidationLte1.signalStrength = SignalStrength.SIGNAL_STRENGTH_GREAT;
+ mDataNetworkValidationLte1.validationResult =
+ PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS;
+ mDataNetworkValidationLte1.elapsedTimeInMillis = 100L;
+ mDataNetworkValidationLte1.handoverAttempted = false;
+ mDataNetworkValidationLte1.networkValidationCount = 1;
+
+ // for LTE #2
+ mDataNetworkValidationLte2 = new DataNetworkValidation();
+ mDataNetworkValidationLte2.networkType = TelephonyManager.NETWORK_TYPE_LTE;
+ mDataNetworkValidationLte2.apnTypeBitmask = ApnSetting.TYPE_IMS;
+ mDataNetworkValidationLte2.signalStrength = SignalStrength.SIGNAL_STRENGTH_GREAT;
+ mDataNetworkValidationLte2.validationResult =
+ PreciseDataConnectionState.NETWORK_VALIDATION_SUCCESS;
+ mDataNetworkValidationLte2.elapsedTimeInMillis = 100L;
+ mDataNetworkValidationLte2.handoverAttempted = false;
+ mDataNetworkValidationLte2.networkValidationCount = 1;
+
+ // for IWLAN #1
+ mDataNetworkValidationIwlan1 = new DataNetworkValidation();
+ mDataNetworkValidationIwlan1.networkType = TelephonyManager.NETWORK_TYPE_IWLAN;
+ mDataNetworkValidationIwlan1.apnTypeBitmask = ApnSetting.TYPE_IMS;
+ mDataNetworkValidationIwlan1.signalStrength = SignalStrength.SIGNAL_STRENGTH_POOR;
+ mDataNetworkValidationIwlan1.validationResult =
+ PreciseDataConnectionState.NETWORK_VALIDATION_FAILURE;
+ mDataNetworkValidationIwlan1.elapsedTimeInMillis = 10000L;
+ mDataNetworkValidationIwlan1.handoverAttempted = false;
+ mDataNetworkValidationIwlan1.networkValidationCount = 1;
+
+ // for IWLAN #2
+ mDataNetworkValidationIwlan2 = new DataNetworkValidation();
+ mDataNetworkValidationIwlan2.networkType = TelephonyManager.NETWORK_TYPE_IWLAN;
+ mDataNetworkValidationIwlan2.apnTypeBitmask = ApnSetting.TYPE_IMS;
+ mDataNetworkValidationIwlan2.signalStrength = SignalStrength.SIGNAL_STRENGTH_POOR;
+ mDataNetworkValidationIwlan2.validationResult =
+ PreciseDataConnectionState.NETWORK_VALIDATION_FAILURE;
+ mDataNetworkValidationIwlan2.elapsedTimeInMillis = 30000L;
+ mDataNetworkValidationIwlan2.handoverAttempted = false;
+ mDataNetworkValidationIwlan2.networkValidationCount = 1;
+
+ mDataNetworkValidations =
+ new DataNetworkValidation[] {
+ mDataNetworkValidationLte1,
+ mDataNetworkValidationLte1,
+ mDataNetworkValidationIwlan1,
+ mDataNetworkValidationIwlan2,
+ };
}
private static class TestablePersistAtomsStorage extends PersistAtomsStorage {
@@ -1244,6 +1624,12 @@
mSipTransportSession1 = null;
mSipTransportSession2 = null;
mSipTransportSession = null;
+ mIncomingSms = null;
+ mIncomingSms1 = null;
+ mIncomingSms2 = null;
+ mOutgoingSms = null;
+ mOutgoingSms1 = null;
+ mOutgoingSms2 = null;
mOutgoingShortCodeSms1 = null;
mOutgoingShortCodeSms2 = null;
mOutgoingShortCodeSms = null;
@@ -1265,6 +1651,25 @@
mSatelliteSosMessageRecommender1 = null;
mSatelliteSosMessageRecommender2 = null;
mSatelliteSosMessageRecommenders = null;
+ mDataNetworkValidationLte1 = null;
+ mDataNetworkValidationLte2 = null;
+ mDataNetworkValidationIwlan1 = null;
+ mDataNetworkValidationIwlan2 = null;
+ mCarrierRoamingSatelliteSession1 = null;
+ mCarrierRoamingSatelliteSession2 = null;
+ mCarrierRoamingSatelliteSessions = null;
+ mCarrierRoamingSatelliteControllerStats1 = null;
+ mCarrierRoamingSatelliteControllerStats2 = null;
+ mCarrierRoamingSatelliteControllerStats = null;
+ mSatelliteEntitlement1 = null;
+ mSatelliteEntitlement2 = null;
+ mSatelliteEntitlements = null;
+ mSatelliteConfigUpdater1 = null;
+ mSatelliteConfigUpdater2 = null;
+ mSatelliteConfigUpdaters = null;
+ mSatelliteAccessController1 = null;
+ mSatelliteAccessController2 = null;
+ mSatelliteAccessControllers = null;
super.tearDown();
}
@@ -3721,6 +4126,88 @@
}
@Test
+ public void addIncomingSms_emptyProto() throws Exception {
+ createEmptyTestFile();
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addIncomingSms(mIncomingSms1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // IncomingSms should be added successfully, changes should be saved.
+ verifyCurrentStateSavedToFileOnce();
+ IncomingSms[] expectedList = new IncomingSms[] {mIncomingSms1};
+ assertProtoArrayEquals(expectedList, mPersistAtomsStorage.getIncomingSms(0L));
+ }
+
+ @Test
+ public void addIncomingSms_withExistingEntries() throws Exception {
+ createEmptyTestFile();
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addIncomingSms(mIncomingSms1);
+ mPersistAtomsStorage.addIncomingSms(mIncomingSms2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // IncomingSms should be added successfully.
+ verifyCurrentStateSavedToFileOnce();
+ IncomingSms[] expectedList = new IncomingSms[] {mIncomingSms1, mIncomingSms2};
+ assertProtoArrayEqualsIgnoringOrder(expectedList, mPersistAtomsStorage.getIncomingSms(0L));
+ }
+
+ @Test
+ public void getIncomingSms_tooFrequent() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ // Pull interval less than minimum.
+ mPersistAtomsStorage.incTimeMillis(50L);
+ IncomingSms[] outgoingShortCodeSmsList = mPersistAtomsStorage.getIncomingSms(100L);
+ // Should be denied.
+ assertNull(outgoingShortCodeSmsList);
+ }
+
+ @Test
+ public void addOutgoingSms_emptyProto() throws Exception {
+ createEmptyTestFile();
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addOutgoingSms(mOutgoingSms1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // OutgoingSms should be added successfully, changes should be saved.
+ verifyCurrentStateSavedToFileOnce();
+ OutgoingSms[] expectedList = new OutgoingSms[] {mOutgoingSms1};
+ assertProtoArrayEquals(expectedList, mPersistAtomsStorage.getOutgoingSms(0L));
+ }
+
+ @Test
+ public void addOutgoingSms_withExistingEntries() throws Exception {
+ createEmptyTestFile();
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addOutgoingSms(mOutgoingSms1);
+ mPersistAtomsStorage.addOutgoingSms(mOutgoingSms2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // OutgoingSms should be added successfully.
+ verifyCurrentStateSavedToFileOnce();
+ OutgoingSms[] expectedList = new OutgoingSms[] {mOutgoingSms1, mOutgoingSms2};
+ assertProtoArrayEqualsIgnoringOrder(expectedList, mPersistAtomsStorage.getOutgoingSms(0L));
+ }
+
+ @Test
+ public void getOutgoingSms_tooFrequent() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ // Pull interval less than minimum.
+ mPersistAtomsStorage.incTimeMillis(50L);
+ OutgoingSms[] outgoingShortCodeSmsList = mPersistAtomsStorage.getOutgoingSms(100L);
+ // Should be denied.
+ assertNull(outgoingShortCodeSmsList);
+ }
+
+ @Test
public void addOutgoingShortCodeSms_emptyProto() throws Exception {
createEmptyTestFile();
@@ -3910,6 +4397,30 @@
expected.totalBatteryChargedTimeSec =
mSatelliteController1.totalBatteryChargedTimeSec
+ mSatelliteController2.totalBatteryChargedTimeSec;
+ expected.countOfDemoModeSatelliteServiceEnablementsSuccess =
+ mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsSuccess
+ + mSatelliteController2.countOfDemoModeSatelliteServiceEnablementsSuccess;
+ expected.countOfDemoModeSatelliteServiceEnablementsFail =
+ mSatelliteController1.countOfDemoModeSatelliteServiceEnablementsFail
+ + mSatelliteController2.countOfDemoModeSatelliteServiceEnablementsFail;
+ expected.countOfDemoModeOutgoingDatagramSuccess =
+ mSatelliteController1.countOfDemoModeOutgoingDatagramSuccess
+ + mSatelliteController2.countOfDemoModeOutgoingDatagramSuccess;
+ expected.countOfDemoModeOutgoingDatagramFail =
+ mSatelliteController1.countOfDemoModeOutgoingDatagramFail
+ + mSatelliteController2.countOfDemoModeOutgoingDatagramFail;
+ expected.countOfDemoModeIncomingDatagramSuccess =
+ mSatelliteController1.countOfDemoModeIncomingDatagramSuccess
+ + mSatelliteController2.countOfDemoModeIncomingDatagramSuccess;
+ expected.countOfDemoModeIncomingDatagramFail =
+ mSatelliteController1.countOfDemoModeIncomingDatagramFail
+ + mSatelliteController2.countOfDemoModeIncomingDatagramFail;
+ expected.countOfDatagramTypeKeepAliveSuccess =
+ mSatelliteController1.countOfDatagramTypeKeepAliveSuccess
+ + mSatelliteController2.countOfDatagramTypeKeepAliveSuccess;
+ expected.countOfDatagramTypeKeepAliveFail =
+ mSatelliteController1.countOfDatagramTypeKeepAliveFail
+ + mSatelliteController2.countOfDatagramTypeKeepAliveFail;
// Service state and service switch should be added successfully
verifyCurrentStateSavedToFileOnce();
@@ -4314,6 +4825,533 @@
}
@Test
+ public void addCarrierRoamingSatelliteSessionStats_emptyProto() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats(
+ mCarrierRoamingSatelliteSession1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ verifyCurrentStateSavedToFileOnce();
+ CarrierRoamingSatelliteSession[] output =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(0L);
+ assertProtoArrayEquals(new CarrierRoamingSatelliteSession[] {
+ mCarrierRoamingSatelliteSession1}, output);
+ }
+
+ @Test
+ public void addCarrierRoamingSatelliteSessionStats_withExistingEntries() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats(
+ mCarrierRoamingSatelliteSession1);
+ mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats(
+ mCarrierRoamingSatelliteSession2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ verifyCurrentStateSavedToFileOnce();
+ CarrierRoamingSatelliteSession[] output =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(0L);
+ assertProtoArrayEqualsIgnoringOrder(
+ new CarrierRoamingSatelliteSession[] {mCarrierRoamingSatelliteSession2}, output);
+ }
+
+ @Test
+ public void addCarrierRoamingSatelliteSessionStats_tooManyEntries() throws Exception {
+ createEmptyTestFile();
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+
+ // Store atoms up to maximum number + 1
+ int maxCount = 1 + 1;
+ for (int i = 0; i < maxCount; i++) {
+ mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats(
+ copyOf(mCarrierRoamingSatelliteSession1));
+ mPersistAtomsStorage.incTimeMillis(100L);
+ }
+
+ // Store 1 different atom
+ mPersistAtomsStorage.addCarrierRoamingSatelliteSessionStats(
+ mCarrierRoamingSatelliteSession2);
+
+ verifyCurrentStateSavedToFileOnce();
+
+ CarrierRoamingSatelliteSession[] result =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(0L);
+
+ // First atom has count 0, the other has 1
+ assertHasStatsAndCount(result, mCarrierRoamingSatelliteSession1, 0);
+ assertHasStatsAndCount(result, mCarrierRoamingSatelliteSession2, 1);
+ }
+
+ @Test
+ public void getCarrierRoamingSatelliteSessionStats_tooFrequent() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
+ CarrierRoamingSatelliteSession[] output =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(100L);
+
+ // Should be denied
+ assertNull(output);
+ }
+
+ @Test
+ public void getCarrierRoamingSatelliteSessionStats_withSavedAtoms() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.incTimeMillis(100L);
+ CarrierRoamingSatelliteSession[] carrierRoamingSatelliteSessionStatsList1 =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(50L);
+ mPersistAtomsStorage.incTimeMillis(100L);
+ CarrierRoamingSatelliteSession[] carrierRoamingSatelliteSessionStatsList2 =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteSessionStats(50L);
+
+ // First set of results should be equal to file contents.
+ CarrierRoamingSatelliteSession[] expectedList = new CarrierRoamingSatelliteSession[] {
+ mCarrierRoamingSatelliteSession1, mCarrierRoamingSatelliteSession2};
+ assertProtoArrayEqualsIgnoringOrder(expectedList, carrierRoamingSatelliteSessionStatsList1);
+ // Second set of results should be empty.
+ assertProtoArrayEquals(new CarrierRoamingSatelliteSession[0],
+ carrierRoamingSatelliteSessionStatsList2);
+ // Corresponding pull timestamp should be updated and saved.
+ assertEquals(START_TIME_MILLIS + 200L, mPersistAtomsStorage
+ .getAtomsProto().carrierRoamingSatelliteSessionPullTimestampMillis);
+ InOrder inOrder = inOrder(mTestFileOutputStream);
+ assertEquals(START_TIME_MILLIS + 100L,
+ getAtomsWritten(inOrder).carrierRoamingSatelliteSessionPullTimestampMillis);
+ assertEquals(START_TIME_MILLIS + 200L,
+ getAtomsWritten(inOrder).carrierRoamingSatelliteSessionPullTimestampMillis);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void addCarrierRoamingSatelliteControllerStats_emptyProto() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
+ mCarrierRoamingSatelliteControllerStats1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ verifyCurrentStateSavedToFileOnce();
+ CarrierRoamingSatelliteControllerStats[] output =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L);
+ assertProtoArrayEquals(new CarrierRoamingSatelliteControllerStats[] {
+ mCarrierRoamingSatelliteControllerStats1}, output);
+ }
+
+ @Test
+ public void addCarrierRoamingSatelliteControllerStats_withExistingEntries() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
+ mCarrierRoamingSatelliteControllerStats1);
+ mPersistAtomsStorage.addCarrierRoamingSatelliteControllerStats(
+ mCarrierRoamingSatelliteControllerStats2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ CarrierRoamingSatelliteControllerStats expected =
+ new CarrierRoamingSatelliteControllerStats();
+ expected.configDataSource = mCarrierRoamingSatelliteControllerStats2.configDataSource;
+ expected.countOfEntitlementStatusQueryRequest =
+ mCarrierRoamingSatelliteControllerStats1.countOfEntitlementStatusQueryRequest
+ + mCarrierRoamingSatelliteControllerStats2
+ .countOfEntitlementStatusQueryRequest;
+ expected.countOfSatelliteConfigUpdateRequest =
+ mCarrierRoamingSatelliteControllerStats1.countOfSatelliteConfigUpdateRequest
+ + mCarrierRoamingSatelliteControllerStats2
+ .countOfSatelliteConfigUpdateRequest;
+ expected.countOfSatelliteNotificationDisplayed =
+ mCarrierRoamingSatelliteControllerStats1.countOfSatelliteNotificationDisplayed
+ + mCarrierRoamingSatelliteControllerStats2
+ .countOfSatelliteNotificationDisplayed;
+ expected.satelliteSessionGapMinSec =
+ mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMinSec;
+ expected.satelliteSessionGapAvgSec =
+ mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapAvgSec;
+ expected.satelliteSessionGapMaxSec =
+ mCarrierRoamingSatelliteControllerStats2.satelliteSessionGapMaxSec;
+
+ verifyCurrentStateSavedToFileOnce();
+ CarrierRoamingSatelliteControllerStats[] output =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(0L);
+ assertHasStats(output, expected);
+ }
+
+ @Test
+ public void getCarrierRoamingSatelliteControllerStats_tooFrequent() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
+ CarrierRoamingSatelliteControllerStats[] output =
+ mPersistAtomsStorage.getCarrierRoamingSatelliteControllerStats(100L);
+
+ // Should be denied
+ assertNull(output);
+ }
+
+
+ @Test
+ public void addSatelliteEntitlementStats_emptyProto() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ verifyCurrentStateSavedToFileOnce();
+ SatelliteEntitlement[] output =
+ mPersistAtomsStorage.getSatelliteEntitlementStats(0L);
+ assertProtoArrayEquals(new SatelliteEntitlement[] {mSatelliteEntitlement1}, output);
+ }
+
+ @Test
+ public void addSatelliteEntitlementStats_withExistingEntries() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement1);
+ mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ verifyCurrentStateSavedToFileOnce();
+ SatelliteEntitlement[] output =
+ mPersistAtomsStorage.getSatelliteEntitlementStats(0L);
+ assertProtoArrayEqualsIgnoringOrder(
+ new SatelliteEntitlement[] {
+ mSatelliteEntitlement1, mSatelliteEntitlement2}, output);
+ }
+
+ @Test
+ public void addSatelliteEntitlementStats_updateExistingEntries() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addSatelliteEntitlementStats(copyOf(mSatelliteEntitlement1));
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // Count should be increased by 1.
+ verifyCurrentStateSavedToFileOnce();
+ SatelliteEntitlement newSatelliteEntitlement1 = copyOf(mSatelliteEntitlement1);
+ newSatelliteEntitlement1.count = 2;
+ SatelliteEntitlement[] expectedList = new SatelliteEntitlement[] {newSatelliteEntitlement1,
+ mSatelliteEntitlement2};
+ assertProtoArrayEqualsIgnoringOrder(expectedList,
+ mPersistAtomsStorage.getSatelliteEntitlementStats(0L));
+ }
+
+ @Test
+ public void addSatelliteEntitlementStats_tooManyEntries() throws Exception {
+ createEmptyTestFile();
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+
+ // Store atoms up to maximum number + 1
+ int maxCount = 15 + 1;
+ for (int i = 0; i < maxCount; i++) {
+ mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+ }
+
+ // Store 1 different atom
+ mPersistAtomsStorage.addSatelliteEntitlementStats(mSatelliteEntitlement2);
+
+ verifyCurrentStateSavedToFileOnce();
+
+ SatelliteEntitlement[] result =
+ mPersistAtomsStorage.getSatelliteEntitlementStats(0L);
+
+ // First atom has count 14, the other has 1
+ assertHasStatsAndCount(result, mSatelliteEntitlement1, 16);
+ assertHasStatsAndCount(result, mSatelliteEntitlement2, 1);
+ }
+
+ @Test
+ public void getSatelliteEntitlementStats_tooFrequent() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
+ SatelliteEntitlement[] output =
+ mPersistAtomsStorage.getSatelliteEntitlementStats(100L);
+
+ // Should be denied
+ assertNull(output);
+ }
+
+ @Test
+ public void getSatelliteEntitlementStats_withSavedAtoms() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.incTimeMillis(100L);
+ SatelliteEntitlement[] satelliteEntitlementStatsList1 =
+ mPersistAtomsStorage.getSatelliteEntitlementStats(50L);
+ mPersistAtomsStorage.incTimeMillis(100L);
+ SatelliteEntitlement[] satelliteEntitlementStatsList2 =
+ mPersistAtomsStorage.getSatelliteEntitlementStats(50L);
+
+ // First set of results should be equal to file contents.
+ SatelliteEntitlement[] expectedList = new SatelliteEntitlement[] {
+ mSatelliteEntitlement1, mSatelliteEntitlement2};
+ assertProtoArrayEqualsIgnoringOrder(expectedList, satelliteEntitlementStatsList1);
+ // Second set of results should be empty.
+ assertProtoArrayEquals(new SatelliteEntitlement[0], satelliteEntitlementStatsList2);
+ // Corresponding pull timestamp should be updated and saved.
+ assertEquals(START_TIME_MILLIS + 200L, mPersistAtomsStorage
+ .getAtomsProto().satelliteEntitlementPullTimestampMillis);
+ InOrder inOrder = inOrder(mTestFileOutputStream);
+ assertEquals(START_TIME_MILLIS + 100L,
+ getAtomsWritten(inOrder).satelliteEntitlementPullTimestampMillis);
+ assertEquals(START_TIME_MILLIS + 200L,
+ getAtomsWritten(inOrder).satelliteEntitlementPullTimestampMillis);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void addSatelliteConfigUpdaterStats_emptyProto() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ verifyCurrentStateSavedToFileOnce();
+ SatelliteConfigUpdater[] output =
+ mPersistAtomsStorage.getSatelliteConfigUpdaterStats(0L);
+ assertProtoArrayEquals(new SatelliteConfigUpdater[] {mSatelliteConfigUpdater1}, output);
+ }
+
+ @Test
+ public void addSatelliteConfigUpdaterStats_withExistingEntries() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater1);
+ mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ verifyCurrentStateSavedToFileOnce();
+ SatelliteConfigUpdater[] output =
+ mPersistAtomsStorage.getSatelliteConfigUpdaterStats(0L);
+ assertProtoArrayEqualsIgnoringOrder(new SatelliteConfigUpdater[] {
+ mSatelliteConfigUpdater1, mSatelliteConfigUpdater2}, output);
+ }
+
+ @Test
+ public void addSatelliteConfigUpdaterStats_updateExistingEntries() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addSatelliteConfigUpdaterStats(copyOf(mSatelliteConfigUpdater1));
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // Count should be increased by 1.
+ verifyCurrentStateSavedToFileOnce();
+ SatelliteConfigUpdater newSatelliteConfigUpdater1 = copyOf(mSatelliteConfigUpdater1);
+ newSatelliteConfigUpdater1.count = 2;
+ SatelliteConfigUpdater[] expectedList = new SatelliteConfigUpdater[] {
+ newSatelliteConfigUpdater1, mSatelliteConfigUpdater2};
+ assertProtoArrayEqualsIgnoringOrder(expectedList,
+ mPersistAtomsStorage.getSatelliteConfigUpdaterStats(0L));
+ }
+
+ @Test
+ public void addSatelliteConfigUpdaterStats_tooManyEntries() throws Exception {
+ createEmptyTestFile();
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+
+ // Store atoms up to maximum number + 1
+ int maxCount = 15 + 1;
+ for (int i = 0; i < maxCount; i++) {
+ mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+ }
+
+ // Store 1 different atom
+ mPersistAtomsStorage.addSatelliteConfigUpdaterStats(mSatelliteConfigUpdater2);
+
+ verifyCurrentStateSavedToFileOnce();
+
+ SatelliteConfigUpdater[] result =
+ mPersistAtomsStorage.getSatelliteConfigUpdaterStats(0L);
+
+ // First atom has count 14, the other has 1
+ assertHasStatsAndCount(result, mSatelliteConfigUpdater1, 16);
+ assertHasStatsAndCount(result, mSatelliteConfigUpdater2, 1);
+ }
+
+ @Test
+ public void getSatelliteConfigUpdaterStats_tooFrequent() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
+ SatelliteConfigUpdater[] output =
+ mPersistAtomsStorage.getSatelliteConfigUpdaterStats(100L);
+
+ // Should be denied
+ assertNull(output);
+ }
+
+ @Test
+ public void getSatelliteConfigUpdaterStats_withSavedAtoms() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.incTimeMillis(100L);
+ SatelliteConfigUpdater[] satelliteConfigUpdaterStatsList1 =
+ mPersistAtomsStorage.getSatelliteConfigUpdaterStats(50L);
+ mPersistAtomsStorage.incTimeMillis(100L);
+ SatelliteConfigUpdater[] satelliteConfigUpdaterStatsList2 =
+ mPersistAtomsStorage.getSatelliteConfigUpdaterStats(50L);
+
+ // First set of results should be equal to file contents.
+ SatelliteConfigUpdater[] expectedList = new SatelliteConfigUpdater[] {
+ mSatelliteConfigUpdater1, mSatelliteConfigUpdater2};
+ assertProtoArrayEqualsIgnoringOrder(expectedList, satelliteConfigUpdaterStatsList1);
+ // Second set of results should be empty.
+ assertProtoArrayEquals(new SatelliteConfigUpdater[0], satelliteConfigUpdaterStatsList2);
+ // Corresponding pull timestamp should be updated and saved.
+ assertEquals(START_TIME_MILLIS + 200L, mPersistAtomsStorage
+ .getAtomsProto().satelliteConfigUpdaterPullTimestampMillis);
+ InOrder inOrder = inOrder(mTestFileOutputStream);
+ assertEquals(START_TIME_MILLIS + 100L,
+ getAtomsWritten(inOrder).satelliteConfigUpdaterPullTimestampMillis);
+ assertEquals(START_TIME_MILLIS + 200L,
+ getAtomsWritten(inOrder).satelliteConfigUpdaterPullTimestampMillis);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void addSatelliteAccessControllerStats_emptyProto() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.addSatelliteAccessControllerStats(
+ mSatelliteAccessController1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // Service state and service switch should be added successfully
+ verifyCurrentStateSavedToFileOnce();
+ SatelliteAccessController[] output =
+ mPersistAtomsStorage.getSatelliteAccessControllerStats(0L);
+ assertProtoArrayEquals(
+ new SatelliteAccessController[] {mSatelliteAccessController1}, output);
+ }
+
+ @Test
+ public void addSatelliteAccessControllerStats_tooManyEntries() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+
+ // Store atoms up to maximum number + 1
+ int maxCount = 15 + 1;
+ for (int i = 0; i < maxCount; i++) {
+ mPersistAtomsStorage
+ .addSatelliteAccessControllerStats(//mSatelliteAccessController1);
+ copyOf(mSatelliteAccessController1));
+ mPersistAtomsStorage.incTimeMillis(100L);
+ }
+
+ // Store 1 different atom
+ mPersistAtomsStorage
+ .addSatelliteAccessControllerStats(mSatelliteAccessController2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ verifyCurrentStateSavedToFileOnce();
+
+ SatelliteAccessController[] result =
+ mPersistAtomsStorage.getSatelliteAccessControllerStats(0L);
+ // First atom should have count 14, the other should have 1
+ assertHasStatsAndCount(result, mSatelliteAccessController1, 14);
+ assertHasStatsAndCount(result, mSatelliteAccessController2, 1);
+ }
+
+ @Test
+ public void getSatelliteAccessControllerStats_tooFrequent() throws Exception {
+ createTestFile(START_TIME_MILLIS);
+
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+ mPersistAtomsStorage.incTimeMillis(50L); // pull interval less than minimum
+ SatelliteAccessController[] output =
+ mPersistAtomsStorage.getSatelliteAccessControllerStats(100L);
+
+ // Should be denied
+ assertNull(output);
+ }
+
+ @Test
+ @SmallTest
+ public void addDataNetworkValidation_newEntry() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+
+ mPersistAtomsStorage.addDataNetworkValidation(mDataNetworkValidationLte1);
+ mPersistAtomsStorage.addDataNetworkValidation(mDataNetworkValidationIwlan1);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // There should be 2 DataNetworkValidation
+ verifyCurrentStateSavedToFileOnce();
+ DataNetworkValidation[] output = mPersistAtomsStorage.getDataNetworkValidation(0L);
+ assertProtoArrayEqualsIgnoringOrder(
+ new DataNetworkValidation[] {
+ mDataNetworkValidationLte1, mDataNetworkValidationIwlan1},
+ output);
+ }
+
+ @Test
+ public void addDataNetworkValidation_existingEntry() throws Exception {
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+
+ int expectedNetworkValidationCount =
+ mDataNetworkValidationLte1.networkValidationCount
+ + mDataNetworkValidationLte2.networkValidationCount;
+
+ mPersistAtomsStorage.addDataNetworkValidation(mDataNetworkValidationLte1);
+ mPersistAtomsStorage.addDataNetworkValidation(mDataNetworkValidationLte2);
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ DataNetworkValidation expected = copyOf(mDataNetworkValidationLte1);
+ expected.networkValidationCount = expectedNetworkValidationCount;
+
+ // There should be 1 DataNetworkValidation
+ verifyCurrentStateSavedToFileOnce();
+ DataNetworkValidation[] output =
+ mPersistAtomsStorage.getDataNetworkValidation(0L);
+ assertProtoArrayEqualsIgnoringOrder(
+ new DataNetworkValidation[] {expected},
+ output);
+ }
+
+ @Test
+ public void addDataNetworkValidation_tooManyEntries() throws Exception {
+
+ // Set up
+ doReturn(false).when(mPackageManager).hasSystemFeature(anyString());
+
+ createEmptyTestFile();
+ mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
+
+ // Currently, the maximum number that can be stored for DataNetworkValidation in Atom
+ // storage is 15. Try saving excess.
+ int maxNumDataNetworkValidation = 20;
+ mPersistAtomsStorage.addDataNetworkValidation(mDataNetworkValidationLte1);
+ for (int i = 0; i < maxNumDataNetworkValidation; i++) {
+ DataNetworkValidation copied = copyOf(mDataNetworkValidationLte1);
+ copied.apnTypeBitmask = mDataNetworkValidationLte1.apnTypeBitmask + i;
+ mPersistAtomsStorage.addDataNetworkValidation(copied);
+ }
+ mPersistAtomsStorage.incTimeMillis(100L);
+
+ // There should be less than or equal to maxNumDataNetworkValidation
+ verifyCurrentStateSavedToFileOnce();
+ DataNetworkValidation[] output =
+ mPersistAtomsStorage.getDataNetworkValidation(0L);
+ assertTrue(output.length <= maxNumDataNetworkValidation);
+ }
+
+ @Test
@SmallTest
public void clearAtoms() throws Exception {
createTestFile(START_TIME_MILLIS);
@@ -4398,6 +5436,17 @@
atoms.satelliteProvisionPullTimestampMillis = lastPullTimeMillis;
atoms.satelliteSosMessageRecommender = mSatelliteSosMessageRecommenders;
atoms.satelliteSosMessageRecommenderPullTimestampMillis = lastPullTimeMillis;
+ atoms.dataNetworkValidation = mDataNetworkValidations;
+ atoms.dataNetworkValidationPullTimestampMillis = lastPullTimeMillis;
+ atoms.carrierRoamingSatelliteSession = mCarrierRoamingSatelliteSessions;
+ atoms.carrierRoamingSatelliteSessionPullTimestampMillis = lastPullTimeMillis;
+ atoms.carrierRoamingSatelliteControllerStats = mCarrierRoamingSatelliteControllerStats;
+ atoms.carrierRoamingSatelliteControllerStatsPullTimestampMillis = lastPullTimeMillis;
+ atoms.satelliteEntitlement = mSatelliteEntitlements;
+ atoms.satelliteEntitlementPullTimestampMillis = lastPullTimeMillis;
+ atoms.satelliteConfigUpdater = mSatelliteConfigUpdaters;
+ atoms.satelliteConfigUpdaterPullTimestampMillis = lastPullTimeMillis;
+ atoms.satelliteAccessControllerPullTimestampMillis = lastPullTimeMillis;
FileOutputStream stream = new FileOutputStream(mTestFile);
stream.write(PersistAtoms.toByteArray(atoms));
stream.close();
@@ -4516,6 +5565,16 @@
return SipTransportSession.parseFrom(MessageNano.toByteArray(source));
}
+ private static IncomingSms copyOf(IncomingSms source)
+ throws Exception {
+ return IncomingSms.parseFrom(MessageNano.toByteArray(source));
+ }
+
+ private static OutgoingSms copyOf(OutgoingSms source)
+ throws Exception {
+ return OutgoingSms.parseFrom(MessageNano.toByteArray(source));
+ }
+
private static OutgoingShortCodeSms copyOf(OutgoingShortCodeSms source)
throws Exception {
return OutgoingShortCodeSms.parseFrom(MessageNano.toByteArray(source));
@@ -4551,6 +5610,34 @@
return SatelliteSosMessageRecommender.parseFrom(MessageNano.toByteArray(source));
}
+ private static DataNetworkValidation copyOf(DataNetworkValidation source)
+ throws Exception {
+ return DataNetworkValidation.parseFrom(MessageNano.toByteArray(source));
+ }
+
+ private static CarrierRoamingSatelliteSession copyOf(CarrierRoamingSatelliteSession source)
+ throws Exception {
+ return CarrierRoamingSatelliteSession.parseFrom(MessageNano.toByteArray(source));
+ }
+
+ private static CarrierRoamingSatelliteControllerStats copyOf(
+ CarrierRoamingSatelliteControllerStats source) throws Exception {
+ return CarrierRoamingSatelliteControllerStats.parseFrom(MessageNano.toByteArray(source));
+ }
+
+ private static SatelliteEntitlement copyOf(SatelliteEntitlement source) throws Exception {
+ return SatelliteEntitlement.parseFrom(MessageNano.toByteArray(source));
+ }
+
+ private static SatelliteConfigUpdater copyOf(SatelliteConfigUpdater source) throws Exception {
+ return SatelliteConfigUpdater.parseFrom(MessageNano.toByteArray(source));
+ }
+
+ private static SatelliteAccessController copyOf(SatelliteAccessController source)
+ throws Exception {
+ return SatelliteAccessController.parseFrom(MessageNano.toByteArray(source));
+ }
+
private void assertAllPullTimestampEquals(long timestamp) {
assertEquals(
timestamp,
@@ -4726,6 +5813,18 @@
expectedStats.totalBatteryConsumptionPercent);
assertEquals(tested[0].totalBatteryChargedTimeSec,
expectedStats.totalBatteryChargedTimeSec);
+ assertEquals(tested[0].countOfDemoModeSatelliteServiceEnablementsSuccess,
+ expectedStats.countOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(tested[0].countOfDemoModeSatelliteServiceEnablementsFail,
+ expectedStats.countOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(tested[0].countOfDemoModeOutgoingDatagramSuccess,
+ expectedStats.countOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(tested[0].countOfDemoModeOutgoingDatagramFail,
+ expectedStats.countOfDemoModeOutgoingDatagramFail);
+ assertEquals(tested[0].countOfDemoModeIncomingDatagramSuccess,
+ expectedStats.countOfDemoModeIncomingDatagramSuccess);
+ assertEquals(tested[0].countOfDemoModeIncomingDatagramFail,
+ expectedStats.countOfDemoModeIncomingDatagramFail);
}
private static void assertHasStatsAndCount(
@@ -4736,7 +5835,23 @@
for (SatelliteSession stats : tested) {
if (stats.satelliteServiceInitializationResult
== expectedStats.satelliteServiceInitializationResult
- && stats.satelliteTechnology == expectedStats.satelliteTechnology) {
+ && stats.satelliteTechnology == expectedStats.satelliteTechnology
+ && stats.satelliteServiceTerminationResult
+ == expectedStats.satelliteServiceTerminationResult
+ && stats.initializationProcessingTimeMillis
+ == expectedStats.initializationProcessingTimeMillis
+ && stats.terminationProcessingTimeMillis
+ == expectedStats.terminationProcessingTimeMillis
+ && stats.sessionDurationSeconds == expectedStats.sessionDurationSeconds
+ && stats.countOfOutgoingDatagramSuccess
+ == expectedStats.countOfOutgoingDatagramSuccess
+ && stats.countOfOutgoingDatagramFailed
+ == expectedStats.countOfOutgoingDatagramFailed
+ && stats.countOfIncomingDatagramSuccess
+ == expectedStats.countOfIncomingDatagramSuccess
+ && stats.countOfIncomingDatagramFailed
+ == expectedStats.countOfIncomingDatagramFailed
+ && stats.isDemoMode == expectedStats.isDemoMode) {
actualCount = stats.count;
}
}
@@ -4752,7 +5867,8 @@
if (stats.resultCode == expectedStats.resultCode
&& stats.datagramSizeBytes == expectedStats.datagramSizeBytes
&& stats.datagramTransferTimeMillis
- == expectedStats.datagramTransferTimeMillis) {
+ == expectedStats.datagramTransferTimeMillis
+ && stats.isDemoMode == expectedStats.isDemoMode) {
actualCount++;
}
}
@@ -4769,7 +5885,8 @@
&& stats.resultCode == expectedStats.resultCode
&& stats.datagramSizeBytes == expectedStats.datagramSizeBytes
&& stats.datagramTransferTimeMillis
- == expectedStats.datagramTransferTimeMillis) {
+ == expectedStats.datagramTransferTimeMillis
+ && stats.isDemoMode == expectedStats.isDemoMode) {
actualCount++;
}
}
@@ -4813,6 +5930,28 @@
assertEquals(expectedCount, actualCount);
}
+ private static void assertHasStatsAndCount(
+ SatelliteAccessController[] tested,
+ @Nullable SatelliteAccessController expectedStats, int expectedCount) {
+ assertNotNull(tested);
+ int actualCount = 0;
+ for (SatelliteAccessController stats : tested) {
+ if (stats.accessControlType
+ == expectedStats.accessControlType
+ && stats.locationQueryTimeMillis == expectedStats.locationQueryTimeMillis
+ && stats.onDeviceLookupTimeMillis == expectedStats.onDeviceLookupTimeMillis
+ && stats.totalCheckingTimeMillis == expectedStats.totalCheckingTimeMillis
+ && stats.isAllowed == expectedStats.isAllowed
+ && stats.isEmergency == expectedStats.isEmergency
+ && stats.resultCode == expectedStats.resultCode
+ && Arrays.equals(stats.countryCodes, expectedStats.countryCodes)
+ && stats.configDataSource == expectedStats.configDataSource) {
+ actualCount++;
+ }
+ }
+ assertEquals(expectedCount, actualCount);
+ }
+
private static void assertHasStatsAndCountDuration(
RcsAcsProvisioningStats[] statses,
@Nullable RcsAcsProvisioningStats expectedStats, int count, long duration) {
@@ -4949,6 +6088,65 @@
}
private static void assertHasStatsAndCount(
+ IncomingSms[] incomingSmsList,
+ @Nullable IncomingSms expectedIncomingSms, int expectedCount) {
+ assertNotNull(incomingSmsList);
+ int actualCount = -1;
+ for (IncomingSms incomingSms : incomingSmsList) {
+ if (incomingSms.smsFormat == expectedIncomingSms.smsFormat
+ && incomingSms.smsTech == expectedIncomingSms.smsTech
+ && incomingSms.rat == expectedIncomingSms.rat
+ && incomingSms.smsType == expectedIncomingSms.smsType
+ && incomingSms.totalParts == expectedIncomingSms.totalParts
+ && incomingSms.receivedParts == expectedIncomingSms.receivedParts
+ && incomingSms.blocked == expectedIncomingSms.blocked
+ && incomingSms.error == expectedIncomingSms.error
+ && incomingSms.isRoaming == expectedIncomingSms.isRoaming
+ && incomingSms.simSlotIndex == expectedIncomingSms.simSlotIndex
+ && incomingSms.isMultiSim == expectedIncomingSms.isMultiSim
+ && incomingSms.isEsim == expectedIncomingSms.isEsim
+ && incomingSms.carrierId == expectedIncomingSms.carrierId
+ && incomingSms.messageId == expectedIncomingSms.messageId
+ && incomingSms.isManagedProfile == expectedIncomingSms.isManagedProfile
+ && incomingSms.isNtn == expectedIncomingSms.isNtn
+ && incomingSms.isEmergency == expectedIncomingSms.isEmergency) {
+ actualCount = incomingSms.count;
+ }
+ }
+ assertEquals(expectedCount, actualCount);
+ }
+
+ private static void assertHasStatsAndCount(
+ OutgoingSms[] outgoingSmsList,
+ @Nullable OutgoingSms expectedOutgoingSms, int expectedCount) {
+ assertNotNull(outgoingSmsList);
+ int actualCount = -1;
+ for (OutgoingSms outgoingSms : outgoingSmsList) {
+ if (outgoingSms.smsFormat == expectedOutgoingSms.smsFormat
+ && outgoingSms.smsTech == expectedOutgoingSms.smsTech
+ && outgoingSms.rat == expectedOutgoingSms.rat
+ && outgoingSms.sendResult == expectedOutgoingSms.sendResult
+ && outgoingSms.errorCode == expectedOutgoingSms.errorCode
+ && outgoingSms.isRoaming == expectedOutgoingSms.isRoaming
+ && outgoingSms.isFromDefaultApp == expectedOutgoingSms.isFromDefaultApp
+ && outgoingSms.simSlotIndex == expectedOutgoingSms.simSlotIndex
+ && outgoingSms.isMultiSim == expectedOutgoingSms.isMultiSim
+ && outgoingSms.carrierId == expectedOutgoingSms.carrierId
+ && outgoingSms.messageId == expectedOutgoingSms.messageId
+ && outgoingSms.retryId == expectedOutgoingSms.retryId
+ && outgoingSms.intervalMillis == expectedOutgoingSms.intervalMillis
+ && outgoingSms.sendErrorCode == expectedOutgoingSms.sendErrorCode
+ && outgoingSms.networkErrorCode == expectedOutgoingSms.networkErrorCode
+ && outgoingSms.isManagedProfile == expectedOutgoingSms.isManagedProfile
+ && outgoingSms.isEmergency == expectedOutgoingSms.isEmergency
+ && outgoingSms.isNtn == expectedOutgoingSms.isNtn) {
+ actualCount = outgoingSms.count;
+ }
+ }
+ assertEquals(expectedCount, actualCount);
+ }
+
+ private static void assertHasStatsAndCount(
OutgoingShortCodeSms[] outgoingShortCodeSmsList,
@Nullable OutgoingShortCodeSms expectedOutgoingShortCodeSms, int expectedCount) {
assertNotNull(outgoingShortCodeSmsList);
@@ -4961,4 +6159,82 @@
}
assertEquals(expectedCount, actualCount);
}
+
+ private static void assertHasStatsAndCount(CarrierRoamingSatelliteSession[] tested,
+ @Nullable CarrierRoamingSatelliteSession expectedStats, int expectedCount) {
+ assertNotNull(tested);
+ int actualCount = 0;
+ for (CarrierRoamingSatelliteSession stats : tested) {
+ if (stats.carrierId == expectedStats.carrierId
+ && stats.isNtnRoamingInHomeCountry == expectedStats.isNtnRoamingInHomeCountry
+ && stats.totalSatelliteModeTimeSec == expectedStats.totalSatelliteModeTimeSec
+ && stats.numberOfSatelliteConnections
+ == expectedStats.numberOfSatelliteConnections
+ && stats.avgDurationOfSatelliteConnectionSec
+ == expectedStats.avgDurationOfSatelliteConnectionSec
+ && stats.satelliteConnectionGapMinSec
+ == expectedStats.satelliteConnectionGapMinSec
+ && stats.satelliteConnectionGapAvgSec
+ == expectedStats.satelliteConnectionGapAvgSec
+ && stats.satelliteConnectionGapMaxSec
+ == expectedStats.satelliteConnectionGapMaxSec
+ && stats.rsrpAvg == expectedStats.rsrpAvg
+ && stats.rsrpMedian == expectedStats.rsrpMedian
+ && stats.rssnrAvg == expectedStats.rssnrAvg
+ && stats.rssnrMedian == expectedStats.rssnrMedian
+ && stats.countOfIncomingSms == expectedStats.countOfIncomingSms
+ && stats.countOfOutgoingSms == expectedStats.countOfOutgoingSms
+ && stats.countOfIncomingMms == expectedStats.countOfIncomingMms
+ && stats.countOfOutgoingMms == expectedStats.countOfOutgoingMms) {
+ actualCount++;
+ }
+ }
+ assertEquals(expectedCount, actualCount);
+ }
+
+ private static void assertHasStats(CarrierRoamingSatelliteControllerStats[] tested,
+ @Nullable CarrierRoamingSatelliteControllerStats expectedStats) {
+ assertNotNull(tested);
+ assertEquals(tested[0].configDataSource, expectedStats.configDataSource);
+ assertEquals(tested[0].countOfEntitlementStatusQueryRequest,
+ expectedStats.countOfEntitlementStatusQueryRequest);
+ assertEquals(tested[0].countOfSatelliteConfigUpdateRequest,
+ expectedStats.countOfSatelliteConfigUpdateRequest);
+ assertEquals(tested[0].countOfSatelliteNotificationDisplayed,
+ expectedStats.countOfSatelliteNotificationDisplayed);
+ assertEquals(tested[0].satelliteSessionGapMinSec, expectedStats.satelliteSessionGapMinSec);
+ assertEquals(tested[0].satelliteSessionGapAvgSec, expectedStats.satelliteSessionGapAvgSec);
+ assertEquals(tested[0].satelliteSessionGapMaxSec, expectedStats.satelliteSessionGapMaxSec);
+ }
+
+ private static void assertHasStatsAndCount(
+ SatelliteEntitlement[] tested,
+ @Nullable SatelliteEntitlement expectedStats, int expectedCount) {
+ assertNotNull(tested);
+ int actualCount = 0;
+ for (SatelliteEntitlement stats : tested) {
+ if (stats.carrierId == expectedStats.carrierId
+ && stats.result == expectedStats.result
+ && stats.entitlementStatus == expectedStats.entitlementStatus
+ && stats.isRetry == expectedStats.isRetry) {
+ actualCount = stats.count;
+ }
+ }
+ assertEquals(expectedCount, actualCount);
+ }
+
+ private static void assertHasStatsAndCount(
+ SatelliteConfigUpdater[] tested,
+ @Nullable SatelliteConfigUpdater expectedStats, int expectedCount) {
+ assertNotNull(tested);
+ int actualCount = 0;
+ for (SatelliteConfigUpdater stats : tested) {
+ if (stats.configVersion == expectedStats.configVersion
+ && stats.oemConfigResult == expectedStats.oemConfigResult
+ && stats.carrierConfigResult == expectedStats.carrierConfigResult) {
+ actualCount = stats.count;
+ }
+ }
+ assertEquals(expectedCount, actualCount);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
index 959b643..cda96ef 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/SatelliteStatsTest.java
@@ -16,6 +16,12 @@
package com.android.internal.telephony.metrics;
+import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import static com.android.internal.telephony.satellite.SatelliteConstants.CONFIG_DATA_SOURCE_DEVICE_CONFIG;
+import static com.android.internal.telephony.satellite.SatelliteConstants.ACCESS_CONTROL_TYPE_CACHED_COUNTRY_CODE;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -24,7 +30,12 @@
import android.telephony.TelephonyProtoEnums;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteControllerStats;
+import com.android.internal.telephony.nano.PersistAtomsProto.CarrierRoamingSatelliteSession;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteAccessController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteConfigUpdater;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteController;
+import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteEntitlement;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteIncomingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteOutgoingDatagram;
import com.android.internal.telephony.nano.PersistAtomsProto.SatelliteProvision;
@@ -36,6 +47,8 @@
import org.junit.Test;
import org.mockito.ArgumentCaptor;
+import java.util.concurrent.TimeUnit;
+
public class SatelliteStatsTest extends TelephonyTest {
private static final String TAG = SatelliteStatsTest.class.getSimpleName();
@@ -81,6 +94,14 @@
.setTotalServiceUptimeSec(60 * 60 * 24 * 7)
.setTotalBatteryConsumptionPercent(7)
.setTotalBatteryChargedTimeSec(60 * 60 * 3)
+ .setCountOfDemoModeSatelliteServiceEnablementsSuccess(3)
+ .setCountOfDemoModeSatelliteServiceEnablementsFail(1)
+ .setCountOfDemoModeOutgoingDatagramSuccess(4)
+ .setCountOfDemoModeOutgoingDatagramFail(2)
+ .setCountOfDemoModeIncomingDatagramSuccess(3)
+ .setCountOfDemoModeIncomingDatagramFail(2)
+ .setCountOfDatagramTypeKeepAliveSuccess(1)
+ .setCountOfDatagramTypeKeepAliveFail(2)
.build();
mSatelliteStats.onSatelliteControllerMetrics(param);
@@ -123,6 +144,22 @@
stats.totalBatteryConsumptionPercent);
assertEquals(param.getTotalBatteryChargedTimeSec(),
stats.totalBatteryChargedTimeSec);
+ assertEquals(param.getCountOfDemoModeSatelliteServiceEnablementsSuccess(),
+ stats.countOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(param.getCountOfDemoModeSatelliteServiceEnablementsFail(),
+ stats.countOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(param.getCountOfDemoModeOutgoingDatagramSuccess(),
+ stats.countOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(param.getCountOfDemoModeOutgoingDatagramFail(),
+ stats.countOfDemoModeOutgoingDatagramFail);
+ assertEquals(param.getCountOfDemoModeIncomingDatagramSuccess(),
+ stats.countOfDemoModeIncomingDatagramSuccess);
+ assertEquals(param.getCountOfDemoModeIncomingDatagramFail(),
+ stats.countOfDemoModeIncomingDatagramFail);
+ assertEquals(param.getCountOfDatagramTypeKeepAliveSuccess(),
+ stats.countOfDatagramTypeKeepAliveSuccess);
+ assertEquals(param.getCountOfDatagramTypeKeepAliveFail(),
+ stats.countOfDatagramTypeKeepAliveFail);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -134,6 +171,16 @@
.setSatelliteServiceInitializationResult(
SatelliteProtoEnums.SATELLITE_ERROR_NONE)
.setSatelliteTechnology(SatelliteProtoEnums.NT_RADIO_TECHNOLOGY_PROPRIETARY)
+ .setTerminationResult(SatelliteProtoEnums.SATELLITE_ERROR_NONE)
+ .setInitializationProcessingTime(100)
+ .setTerminationProcessingTime(200)
+ .setSessionDuration(3)
+ .setCountOfOutgoingDatagramSuccess(1)
+ .setCountOfOutgoingDatagramFailed(0)
+ .setCountOfIncomingDatagramSuccess(1)
+ .setCountOfIncomingDatagramFailed(0)
+ .setIsDemoMode(false)
+ .setMaxNtnSignalStrengthLevel(NTN_SIGNAL_STRENGTH_GOOD)
.build();
mSatelliteStats.onSatelliteSessionMetrics(param);
@@ -144,7 +191,20 @@
SatelliteSession stats = captor.getValue();
assertEquals(param.getSatelliteServiceInitializationResult(),
stats.satelliteServiceInitializationResult);
- assertEquals(param.getSatelliteTechnology(), stats.satelliteTechnology);
+ assertEquals(param.getTerminationResult(), stats.satelliteServiceTerminationResult);
+ assertEquals(param.getInitializationProcessingTime(),
+ stats.initializationProcessingTimeMillis);
+ assertEquals(param.getTerminationProcessingTime(), stats.terminationProcessingTimeMillis);
+ assertEquals(param.getSessionDuration(), stats.sessionDurationSeconds);
+ assertEquals(param.getCountOfOutgoingDatagramSuccess(),
+ stats.countOfOutgoingDatagramSuccess);
+ assertEquals(param.getCountOfOutgoingDatagramFailed(), stats.countOfOutgoingDatagramFailed);
+ assertEquals(param.getCountOfIncomingDatagramSuccess(),
+ stats.countOfIncomingDatagramSuccess);
+ assertEquals(param.getCountOfIncomingDatagramFailed(), stats.countOfIncomingDatagramFailed);
+ assertEquals(param.getIsDemoMode(), stats.isDemoMode);
+ assertEquals(param.getMaxNtnSignalStrengthLevel(), stats.maxNtnSignalStrengthLevel);
+
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -155,6 +215,7 @@
.setResultCode(SatelliteProtoEnums.SATELLITE_ERROR_NONE)
.setDatagramSizeBytes(1 * 1024)
.setDatagramTransferTimeMillis(3 * 1000)
+ .setIsDemoMode(true)
.build();
mSatelliteStats.onSatelliteIncomingDatagramMetrics(param);
@@ -166,6 +227,7 @@
assertEquals(param.getResultCode(), stats.resultCode);
assertEquals(param.getDatagramSizeBytes(), stats.datagramSizeBytes);
assertEquals(param.getDatagramTransferTimeMillis(), stats.datagramTransferTimeMillis);
+ assertEquals(param.getIsDemoMode(), stats.isDemoMode);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -177,6 +239,7 @@
.setResultCode(SatelliteProtoEnums.SATELLITE_ERROR_NONE)
.setDatagramSizeBytes(1 * 1024)
.setDatagramTransferTimeMillis(3 * 1000)
+ .setIsDemoMode(true)
.build();
mSatelliteStats.onSatelliteOutgoingDatagramMetrics(param);
@@ -189,6 +252,7 @@
assertEquals(param.getResultCode(), stats.resultCode);
assertEquals(param.getDatagramSizeBytes(), stats.datagramSizeBytes);
assertEquals(param.getDatagramTransferTimeMillis(), stats.datagramTransferTimeMillis);
+ assertEquals(param.getIsDemoMode(), stats.isDemoMode);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
@@ -247,4 +311,170 @@
stats.isSatelliteAllowedInCurrentLocation);
verifyNoMoreInteractions(mPersistAtomsStorage);
}
+
+ @Test
+ public void onCarrierRoamingSatelliteSessionMetrics_withAtoms() throws Exception {
+ SatelliteStats.CarrierRoamingSatelliteSessionParams param =
+ new SatelliteStats.CarrierRoamingSatelliteSessionParams.Builder()
+ .setCarrierId(100)
+ .setIsNtnRoamingInHomeCountry(true)
+ .setTotalSatelliteModeTimeSec(10 * 60)
+ .setNumberOfSatelliteConnections(5)
+ .setAvgDurationOfSatelliteConnectionSec(2 * 60)
+ .setSatelliteConnectionGapMinSec(30)
+ .setSatelliteConnectionGapAvgSec(300)
+ .setSatelliteConnectionGapMaxSec(500)
+ .setRsrpAvg(2)
+ .setRsrpMedian(3)
+ .setRssnrAvg(12)
+ .setRssnrMedian(18)
+ .setCountOfIncomingSms(6)
+ .setCountOfOutgoingSms(11)
+ .setCountOfIncomingMms(9)
+ .setCountOfOutgoingMms(14)
+ .build();
+
+ mSatelliteStats.onCarrierRoamingSatelliteSessionMetrics(param);
+
+ ArgumentCaptor<CarrierRoamingSatelliteSession> captor =
+ ArgumentCaptor.forClass(CarrierRoamingSatelliteSession.class);
+ verify(mPersistAtomsStorage).addCarrierRoamingSatelliteSessionStats(captor.capture());
+ CarrierRoamingSatelliteSession stats = captor.getValue();
+ assertEquals(param.getCarrierId(), stats.carrierId);
+ assertEquals(param.getIsNtnRoamingInHomeCountry(), stats.isNtnRoamingInHomeCountry);
+ assertEquals(param.getTotalSatelliteModeTimeSec(), stats.totalSatelliteModeTimeSec);
+ assertEquals(param.getNumberOfSatelliteConnections(), stats.numberOfSatelliteConnections);
+ assertEquals(param.getAvgDurationOfSatelliteConnectionSec(),
+ stats.avgDurationOfSatelliteConnectionSec);
+ assertEquals(param.getSatelliteConnectionGapMinSec(), stats.satelliteConnectionGapMinSec);
+ assertEquals(param.getSatelliteConnectionGapAvgSec(), stats.satelliteConnectionGapAvgSec);
+ assertEquals(param.getSatelliteConnectionGapMaxSec(), stats.satelliteConnectionGapMaxSec);
+ assertEquals(param.getRsrpAvg(), stats.rsrpAvg);
+ assertEquals(param.getRsrpMedian(), stats.rsrpMedian);
+ assertEquals(param.getRssnrAvg(), stats.rssnrAvg);
+ assertEquals(param.getRssnrMedian(), stats.rssnrMedian);
+ assertEquals(param.getCountOfIncomingSms(), stats.countOfIncomingSms);
+ assertEquals(param.getCountOfOutgoingSms(), stats.countOfOutgoingSms);
+ assertEquals(param.getCountOfIncomingMms(), stats.countOfIncomingMms);
+ assertEquals(param.getCountOfOutgoingMms(), stats.countOfOutgoingMms);
+
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onCarrierRoamingSatelliteControllerStatsMetrics_withAtoms() throws Exception {
+ SatelliteStats.CarrierRoamingSatelliteControllerStatsParams param =
+ new SatelliteStats.CarrierRoamingSatelliteControllerStatsParams.Builder()
+ .setConfigDataSource(4)
+ .setCountOfEntitlementStatusQueryRequest(6)
+ .setCountOfSatelliteConfigUpdateRequest(2)
+ .setCountOfSatelliteNotificationDisplayed(1)
+ .setSatelliteSessionGapMinSec(15)
+ .setSatelliteSessionGapAvgSec(30)
+ .setSatelliteSessionGapMaxSec(45)
+ .build();
+
+ mSatelliteStats.onCarrierRoamingSatelliteControllerStatsMetrics(param);
+
+ ArgumentCaptor<CarrierRoamingSatelliteControllerStats> captor =
+ ArgumentCaptor.forClass(CarrierRoamingSatelliteControllerStats.class);
+ verify(mPersistAtomsStorage).addCarrierRoamingSatelliteControllerStats(captor.capture());
+ CarrierRoamingSatelliteControllerStats stats = captor.getValue();
+ assertEquals(param.getConfigDataSource(), stats.configDataSource);
+ assertEquals(param.getCountOfEntitlementStatusQueryRequest(),
+ stats.countOfEntitlementStatusQueryRequest);
+ assertEquals(param.getCountOfSatelliteConfigUpdateRequest(),
+ stats.countOfSatelliteConfigUpdateRequest);
+ assertEquals(param.getCountOfSatelliteNotificationDisplayed(),
+ stats.countOfSatelliteNotificationDisplayed);
+ assertEquals(param.getSatelliteSessionGapMinSec(), stats.satelliteSessionGapMinSec);
+ assertEquals(param.getSatelliteSessionGapAvgSec(), stats.satelliteSessionGapAvgSec);
+ assertEquals(param.getSatelliteSessionGapMaxSec(), stats.satelliteSessionGapMaxSec);
+
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onSatelliteEntitlementMetrics_withAtoms() throws Exception {
+ SatelliteStats.SatelliteEntitlementParams param =
+ new SatelliteStats.SatelliteEntitlementParams.Builder()
+ .setCarrierId(10)
+ .setResult(500)
+ .setEntitlementStatus(2)
+ .setIsRetry(true)
+ .setCount(5)
+ .build();
+
+ mSatelliteStats.onSatelliteEntitlementMetrics(param);
+
+ ArgumentCaptor<SatelliteEntitlement> captor =
+ ArgumentCaptor.forClass(SatelliteEntitlement.class);
+ verify(mPersistAtomsStorage).addSatelliteEntitlementStats(captor.capture());
+ SatelliteEntitlement stats = captor.getValue();
+ assertEquals(param.getCarrierId(), stats.carrierId);
+ assertEquals(param.getResult(), stats.result);
+ assertEquals(param.getEntitlementStatus(), stats.entitlementStatus);
+ assertEquals(param.getIsRetry(), stats.isRetry);
+ assertEquals(param.getCount(), stats.count);
+
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+ @Test
+ public void onSatelliteConfigUpdaterMetrics_withAtoms() throws Exception {
+ SatelliteStats.SatelliteConfigUpdaterParams param =
+ new SatelliteStats.SatelliteConfigUpdaterParams.Builder()
+ .setConfigVersion(8)
+ .setOemConfigResult(9)
+ .setCarrierConfigResult(7)
+ .setCount(3)
+ .build();
+
+ mSatelliteStats.onSatelliteConfigUpdaterMetrics(param);
+
+ ArgumentCaptor<SatelliteConfigUpdater> captor =
+ ArgumentCaptor.forClass(SatelliteConfigUpdater.class);
+ verify(mPersistAtomsStorage).addSatelliteConfigUpdaterStats(captor.capture());
+ SatelliteConfigUpdater stats = captor.getValue();
+ assertEquals(param.getConfigVersion(), stats.configVersion);
+ assertEquals(param.getOemConfigResult(), stats.oemConfigResult);
+ assertEquals(param.getCarrierConfigResult(), stats.carrierConfigResult);
+ assertEquals(param.getCount(), stats.count);
+
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
+
+
+ @Test
+ public void onSatelliteAccessControllerMetrics_withAtoms() {
+ SatelliteStats.SatelliteAccessControllerParams param =
+ new SatelliteStats.SatelliteAccessControllerParams.Builder()
+ .setAccessControlType(ACCESS_CONTROL_TYPE_CACHED_COUNTRY_CODE)
+ .setLocationQueryTime(TimeUnit.SECONDS.toMillis(1))
+ .setOnDeviceLookupTime(TimeUnit.SECONDS.toMillis(2))
+ .setTotalCheckingTime(TimeUnit.SECONDS.toMillis(3))
+ .setIsAllowed(true)
+ .setIsEmergency(false)
+ .setResult(SATELLITE_RESULT_SUCCESS)
+ .setCountryCodes(new String[]{"AB", "CD"})
+ .setConfigDatasource(CONFIG_DATA_SOURCE_DEVICE_CONFIG)
+ .build();
+
+ mSatelliteStats.onSatelliteAccessControllerMetrics(param);
+
+ ArgumentCaptor<SatelliteAccessController> captor = ArgumentCaptor.forClass(
+ SatelliteAccessController.class);
+ verify(mPersistAtomsStorage).addSatelliteAccessControllerStats(captor.capture());
+ SatelliteAccessController stats = captor.getValue();
+ assertEquals(param.getAccessControlType(), stats.accessControlType);
+ assertEquals(param.getLocationQueryTime(), stats.locationQueryTimeMillis);
+ assertEquals(param.getOnDeviceLookupTime(), stats.onDeviceLookupTimeMillis);
+ assertEquals(param.getTotalCheckingTime(), stats.totalCheckingTimeMillis);
+ assertEquals(param.getIsAllowed(), stats.isAllowed);
+ assertEquals(param.getIsEmergency(), stats.isEmergency);
+ assertEquals(param.getResultCode(), stats.resultCode);
+ assertEquals(param.getCountryCodes(), stats.countryCodes);
+ assertEquals(param.getConfigDataSource(), stats.configDataSource);
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
index 16dab44..27878d1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
@@ -30,15 +30,20 @@
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation.NetworkType;
import android.telephony.NetworkRegistrationInfo;
@@ -58,6 +63,7 @@
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
@@ -76,6 +82,9 @@
private TestableServiceStateStats mServiceStateStats;
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
private static class TestableServiceStateStats extends ServiceStateStats {
private long mTimeMillis = START_TIME_MILLIS;
@@ -1324,6 +1333,34 @@
verifyNoMoreInteractions(mPersistAtomsStorage);
}
+ @Test
+ public void testIsNtn() {
+ // Using default service state for LTE
+ mServiceStateStats.onServiceStateChanged(mServiceState);
+ mServiceStateStats.incTimeMillis(100L);
+ mServiceStateStats.conclude();
+
+ ArgumentCaptor<CellularServiceState> captor =
+ ArgumentCaptor.forClass(CellularServiceState.class);
+ verify(mPersistAtomsStorage)
+ .addCellularServiceStateAndCellularDataServiceSwitch(captor.capture(), eq(null));
+ CellularServiceState state = captor.getValue();
+ assertFalse(state.isNtn);
+
+ reset(mPersistAtomsStorage);
+ reset(mServiceState);
+
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+ mServiceStateStats.onServiceStateChanged(mServiceState);
+ mServiceStateStats.incTimeMillis(100L);
+ mServiceStateStats.conclude();
+
+ verify(mPersistAtomsStorage)
+ .addCellularServiceStateAndCellularDataServiceSwitch(captor.capture(), eq(null));
+ state = captor.getValue();
+ assertTrue(state.isNtn);
+ }
+
private void mockWwanPsRat(@NetworkType int rat) {
mockWwanRat(
NetworkRegistrationInfo.DOMAIN_PS,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
index 58cc516..04d140c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
@@ -34,20 +34,26 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.os.Looper;
+import android.os.PersistableBundle;
import android.telephony.AccessNetworkConstants;
import android.telephony.Annotation.NetworkType;
+import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PreciseDataConnectionState;
@@ -222,7 +228,8 @@
mVoiceCallSessionStats0 = new TestableVoiceCallSessionStats(0, mPhone, mFeatureFlags);
mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
- mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats(1, mSecondPhone, mFeatureFlags);
+ mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats(
+ 1, mSecondPhone, mFeatureFlags);
mVoiceCallSessionStats1.onServiceStateChanged(mSecondServiceState);
doReturn(true).when(mFeatureFlags).vonrEnabledMetric();
@@ -2753,6 +2760,102 @@
assertProtoEquals(expectedRatUsage, ratUsage.get()[0]);
}
+ @Test
+ public void testIsNtn() {
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any())).thenReturn(true);
+
+ mVoiceCallSessionStats0.onImsDial(mImsConnection0);
+ mVoiceCallSessionStats0.setTimeMillis(2200L);
+ mVoiceCallSessionStats0.onImsCallTerminated(mImsConnection0,
+ new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE, 0));
+
+ ArgumentCaptor<VoiceCallSession> callCaptor =
+ ArgumentCaptor.forClass(VoiceCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addVoiceCallSession(callCaptor.capture());
+ VoiceCallSession session = callCaptor.getValue();
+ assertTrue(session.isNtn);
+
+ reset(mPersistAtomsStorage);
+ reset(mServiceState);
+
+ when(mSatelliteController.isInSatelliteModeForCarrierRoaming(any()))
+ .thenReturn(false);
+ mVoiceCallSessionStats0.onImsDial(mImsConnection0);
+ mVoiceCallSessionStats0.setTimeMillis(2200L);
+ mVoiceCallSessionStats0.onImsCallTerminated(mImsConnection0,
+ new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NETWORK_NO_LTE_COVERAGE, 0));
+
+ verify(mPersistAtomsStorage, times(1)).addVoiceCallSession(callCaptor.capture());
+ session = callCaptor.getValue();
+ assertFalse(session.isNtn);
+ }
+
+
+ @Test
+ @SmallTest
+ public void singleCall_supportBusinessCall() {
+ PersistableBundle mCarrierConfig = new PersistableBundle();
+ mCarrierConfig.putBoolean(
+ CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, true);
+ when(mCarrierConfigManager.getConfigForSubId(eq(mPhone.getSubId()),
+ eq(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL)))
+ .thenReturn(mCarrierConfig);
+ setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+ doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+ doReturn(mImsPhone).when(mPhone).getImsPhone();
+ doReturn(false).when(mImsConnection0).isIncoming();
+ doReturn(2000L).when(mImsConnection0).getCreateTime();
+ doReturn(0L).when(mImsConnection0).getDurationMillis();
+ doReturn(mImsCall0).when(mImsConnection0).getCall();
+ doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections();
+ doReturn(2).when(mTelephonyManager).getCallComposerStatus();
+ VoiceCallSession expectedCall =
+ makeSlot0CallProto(
+ VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS,
+ VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO,
+ TelephonyManager.NETWORK_TYPE_LTE,
+ ImsReasonInfo.CODE_REMOTE_CALL_DECLINE);
+ expectedCall.setupDurationMillis = 200;
+ expectedCall.setupFailed = true;
+ expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_EVS_SWB;
+ expectedCall.mainCodecQuality =
+ VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_SUPER_WIDEBAND;
+ expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
+ expectedCall.supportsBusinessCallComposer = true;
+ // 0 is defined as UNKNOWN, adding 1 to original value.
+ expectedCall.callComposerStatus = 3;
+ VoiceCallRatUsage expectedRatUsage =
+ makeRatUsageProto(
+ CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
+ final AtomicReference<VoiceCallRatUsage[]> ratUsage = setupRatUsageCapture();
+
+ mVoiceCallSessionStats0.setTimeMillis(2000L);
+ doReturn(Call.State.DIALING).when(mImsCall0).getState();
+ doReturn(Call.State.DIALING).when(mImsConnection0).getState();
+ mVoiceCallSessionStats0.onImsDial(mImsConnection0);
+ mVoiceCallSessionStats0.setTimeMillis(2100L);
+ mVoiceCallSessionStats0.onAudioCodecChanged(
+ mImsConnection0, ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB);
+ mVoiceCallSessionStats0.setTimeMillis(2200L);
+ doReturn(Call.State.ALERTING).when(mImsCall0).getState();
+ doReturn(Call.State.ALERTING).when(mImsConnection0).getState();
+ mVoiceCallSessionStats0.onCallStateChanged(mImsCall0);
+ mVoiceCallSessionStats0.setTimeMillis(12000L);
+ mVoiceCallSessionStats0.onImsCallTerminated(
+ mImsConnection0, new ImsReasonInfo(ImsReasonInfo.CODE_REMOTE_CALL_DECLINE, 0));
+
+ ArgumentCaptor<VoiceCallSession> callCaptor =
+ ArgumentCaptor.forClass(VoiceCallSession.class);
+ verify(mPersistAtomsStorage, times(1)).addVoiceCallSession(callCaptor.capture());
+ verify(mPersistAtomsStorage, times(1)).addVoiceCallRatUsage(any());
+ verifyNoMoreInteractions(mPersistAtomsStorage);
+ assertProtoEquals(expectedCall, callCaptor.getValue());
+ assertThat(ratUsage.get()).hasLength(1);
+ assertProtoEquals(expectedRatUsage, ratUsage.get()[0]);
+ }
+
private AtomicReference<VoiceCallRatUsage[]> setupRatUsageCapture() {
final AtomicReference<VoiceCallRatUsage[]> ratUsage = new AtomicReference<>(null);
doAnswer(
@@ -2841,6 +2944,7 @@
call.setupBeginMillis = 0L;
call.signalStrengthAtEnd = 2;
call.vonrEnabled = false;
+ call.callComposerStatus = 1;
return call;
}
@@ -2876,6 +2980,7 @@
call.isRoaming = false;
call.setupBeginMillis = 0L;
call.signalStrengthAtEnd = 2;
+ call.callComposerStatus = 1;
return call;
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
index 76cd4ad..8173bbc 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/ControllerMetricsStatsTest.java
@@ -133,36 +133,48 @@
@Test
public void testReportOutgoingDatagramSuccessCount() {
mTestStats.initializeParams();
- int datagramType = SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
- for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType);
+ int[] sosDatagramTypes = {SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP,
+ SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED};
+ for (int datagramType : sosDatagramTypes) {
+ for (int i = 0; i < 10; i++) {
+ mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType, false);
+ }
+ assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
+ assertEquals(10, mTestStats.mCountOfOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
+ assertEquals(10, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail);
+ assertEquals(0, mTestStats.mCountOfProvisionSuccess);
+ assertEquals(0, mTestStats.mCountOfProvisionFail);
+ assertEquals(0, mTestStats.mCountOfDeprovisionSuccess);
+ assertEquals(0, mTestStats.mCountOfDeprovisionFail);
+ assertEquals(0, mTestStats.mTotalServiceUptimeSec);
+ assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
+ assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail);
+ mTestStats.initializeParams();
}
- assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
- assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
- assertEquals(10, mTestStats.mCountOfOutgoingDatagramSuccess);
- assertEquals(0, mTestStats.mCountOfOutgoingDatagramFail);
- assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess);
- assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
- assertEquals(10, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
- assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail);
- assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
- assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail);
- assertEquals(0, mTestStats.mCountOfProvisionSuccess);
- assertEquals(0, mTestStats.mCountOfProvisionFail);
- assertEquals(0, mTestStats.mCountOfDeprovisionSuccess);
- assertEquals(0, mTestStats.mCountOfDeprovisionFail);
- assertEquals(0, mTestStats.mTotalServiceUptimeSec);
- assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
- assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
- mTestStats.initializeParams();
- datagramType = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING;
+ int datagramType = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING;
for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType);
+ mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType, true);
}
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
- assertEquals(10, mTestStats.mCountOfOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfOutgoingDatagramSuccess);
assertEquals(0, mTestStats.mCountOfOutgoingDatagramFail);
assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess);
assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
@@ -177,11 +189,19 @@
assertEquals(0, mTestStats.mTotalServiceUptimeSec);
assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(10, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail);
mTestStats.initializeParams();
- datagramType = SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
+ datagramType = SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType);
+ mControllerMetricsStatsUT.reportOutgoingDatagramSuccessCount(datagramType, false);
}
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
@@ -200,43 +220,63 @@
assertEquals(0, mTestStats.mTotalServiceUptimeSec);
assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(10, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail);
mTestStats.initializeParams();
}
@Test
public void reportOutgoingDatagramFailCount() {
mTestStats.initializeParams();
- int datagramType = SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
- for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType);
+ int[] sosDatagramTypes = {SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP,
+ SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED};
+ for (int datagramType : sosDatagramTypes) {
+ for (int i = 0; i < 10; i++) {
+ mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType, false);
+ }
+ assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfOutgoingDatagramSuccess);
+ assertEquals(10, mTestStats.mCountOfOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
+ assertEquals(10, mTestStats.mCountOfDatagramTypeSosSmsFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail);
+ assertEquals(0, mTestStats.mCountOfProvisionSuccess);
+ assertEquals(0, mTestStats.mCountOfProvisionFail);
+ assertEquals(0, mTestStats.mCountOfDeprovisionSuccess);
+ assertEquals(0, mTestStats.mCountOfDeprovisionFail);
+ assertEquals(0, mTestStats.mTotalServiceUptimeSec);
+ assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
+ assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail);
+ mTestStats.initializeParams();
}
- assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
- assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
- assertEquals(0, mTestStats.mCountOfOutgoingDatagramSuccess);
- assertEquals(10, mTestStats.mCountOfOutgoingDatagramFail);
- assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess);
- assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
- assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
- assertEquals(10, mTestStats.mCountOfDatagramTypeSosSmsFail);
- assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
- assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingFail);
- assertEquals(0, mTestStats.mCountOfProvisionSuccess);
- assertEquals(0, mTestStats.mCountOfProvisionFail);
- assertEquals(0, mTestStats.mCountOfDeprovisionSuccess);
- assertEquals(0, mTestStats.mCountOfDeprovisionFail);
- assertEquals(0, mTestStats.mTotalServiceUptimeSec);
- assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
- assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
- mTestStats.initializeParams();
- datagramType = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING;
+ int datagramType = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING;
for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType);
+ mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType, true);
}
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
assertEquals(0, mTestStats.mCountOfOutgoingDatagramSuccess);
- assertEquals(10, mTestStats.mCountOfOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfOutgoingDatagramFail);
assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess);
assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
@@ -250,11 +290,19 @@
assertEquals(0, mTestStats.mTotalServiceUptimeSec);
assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(10, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail);
mTestStats.initializeParams();
- datagramType = SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
+ datagramType = SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType);
+ mControllerMetricsStatsUT.reportOutgoingDatagramFailCount(datagramType, false);
}
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
@@ -273,6 +321,14 @@
assertEquals(0, mTestStats.mTotalServiceUptimeSec);
assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(10, mTestStats.mCountOfDatagramTypeKeepAliveFail);
mTestStats.initializeParams();
}
@@ -282,7 +338,7 @@
int result = SatelliteManager.SATELLITE_RESULT_SUCCESS;
for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportIncomingDatagramCount(result);
+ mControllerMetricsStatsUT.reportIncomingDatagramCount(result, false);
}
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
@@ -301,18 +357,26 @@
assertEquals(0, mTestStats.mTotalServiceUptimeSec);
assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail);
mTestStats.initializeParams();
result = SatelliteManager.SATELLITE_RESULT_SERVER_ERROR;
for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportIncomingDatagramCount(result);
+ mControllerMetricsStatsUT.reportIncomingDatagramCount(result, true);
}
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
assertEquals(0, mTestStats.mCountOfOutgoingDatagramSuccess);
assertEquals(0, mTestStats.mCountOfOutgoingDatagramFail);
assertEquals(0, mTestStats.mCountOfIncomingDatagramSuccess);
- assertEquals(10, mTestStats.mCountOfIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfIncomingDatagramFail);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsSuccess);
assertEquals(0, mTestStats.mCountOfDatagramTypeSosSmsFail);
assertEquals(0, mTestStats.mCountOfDatagramTypeLocationSharingSuccess);
@@ -324,11 +388,19 @@
assertEquals(0, mTestStats.mTotalServiceUptimeSec);
assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(10, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail);
mTestStats.initializeParams();
result = SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE;
for (int i = 0; i < 10; i++) {
- mControllerMetricsStatsUT.reportIncomingDatagramCount(result);
+ mControllerMetricsStatsUT.reportIncomingDatagramCount(result, false);
}
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsSuccess);
assertEquals(0, mTestStats.mCountOfSatelliteServiceEnablementsFail);
@@ -347,6 +419,14 @@
assertEquals(0, mTestStats.mTotalServiceUptimeSec);
assertEquals(0, mTestStats.mTotalBatteryConsumptionPercent);
assertEquals(0, mTestStats.mTotalBatteryChargedTimeSec);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeSatelliteServiceEnablementsFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeOutgoingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramSuccess);
+ assertEquals(0, mTestStats.mCountOfDemoModeIncomingDatagramFail);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveSuccess);
+ assertEquals(0, mTestStats.mCountOfDatagramTypeKeepAliveFail);
mTestStats.initializeParams();
}
@@ -558,6 +638,14 @@
public int mTotalServiceUptimeSec;
public int mTotalBatteryConsumptionPercent;
public int mTotalBatteryChargedTimeSec;
+ private int mCountOfDemoModeSatelliteServiceEnablementsSuccess = 0;
+ private int mCountOfDemoModeSatelliteServiceEnablementsFail = 0;
+ private int mCountOfDemoModeOutgoingDatagramSuccess = 0;
+ private int mCountOfDemoModeOutgoingDatagramFail = 0;
+ private int mCountOfDemoModeIncomingDatagramSuccess = 0;
+ private int mCountOfDemoModeIncomingDatagramFail = 0;
+ private int mCountOfDatagramTypeKeepAliveSuccess = 0;
+ private int mCountOfDatagramTypeKeepAliveFail = 0;
@Override
public synchronized void onSatelliteControllerMetrics(SatelliteControllerParams param) {
@@ -582,6 +670,18 @@
mTotalServiceUptimeSec += param.getTotalServiceUptimeSec();
mTotalBatteryConsumptionPercent += param.getTotalBatteryConsumptionPercent();
mTotalBatteryChargedTimeSec += param.getTotalBatteryChargedTimeSec();
+ mCountOfDemoModeSatelliteServiceEnablementsSuccess +=
+ param.getCountOfDemoModeSatelliteServiceEnablementsSuccess();
+ mCountOfDemoModeSatelliteServiceEnablementsFail +=
+ param.getCountOfDemoModeSatelliteServiceEnablementsFail();
+ mCountOfDemoModeOutgoingDatagramSuccess +=
+ param.getCountOfDemoModeOutgoingDatagramSuccess();
+ mCountOfDemoModeOutgoingDatagramFail += param.getCountOfDemoModeOutgoingDatagramFail();
+ mCountOfDemoModeIncomingDatagramSuccess +=
+ param.getCountOfDemoModeIncomingDatagramSuccess();
+ mCountOfDemoModeIncomingDatagramFail += param.getCountOfDemoModeIncomingDatagramFail();
+ mCountOfDatagramTypeKeepAliveSuccess += param.getCountOfDatagramTypeKeepAliveSuccess();
+ mCountOfDatagramTypeKeepAliveFail += param.getCountOfDatagramTypeKeepAliveFail();
}
public void initializeParams() {
@@ -602,6 +702,14 @@
mTotalServiceUptimeSec = 0;
mTotalBatteryConsumptionPercent = 0;
mTotalBatteryChargedTimeSec = 0;
+ mCountOfDemoModeSatelliteServiceEnablementsSuccess = 0;
+ mCountOfDemoModeSatelliteServiceEnablementsFail = 0;
+ mCountOfDemoModeOutgoingDatagramSuccess = 0;
+ mCountOfDemoModeOutgoingDatagramFail = 0;
+ mCountOfDemoModeIncomingDatagramSuccess = 0;
+ mCountOfDemoModeIncomingDatagramFail = 0;
+ mCountOfDatagramTypeKeepAliveSuccess = 0;
+ mCountOfDatagramTypeKeepAliveFail = 0;
}
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
new file mode 100644
index 0000000..2961b4d
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramControllerTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
+import static android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.os.Looper;
+import android.telephony.satellite.SatelliteDatagram;
+import android.telephony.satellite.SatelliteManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.TelephonyTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.Consumer;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class DatagramControllerTest extends TelephonyTest {
+ private static final String TAG = "DatagramControllerTest";
+
+ private DatagramController mDatagramControllerUT;
+
+ @Mock private DatagramReceiver mMockDatagramReceiver;
+ @Mock private DatagramDispatcher mMockDatagramDispatcher;
+ @Mock private PointingAppController mMockPointingAppController;
+ @Mock private SatelliteSessionController mMockSatelliteSessionController;
+ @Mock private SatelliteController mMockSatelliteController;
+
+ private static final int SUB_ID = 0;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ MockitoAnnotations.initMocks(this);
+ logd(TAG + " Setup!");
+
+ replaceInstance(DatagramDispatcher.class, "sInstance", null,
+ mMockDatagramDispatcher);
+ replaceInstance(DatagramReceiver.class, "sInstance", null,
+ mMockDatagramReceiver);
+ replaceInstance(SatelliteController.class, "sInstance", null,
+ mMockSatelliteController);
+ replaceInstance(SatelliteSessionController.class, "sInstance", null,
+ mMockSatelliteSessionController);
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+ mDatagramControllerUT = new DatagramController(
+ mContext, Looper.myLooper(), mFeatureFlags, mMockPointingAppController);
+
+ // Move both send and receive to IDLE state
+ mDatagramControllerUT.updateSendStatus(SUB_ID, DATAGRAM_TYPE_UNKNOWN,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0, SATELLITE_RESULT_SUCCESS);
+ mDatagramControllerUT.updateReceiveStatus(SUB_ID, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE, 0,
+ SATELLITE_RESULT_SUCCESS);
+ pushDemoModeSosDatagram(DATAGRAM_TYPE_SOS_MESSAGE);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ logd(TAG + " tearDown");
+ super.tearDown();
+ }
+
+ @Test
+ public void testUpdateSendStatus() throws Exception {
+ testUpdateSendStatus(true, DATAGRAM_TYPE_SOS_MESSAGE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING);
+ testUpdateSendStatus(true, DATAGRAM_TYPE_LOCATION_SHARING,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ testUpdateSendStatus(false, DATAGRAM_TYPE_KEEP_ALIVE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING);
+ pushDemoModeSosDatagram(DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP);
+ testUpdateSendStatus(true, DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING);
+ pushDemoModeSosDatagram(DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED);
+ testUpdateSendStatus(true, DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING);
+ }
+
+ @Test
+ public void testUpdateReceiveStatus() throws Exception {
+ testUpdateReceiveStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ testUpdateReceiveStatus(true, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ testUpdateReceiveStatus(false, SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING);
+ }
+
+ @Test
+ public void testSetDeviceAlignedWithSatellite() throws Exception {
+ testSetDeviceAlignedWithSatellite(true);
+ testSetDeviceAlignedWithSatellite(false);
+ }
+
+ @Test
+ public void testSuppressSendStatusUpdate() throws Exception {
+ // Move to NOT_CONNECTED state
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+
+ clearInvocations(mMockSatelliteSessionController);
+ clearInvocations(mMockPointingAppController);
+ clearInvocations(mMockDatagramReceiver);
+
+ int sendPendingCount = 1;
+ int errorCode = SATELLITE_RESULT_SUCCESS;
+ mDatagramControllerUT.updateSendStatus(SUB_ID, DATAGRAM_TYPE_KEEP_ALIVE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, sendPendingCount, errorCode);
+ verifyZeroInteractions(mMockSatelliteSessionController);
+ verifyZeroInteractions(mMockPointingAppController);
+ verifyZeroInteractions(mMockDatagramReceiver);
+ }
+
+ @Test
+ public void testNeedsWaitingForSatelliteConnected() throws Exception {
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
+ assertFalse(mDatagramControllerUT
+ .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_KEEP_ALIVE));
+
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+
+ int[] sosDatagramTypes = {DATAGRAM_TYPE_SOS_MESSAGE,
+ DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP,
+ DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED};
+ for (int datagramType : sosDatagramTypes) {
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertFalse(mDatagramControllerUT
+ .needsWaitingForSatelliteConnected(DATAGRAM_TYPE_KEEP_ALIVE));
+ assertTrue(mDatagramControllerUT
+ .needsWaitingForSatelliteConnected(datagramType));
+
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertFalse(mDatagramControllerUT
+ .needsWaitingForSatelliteConnected(datagramType));
+
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ assertFalse(mDatagramControllerUT
+ .needsWaitingForSatelliteConnected(datagramType));
+
+ mDatagramControllerUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ assertTrue(mDatagramControllerUT
+ .needsWaitingForSatelliteConnected(datagramType));
+ }
+ }
+
+ private void testUpdateSendStatus(boolean isDemoMode, int datagramType, int sendState) {
+ mDatagramControllerUT.setDemoMode(isDemoMode);
+ clearAllInvocations();
+
+ int sendPendingCount = 1;
+ int errorCode = SATELLITE_RESULT_SUCCESS;
+ mDatagramControllerUT.updateSendStatus(SUB_ID, datagramType, sendState, sendPendingCount,
+ errorCode);
+
+ verify(mMockSatelliteSessionController)
+ .onDatagramTransferStateChanged(eq(sendState), anyInt());
+ verify(mMockPointingAppController).updateSendDatagramTransferState(
+ eq(SUB_ID), eq(datagramType), eq(sendState), eq(sendPendingCount), eq(errorCode));
+
+ if (isDemoMode) {
+ if (sendState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
+ verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ }
+ } else {
+ verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ }
+ }
+
+ private void testUpdateReceiveStatus(boolean isDemoMode, int receiveState) {
+ mDatagramControllerUT.setDemoMode(isDemoMode);
+ clearAllInvocations();
+
+ int receivePendingCount = 1;
+ int errorCode = SATELLITE_RESULT_SUCCESS;
+ mDatagramControllerUT.updateReceiveStatus(
+ SUB_ID, receiveState, receivePendingCount, errorCode);
+
+ verify(mMockSatelliteSessionController)
+ .onDatagramTransferStateChanged(anyInt(), eq(receiveState));
+ verify(mMockPointingAppController).updateReceiveDatagramTransferState(
+ eq(SUB_ID), eq(receiveState), eq(receivePendingCount), eq(errorCode));
+
+ if (isDemoMode && receiveState == SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE) {
+ verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ } else {
+ verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ }
+ }
+
+ private void testSetDeviceAlignedWithSatellite(boolean isAligned) {
+ mDatagramControllerUT.setDemoMode(true);
+ clearAllInvocations();
+
+ mDatagramControllerUT.setDeviceAlignedWithSatellite(isAligned);
+ verify(mMockDatagramDispatcher).setDeviceAlignedWithSatellite(eq(isAligned));
+ verify(mMockDatagramReceiver).setDeviceAlignedWithSatellite(eq(isAligned));
+ if (isAligned) {
+ verify(mMockDatagramReceiver).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ } else {
+ verify(mMockDatagramReceiver, never()).pollPendingSatelliteDatagrams(
+ anyInt(), any(Consumer.class));
+ }
+ }
+
+ private void clearAllInvocations() {
+ clearInvocations(mMockSatelliteSessionController);
+ clearInvocations(mMockPointingAppController);
+ clearInvocations(mMockDatagramReceiver);
+ clearInvocations(mMockDatagramDispatcher);
+ }
+
+ private void pushDemoModeSosDatagram(int datagramType) {
+ String testMessage = "This is a test datagram message";
+ SatelliteDatagram datagram = new SatelliteDatagram(testMessage.getBytes());
+ mDatagramControllerUT.setDemoMode(true);
+ mDatagramControllerUT.pushDemoModeDatagram(datagramType, datagram);
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
index 37ff69a..7094399 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramDispatcherTest.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.satellite;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_TIMEOUT;
+import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
import static com.android.internal.telephony.satellite.DatagramController.SATELLITE_ALIGN_TIMEOUT;
@@ -59,7 +60,9 @@
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
+import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import org.junit.After;
import org.junit.Before;
@@ -83,21 +86,34 @@
private static final int SUB_ID = 0;
private static final int DATAGRAM_TYPE1 = SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE;
private static final int DATAGRAM_TYPE2 = SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING;
+ private static final int DATAGRAM_TYPE3 = SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE;
+ private static final int DATAGRAM_TYPE4 =
+ SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP;
+ private static final int DATAGRAM_TYPE5 =
+ SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED;
+
private static final String TEST_MESSAGE = "This is a test datagram message";
private static final long TEST_EXPIRE_TIMER_SATELLITE_ALIGN = TimeUnit.SECONDS.toMillis(1);
private static final int TEST_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMEOUT_MILLIS =
(int) TimeUnit.SECONDS.toMillis(180);
private static final long TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS =
TimeUnit.SECONDS.toMillis(60);
+ private static final Long TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE = TimeUnit.SECONDS.toMillis(10);
+ private static final long
+ TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS =
+ TimeUnit.SECONDS.toMillis(60);
+ private static final int
+ TEST_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS =
+ (int) TimeUnit.SECONDS.toMillis(60);
- private DatagramDispatcher mDatagramDispatcherUT;
- private TestDatagramDispatcher mTestDemoModeDatagramDispatcher;
+ private TestDatagramDispatcher mDatagramDispatcherUT;
@Mock private DatagramController mMockDatagramController;
@Mock private DatagramReceiver mMockDatagramReceiver;
@Mock private SatelliteModemInterface mMockSatelliteModemInterface;
@Mock private ControllerMetricsStats mMockControllerMetricsStats;
@Mock private SatelliteSessionController mMockSatelliteSessionController;
+ @Mock private SessionMetricsStats mMockSessionMetricsStats;
/** Variables required to send datagram in the unit tests. */
LinkedBlockingQueue<Integer> mResultListener;
@@ -136,11 +152,13 @@
mMockControllerMetricsStats);
replaceInstance(SatelliteSessionController.class, "sInstance", null,
mMockSatelliteSessionController);
+ replaceInstance(SessionMetricsStats.class, "sInstance", null,
+ mMockSessionMetricsStats);
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
- mDatagramDispatcherUT = DatagramDispatcher.make(mContext, Looper.myLooper(),
- mMockDatagramController);
- mTestDemoModeDatagramDispatcher = new TestDatagramDispatcher(mContext, Looper.myLooper(),
+ when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
+ mDatagramDispatcherUT = new TestDatagramDispatcher(mContext, Looper.myLooper(),
+ mFeatureFlags,
mMockDatagramController);
mResultListener = new LinkedBlockingQueue<>(1);
@@ -154,7 +172,6 @@
logd(TAG + " tearDown");
mDatagramDispatcherUT.destroy();
mDatagramDispatcherUT = null;
- mTestDemoModeDatagramDispatcher = null;
mResultListener = null;
mDatagram = null;
mInOrder = null;
@@ -172,185 +189,238 @@
return null;
}).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
anyBoolean(), anyBoolean(), any(Message.class));
- doReturn(true).when(mMockDatagramController)
- .needsWaitingForSatelliteConnected();
- when(mMockDatagramController.getDatagramWaitTimeForConnectedState())
- .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
- mResultListener.clear();
- mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
- processAllMessages();
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
- mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState();
- verifyZeroInteractions(mMockSatelliteModemInterface);
- assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5};
+ for (int datagramType : sosDatagramTypes) {
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSessionMetricsStats);
+ clearInvocations(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(false)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(true)))
+ .thenReturn(
+ TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS);
+ mResultListener.clear();
- mDatagramDispatcherUT.onSatelliteModemStateChanged(
- SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
- processAllMessages();
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT),
+ eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
+ eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
+ verifyZeroInteractions(mMockSatelliteModemInterface);
+ assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
- mInOrder.verify(mMockDatagramController).isPollingInIdleState();
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- verifyNoMoreInteractions(mMockDatagramController);
- verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
- any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
- assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ doReturn(false).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS),
+ eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verifyNoMoreInteractions(mMockDatagramController);
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfSuccessfulOutgoingDatagram(eq(datagramType));
+ verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
- clearInvocations(mMockSatelliteModemInterface);
- clearInvocations(mMockDatagramController);
- mResultListener.clear();
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
- clearInvocations(mMockSatelliteModemInterface);
- clearInvocations(mMockDatagramController);
- mResultListener.clear();
- mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
- processAllMessages();
- verifyZeroInteractions(mMockSatelliteModemInterface);
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
- mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState();
- assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ clearInvocations(mMockSatelliteModemInterface);
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSessionMetricsStats);
+ mResultListener.clear();
+ doReturn(true).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
+ processAllMessages();
+ verifyZeroInteractions(mMockSatelliteModemInterface);
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
+ eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
+ assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
- moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
- processAllMessages();
- verifyZeroInteractions(mMockSatelliteModemInterface);
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- assertEquals(1, mResultListener.size());
- assertThat(mResultListener.peek()).isEqualTo(
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
- assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ moveTimeForward(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
+ processAllMessages();
+ verifyZeroInteractions(mMockSatelliteModemInterface);
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ eq(1),
+ eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID),
+ eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ assertEquals(1, mResultListener.size());
+ assertThat(mResultListener.peek()).isEqualTo(
+ SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfFailedOutgoingDatagram(anyInt(), anyInt());
- mResultListener.clear();
- mDatagramDispatcherUT.onSatelliteModemStateChanged(
- SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
- processAllMessages();
- verifyZeroInteractions(mMockSatelliteModemInterface);
- assertEquals(0, mResultListener.size());
+ mResultListener.clear();
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+ verifyZeroInteractions(mMockSatelliteModemInterface);
+ assertEquals(0, mResultListener.size());
- clearInvocations(mMockSatelliteModemInterface);
- clearInvocations(mMockDatagramController);
- mResultListener.clear();
- mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
- processAllMessages();
- verifyZeroInteractions(mMockSatelliteModemInterface);
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
- mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState();
- assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
- assertEquals(0, mResultListener.size());
+ clearInvocations(mMockSatelliteModemInterface);
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSessionMetricsStats);
+ mResultListener.clear();
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
+ processAllMessages();
+ verifyZeroInteractions(mMockSatelliteModemInterface);
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(
+ eq(SatelliteServiceUtils.isLastSosMessage(datagramType)));
+ assertTrue(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ assertEquals(0, mResultListener.size());
- mDatagramDispatcherUT.onSatelliteModemStateChanged(
- SatelliteManager.SATELLITE_MODEM_STATE_OFF);
- processAllMessages();
- verifyZeroInteractions(mMockSatelliteModemInterface);
- assertEquals(1, mResultListener.size());
- assertThat(mResultListener.peek()).isEqualTo(
- SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
- assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ processAllMessages();
+ verifyZeroInteractions(mMockSatelliteModemInterface);
+ assertEquals(1, mResultListener.size());
+ assertThat(mResultListener.peek()).isEqualTo(
+ SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED);
+ assertFalse(mDatagramDispatcherUT.isDatagramWaitForConnectedStateTimerStarted());
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfFailedOutgoingDatagram(anyInt(), anyInt());
+ }
}
@Test
public void testSendSatelliteDatagram_timeout() throws Exception {
- doAnswer(invocation -> {
- Message message = (Message) invocation.getArguments()[3];
-
- mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
- new AsyncResult(message.obj, null, null))
- .sendToTarget();
-
- // DatagramDispatcher should ignore the second EVENT_SEND_SATELLITE_DATAGRAM_DONE
- mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
- new AsyncResult(message.obj, null, null))
- .sendToTarget();
-
- return null;
- }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
- anyBoolean(), anyBoolean(), any(Message.class));
- doReturn(false).when(mMockDatagramController)
- .needsWaitingForSatelliteConnected();
- when(mMockDatagramController.getDatagramWaitTimeForConnectedState())
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(false)))
.thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(eq(true)))
+ .thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS);
mContextFixture.putIntResource(
R.integer.config_wait_for_datagram_sending_response_timeout_millis,
TEST_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_TIMEOUT_MILLIS);
+ mContextFixture.putIntResource(
+ R.integer.config_wait_for_datagram_sending_response_for_last_message_timeout_millis,
+ TEST_WAIT_FOR_DATAGRAM_SENDING_RESPONSE_FOR_LAST_MESSAGE_TIMEOUT_MILLIS);
mResultListener.clear();
+ int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5};
+ for (int datagramType : sosDatagramTypes) {
+ doAnswer(invocation -> {
+ Message message = (Message) invocation.getArguments()[3];
- mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
- processAllMessages();
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
- mInOrder.verify(mMockDatagramController).isPollingInIdleState();
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- verifyNoMoreInteractions(mMockDatagramController);
- verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
- any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ new AsyncResult(message.obj, null, null))
+ .sendToTarget();
- clearInvocations(mMockSatelliteModemInterface);
- clearInvocations(mMockDatagramController);
- mResultListener.clear();
+ // DatagramDispatcher should ignore the second EVENT_SEND_SATELLITE_DATAGRAM_DONE
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ new AsyncResult(message.obj, null, null))
+ .sendToTarget();
- // No response for the send request from modem
- doNothing().when(mMockSatelliteModemInterface).sendSatelliteDatagram(
- any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ return null;
+ }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(
+ any(SatelliteDatagram.class),
+ anyBoolean(), anyBoolean(), any(Message.class));
+ doReturn(false).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
- mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
- processAllMessages();
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
- mInOrder.verify(mMockDatagramController).isPollingInIdleState();
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), eq(1),
- eq(SATELLITE_RESULT_MODEM_TIMEOUT));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- verifyNoMoreInteractions(mMockDatagramController);
- verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
- any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
- verify(mMockSatelliteModemInterface).abortSendingSatelliteDatagrams(any(Message.class));
- assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_MODEM_TIMEOUT);
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS),
+ eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verifyNoMoreInteractions(mMockDatagramController);
+ verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfSuccessfulOutgoingDatagram(anyInt());
+ clearInvocations(mMockSatelliteModemInterface);
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSessionMetricsStats);
+ mResultListener.clear();
+
+ // No response for the send request from modem
+ doNothing().when(mMockSatelliteModemInterface).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
+ processAllMessages();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController).isPollingInIdleState();
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ eq(1),
+ eq(SATELLITE_RESULT_MODEM_TIMEOUT));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ verifyNoMoreInteractions(mMockDatagramController);
+ verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ verify(mMockSatelliteModemInterface).abortSendingSatelliteDatagrams(any(Message.class));
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_MODEM_TIMEOUT);
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfFailedOutgoingDatagram(anyInt(), anyInt());
+
+ clearInvocations(mMockSatelliteModemInterface);
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSessionMetricsStats);
+ mResultListener.clear();
+ }
}
@Test
@@ -372,98 +442,123 @@
processAllMessages();
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(DATAGRAM_TYPE2));
mInOrder.verify(mMockDatagramController).isPollingInIdleState();
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
+ .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE2),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
+ .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE2),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR));
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
+ .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE2),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
verifyNoMoreInteractions(mMockDatagramController);
assertThat(mResultListener.peek()).isEqualTo(
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfFailedOutgoingDatagram(anyInt(), anyInt());
}
@Test
public void testSendSatelliteDatagram_DemoMode_Align_Success() throws Exception {
doAnswer(invocation -> {
Message message = (Message) invocation.getArguments()[3];
- mTestDemoModeDatagramDispatcher.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
new AsyncResult(message.obj, null, null))
.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
anyBoolean(), anyBoolean(), any(Message.class));
- mTestDemoModeDatagramDispatcher.setDemoMode(true);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(true);
+ mDatagramDispatcherUT.setDemoMode(true);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
+ int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5};
+ for (int datagramType : sosDatagramTypes) {
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSessionMetricsStats);
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
- processAllMessages();
+ processAllMessages();
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
- mTestDemoModeDatagramDispatcher.setDemoMode(false);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS),
+ eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfSuccessfulOutgoingDatagram(eq(datagramType));
+ mDatagramDispatcherUT.setDemoMode(false);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+ }
}
@Test
public void testSendSatelliteDatagram_DemoMode_Align_failed() throws Exception {
doAnswer(invocation -> {
Message message = (Message) invocation.getArguments()[3];
- mTestDemoModeDatagramDispatcher.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
new AsyncResult(message.obj, null, null))
.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
anyBoolean(), anyBoolean(), any(Message.class));
- long previousTimer = mTestDemoModeDatagramDispatcher.getSatelliteAlignedTimeoutDuration();
- mTestDemoModeDatagramDispatcher.setDemoMode(true);
- mTestDemoModeDatagramDispatcher.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
+ long previousTimer = mDatagramDispatcherUT.getSatelliteAlignedTimeoutDuration();
+ mDatagramDispatcherUT.setDemoMode(true);
+ mDatagramDispatcherUT.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+ when(mMockDatagramController.waitForAligningToSatellite(false)).thenReturn(true);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
+ int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5};
+ for (int datagramType : sosDatagramTypes) {
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSessionMetricsStats);
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- processAllFutureMessages();
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
- anyInt(), eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- assertThat(mResultListener.peek()).isEqualTo(
- SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
- mTestDemoModeDatagramDispatcher.setDemoMode(false);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
- mTestDemoModeDatagramDispatcher.setDuration(previousTimer);
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
+ eq(SATELLITE_RESULT_SUCCESS));
+ processAllFutureMessages();
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ anyInt(), eq(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(eq(SUB_ID), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
+ eq(SATELLITE_RESULT_SUCCESS));
+ assertThat(mResultListener.peek()).isEqualTo(
+ SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ verify(mMockDatagramController, never()).pollPendingSatelliteDatagrams(anyInt(), any());
+ verify(mMockDatagramController, never()).pushDemoModeDatagram(
+ anyInt(), any(SatelliteDatagram.class));
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfFailedOutgoingDatagram(anyInt(), anyInt());
+ }
+
+ mDatagramDispatcherUT.setDemoMode(false);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+ mDatagramDispatcherUT.setDuration(previousTimer);
}
@Test
@@ -471,52 +566,61 @@
doAnswer(invocation -> {
Message message = (Message) invocation.getArguments()[3];
mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
- new AsyncResult(message.obj, SatelliteManager.SATELLITE_RESULT_SUCCESS,
+ new AsyncResult(message.obj, SATELLITE_RESULT_SUCCESS,
null)).sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
anyBoolean(), anyBoolean(), any(Message.class));
- mTestDemoModeDatagramDispatcher.setDemoMode(true);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(true);
+ mDatagramDispatcherUT.setDemoMode(true);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone});
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE2, mDatagram,
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE2, mDatagram,
true, mResultListener::offer);
processAllMessages();
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
+ .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE2),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING), eq(1),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
- assertThat(mResultListener.peek()).isEqualTo(SatelliteManager.SATELLITE_RESULT_SUCCESS);
+ assertThat(mResultListener.peek()).isEqualTo(SATELLITE_RESULT_SUCCESS);
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
+ .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE2),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(eq(SUB_ID),
+ .updateSendStatus(eq(SUB_ID), eq(DATAGRAM_TYPE2),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE), eq(0),
- eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(SATELLITE_RESULT_SUCCESS));
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfSuccessfulOutgoingDatagram(eq(DATAGRAM_TYPE2));
- mTestDemoModeDatagramDispatcher.setDemoMode(false);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
+ mDatagramDispatcherUT.setDemoMode(false);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
}
@Test
public void testSatelliteModemBusy_modemPollingDatagram_sendingDelayed() {
when(mMockDatagramController.isPollingInIdleState()).thenReturn(false);
- mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
- processAllMessages();
- // As modem is busy receiving datagrams, sending datagram did not proceed further.
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
- mInOrder.verify(mMockDatagramController, times(2)).isPollingInIdleState();
- verifyNoMoreInteractions(mMockDatagramController);
+ int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5};
+ for (int datagramType : sosDatagramTypes) {
+ clearInvocations(mMockDatagramController);
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
+ processAllMessages();
+ // As modem is busy receiving datagrams, sending datagram did not proceed further.
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(datagramType));
+ mInOrder.verify(mMockDatagramController, times(2)).isPollingInIdleState();
+ verifyNoMoreInteractions(mMockDatagramController);
+ }
}
@Test
@@ -529,22 +633,26 @@
@Test
public void testOnSatelliteModemStateChanged_modemStateOff_modemSendingDatagrams() {
- mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mResultListener::offer);
+ int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5};
+ for (int datagramType : sosDatagramTypes) {
+ clearInvocations(mMockDatagramController);
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mResultListener::offer);
- mDatagramDispatcherUT.onSatelliteModemStateChanged(
- SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ mDatagramDispatcherUT.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_OFF);
- processAllMessages();
+ processAllMessages();
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(anyInt(),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
- eq(1), eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED));
- mInOrder.verify(mMockDatagramController)
- .updateSendStatus(anyInt(),
- eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
- eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(anyInt(), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED),
+ eq(1), eq(SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED));
+ mInOrder.verify(mMockDatagramController)
+ .updateSendStatus(anyInt(), eq(datagramType),
+ eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
+ eq(0), eq(SATELLITE_RESULT_SUCCESS));
+ }
}
@Test
@@ -555,70 +663,107 @@
processAllMessages();
mInOrder.verify(mMockDatagramController)
- .updateSendStatus(anyInt(),
+ .updateSendStatus(anyInt(), anyInt(),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
- eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ eq(0), eq(SATELLITE_RESULT_SUCCESS));
}
@Test
- public void testSendSatelliteDatagramToModemInDemoMode()
- throws Exception {
+ public void testSendSatelliteDatagramToModemInDemoMode() throws Exception {
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
- doAnswer(invocation -> {
- Message message = (Message) invocation.getArguments()[3];
- mTestDemoModeDatagramDispatcher.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
- new AsyncResult(message.obj, null, null))
- .sendToTarget();
- return null;
- }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(any(SatelliteDatagram.class),
- anyBoolean(), anyBoolean(), any(Message.class));
- mTestDemoModeDatagramDispatcher.setDemoMode(true);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(true);
- mIntegerConsumerSemaphore.drainPermits();
+ mDatagramDispatcherUT.setDemoMode(true);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(true);
- // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is true
- mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
- mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, true);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mIntegerConsumer);
- processAllMessages();
- waitForIntegerConsumerResult(1);
- assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
- (int) mIntegerConsumerResult.get(0));
- mIntegerConsumerResult.clear();
- verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
- any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ int[] sosDatagramTypes = {DATAGRAM_TYPE1, DATAGRAM_TYPE4, DATAGRAM_TYPE5};
+ for (int datagramType : sosDatagramTypes) {
+ mIntegerConsumerSemaphore.drainPermits();
+ mIntegerConsumerResult.clear();
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockSatelliteModemInterface);
+ clearInvocations(mMockSessionMetricsStats);
+ doAnswer(invocation -> {
+ Message message = (Message) invocation.getArguments()[3];
+ mDatagramDispatcherUT.obtainMessage(2 /*EVENT_SEND_SATELLITE_DATAGRAM_DONE*/,
+ new AsyncResult(message.obj, null, null))
+ .sendToTarget();
+ return null;
+ }).when(mMockSatelliteModemInterface).sendSatelliteDatagram(
+ any(SatelliteDatagram.class),
+ anyBoolean(), anyBoolean(), any(Message.class));
- // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is false
- reset(mMockSatelliteModemInterface);
- mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
- mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, false);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mIntegerConsumer);
- processAllMessages();
- waitForIntegerConsumerResult(1);
- assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
- (int) mIntegerConsumerResult.get(0));
- mIntegerConsumerResult.clear();
- verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram(
- any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is true
+ mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null);
+ mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode, true);
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mIntegerConsumer);
+ processAllMessages();
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+ waitForIntegerConsumerResult(1);
+ assertEquals(SATELLITE_RESULT_SUCCESS, (int) mIntegerConsumerResult.get(0));
+ mIntegerConsumerResult.clear();
+ verify(mMockSatelliteModemInterface, times(1)).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
- // Send datagram one more time
- reset(mMockSatelliteModemInterface);
- mTestDemoModeDatagramDispatcher.sendSatelliteDatagram(SUB_ID, DATAGRAM_TYPE1, mDatagram,
- true, mIntegerConsumer);
- processAllMessages();
- waitForIntegerConsumerResult(1);
- assertEquals(SatelliteManager.SATELLITE_RESULT_SUCCESS,
- (int) mIntegerConsumerResult.get(0));
- mIntegerConsumerResult.clear();
- verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram(
- any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+ verify(mMockDatagramController).pushDemoModeDatagram(
+ anyInt(), any(SatelliteDatagram.class));
+ verify(mMockDatagramController).pollPendingSatelliteDatagrams(anyInt(), any());
+ verify(mMockSessionMetricsStats, times(1))
+ .addCountOfSuccessfulOutgoingDatagram(anyInt());
- mTestDemoModeDatagramDispatcher.setDemoMode(false);
- mTestDemoModeDatagramDispatcher.setDeviceAlignedWithSatellite(false);
- mTestDemoModeDatagramDispatcher.setShouldSendDatagramToModemInDemoMode(null);
+ // Test when overlay config config_send_satellite_datagram_to_modem_in_demo_mode is
+ // false
+ reset(mMockSatelliteModemInterface);
+ mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null);
+ mContextFixture.putBooleanResource(mConfigSendSatelliteDatagramToModemInDemoMode,
+ false);
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mIntegerConsumer);
+ processAllMessages();
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+
+ waitForIntegerConsumerResult(1);
+ assertEquals(SATELLITE_RESULT_SUCCESS, (int) mIntegerConsumerResult.get(0));
+ mIntegerConsumerResult.clear();
+ verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+ verify(mMockDatagramController, times(2)).pushDemoModeDatagram(
+ anyInt(), any(SatelliteDatagram.class));
+ verify(mMockDatagramController, times(2)).pollPendingSatelliteDatagrams(anyInt(),
+ any());
+
+ // Send datagram one more time
+ reset(mMockSatelliteModemInterface);
+ mDatagramDispatcherUT.sendSatelliteDatagram(SUB_ID, datagramType, mDatagram,
+ true, mIntegerConsumer);
+ processAllMessages();
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+
+ waitForIntegerConsumerResult(1);
+ assertEquals(SATELLITE_RESULT_SUCCESS, (int) mIntegerConsumerResult.get(0));
+ mIntegerConsumerResult.clear();
+ verify(mMockSatelliteModemInterface, never()).sendSatelliteDatagram(
+ any(SatelliteDatagram.class), anyBoolean(), anyBoolean(), any(Message.class));
+
+ moveTimeForward(TIMEOUT_DATAGRAM_DELAY_IN_DEMO_MODE);
+ processAllMessages();
+ verify(mMockDatagramController, times(3)).pushDemoModeDatagram(
+ anyInt(), any(SatelliteDatagram.class));
+ verify(mMockDatagramController, times(3)).pollPendingSatelliteDatagrams(anyInt(),
+ any());
+ }
+
+ mDatagramDispatcherUT.setDemoMode(false);
+ mDatagramDispatcherUT.setDeviceAlignedWithSatellite(false);
+ mDatagramDispatcherUT.setShouldSendDatagramToModemInDemoMode(null);
}
private boolean waitForIntegerConsumerResult(int expectedNumberOfEvents) {
@@ -640,8 +785,9 @@
private long mLong = SATELLITE_ALIGN_TIMEOUT;
TestDatagramDispatcher(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
@NonNull DatagramController datagramController) {
- super(context, looper, datagramController);
+ super(context, looper, featureFlags, datagramController);
}
@Override
@@ -650,7 +796,7 @@
}
@Override
- protected void setDeviceAlignedWithSatellite(boolean isAligned) {
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
super.setDeviceAlignedWithSatellite(isAligned);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
index 3a42881..947661b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DatagramReceiverTest.java
@@ -25,6 +25,7 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.clearInvocations;
@@ -57,7 +58,9 @@
import com.android.internal.telephony.IVoidConsumer;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.satellite.metrics.ControllerMetricsStats;
+import com.android.internal.telephony.satellite.metrics.SessionMetricsStats;
import org.junit.After;
import org.junit.Before;
@@ -90,6 +93,7 @@
@Mock private SatelliteModemInterface mMockSatelliteModemInterface;
@Mock private ControllerMetricsStats mMockControllerMetricsStats;
@Mock private SatelliteSessionController mMockSatelliteSessionController;
+ @Mock private SessionMetricsStats mMockSessionMetricsStats;
/** Variables required to receive datagrams in the unit tests. */
LinkedBlockingQueue<Integer> mResultListener;
@@ -120,10 +124,14 @@
mMockControllerMetricsStats);
replaceInstance(SatelliteSessionController.class, "sInstance", null,
mMockSatelliteSessionController);
+ replaceInstance(SessionMetricsStats.class, "sInstance", null,
+ mMockSessionMetricsStats);
- mDatagramReceiverUT = DatagramReceiver.make(mContext, Looper.myLooper(),
+ when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
+ mDatagramReceiverUT = DatagramReceiver.make(mContext, Looper.myLooper(), mFeatureFlags,
mMockDatagramController);
mTestDemoModeDatagramReceiver = new TestDatagramReceiver(mContext, Looper.myLooper(),
+ mFeatureFlags,
mMockDatagramController);
mSatelliteDatagramListenerHandler = new DatagramReceiver.SatelliteDatagramListenerHandler(
Looper.myLooper(), SUB_ID);
@@ -134,7 +142,8 @@
when(mMockDatagramController.isSendingInIdleState()).thenReturn(true);
when(mMockDatagramController.isPollingInIdleState()).thenReturn(true);
- when(mMockDatagramController.needsWaitingForSatelliteConnected()).thenReturn(false);
+ when(mMockDatagramController.needsWaitingForSatelliteConnected(
+ eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN))).thenReturn(false);
processAllMessages();
}
@@ -163,22 +172,25 @@
.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface).pollPendingSatelliteDatagrams(any(Message.class));
- doReturn(true).when(mMockDatagramController).needsWaitingForSatelliteConnected();
- when(mMockDatagramController.getDatagramWaitTimeForConnectedState())
+ doReturn(true).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN));
+ when(mMockDatagramController.getDatagramWaitTimeForConnectedState(anyBoolean()))
.thenReturn(TEST_DATAGRAM_WAIT_FOR_CONNECTED_STATE_TIMEOUT_MILLIS);
mResultListener.clear();
mDatagramReceiverUT.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
processAllMessages();
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN));
mInOrder.verify(mMockDatagramController).updateReceiveStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_WAITING_TO_CONNECT), eq(0),
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
- mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState();
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(eq(false));
verifyZeroInteractions(mMockSatelliteModemInterface);
assertTrue(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted());
- doReturn(false).when(mMockDatagramController).needsWaitingForSatelliteConnected();
+ doReturn(false).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN));
mDatagramReceiverUT.onSatelliteModemStateChanged(
SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
processAllMessages();
@@ -194,12 +206,15 @@
assertFalse(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted());
clearInvocations(mMockSatelliteModemInterface);
+ clearInvocations(mMockSessionMetricsStats);
mResultListener.clear();
- doReturn(true).when(mMockDatagramController).needsWaitingForSatelliteConnected();
+ doReturn(true).when(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN));
mDatagramReceiverUT.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
processAllMessages();
- mInOrder.verify(mMockDatagramController).needsWaitingForSatelliteConnected();
- mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState();
+ mInOrder.verify(mMockDatagramController)
+ .needsWaitingForSatelliteConnected(eq(SatelliteManager.DATAGRAM_TYPE_UNKNOWN));
+ mInOrder.verify(mMockDatagramController).getDatagramWaitTimeForConnectedState(eq(false));
verifyZeroInteractions(mMockSatelliteModemInterface);
assertTrue(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted());
@@ -215,6 +230,7 @@
assertEquals(1, mResultListener.size());
assertThat(mResultListener.peek()).isEqualTo(
SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ verify(mMockSessionMetricsStats, times(1)).addCountOfFailedIncomingDatagram();
assertFalse(mDatagramReceiverUT.isDatagramWaitForConnectedStateTimerStarted());
mResultListener.clear();
@@ -255,6 +271,8 @@
assertThat(mResultListener.peek()).isEqualTo(
SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR);
+
+ verify(mMockSessionMetricsStats, times(1)).addCountOfFailedIncomingDatagram();
}
@Test
@@ -273,6 +291,8 @@
.updateReceiveStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+
+ verify(mMockSessionMetricsStats, never()).addCountOfFailedIncomingDatagram();
}
@Test
@@ -295,6 +315,7 @@
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE),
eq(0), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
assertTrue(testSatelliteDatagramCallback.waitForOnSatelliteDatagramReceived());
+ verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulIncomingDatagram();
assertTrue(testSatelliteDatagramCallback.sendInternalAck());
try {
@@ -316,6 +337,7 @@
.updateReceiveStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS),
eq(10), eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
+ verify(mMockSessionMetricsStats, times(1)).addCountOfSuccessfulIncomingDatagram();
}
@Test
@@ -323,10 +345,11 @@
// Checks invalid case only as SatelliteController does not exist in unit test
mTestDemoModeDatagramReceiver.setDemoMode(true);
mTestDemoModeDatagramReceiver.setDeviceAlignedWithSatellite(true);
- when(mMockDatagramController.getDemoModeDatagram()).thenReturn(mDatagram);
+ when(mMockDatagramController.popDemoModeDatagram()).thenReturn(mDatagram);
+
mTestDemoModeDatagramReceiver.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
processAllMessages();
- verify(mMockDatagramController, times(1)).getDemoModeDatagram();
+ verify(mMockDatagramController, times(1)).popDemoModeDatagram();
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING),
@@ -353,10 +376,11 @@
mTestDemoModeDatagramReceiver.setDemoMode(true);
mTestDemoModeDatagramReceiver.setDuration(TEST_EXPIRE_TIMER_SATELLITE_ALIGN);
mTestDemoModeDatagramReceiver.setDeviceAlignedWithSatellite(false);
- when(mMockDatagramController.getDemoModeDatagram()).thenReturn(mDatagram);
+ when(mMockDatagramController.waitForAligningToSatellite(false)).thenReturn(true);
+ when(mMockDatagramController.popDemoModeDatagram()).thenReturn(mDatagram);
mTestDemoModeDatagramReceiver.pollPendingSatelliteDatagrams(SUB_ID, mResultListener::offer);
processAllMessages();
- verify(mMockDatagramController, never()).getDemoModeDatagram();
+ verify(mMockDatagramController, never()).popDemoModeDatagram();
verify(mMockDatagramController)
.updateReceiveStatus(eq(SUB_ID),
eq(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING),
@@ -375,6 +399,7 @@
eq(SatelliteManager.SATELLITE_RESULT_SUCCESS));
assertThat(mResultListener.peek())
.isEqualTo(SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE);
+ verify(mMockSessionMetricsStats, times(1)).addCountOfFailedIncomingDatagram();
mTestDemoModeDatagramReceiver.setDemoMode(false);
mTestDemoModeDatagramReceiver.setDeviceAlignedWithSatellite(false);
@@ -468,8 +493,9 @@
private long mLong = SATELLITE_ALIGN_TIMEOUT;
TestDatagramReceiver(@NonNull Context context, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags,
@NonNull DatagramController datagramController) {
- super(context, looper, datagramController);
+ super(context, looper, featureFlags, datagramController);
}
@Override
@@ -478,7 +504,7 @@
}
@Override
- protected void setDeviceAlignedWithSatellite(boolean isAligned) {
+ public void setDeviceAlignedWithSatellite(boolean isAligned) {
super.setDeviceAlignedWithSatellite(isAligned);
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java
new file mode 100644
index 0000000..319e39f
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/DemoSimulatorTest.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.satellite;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Looper;
+import android.telephony.satellite.stub.ISatelliteListener;
+import android.telephony.satellite.stub.NtnSignalStrength;
+import android.telephony.satellite.stub.SatelliteModemState;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.TelephonyTest;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Unit tests for DemoSimulator
+ */
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class DemoSimulatorTest extends TelephonyTest {
+ private static final String TAG = "DemoSimulatorTest";
+ private static final long TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS = 200L;
+ private static final long TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS = 300L;
+ private static final String STATE_POWER_OFF = "PowerOffState";
+ private static final String STATE_NOT_CONNECTED = "NotConnectedState";
+ private static final String STATE_CONNECTED = "ConnectedState";
+
+ private TestDemoSimulator mTestDemoSimulator;
+ @Mock private ISatelliteListener mISatelliteListener;
+
+ @Mock private SatelliteController mMockSatelliteController;
+
+ @Before
+ public void setUp() throws Exception {
+ super.setUp(getClass().getSimpleName());
+ MockitoAnnotations.initMocks(this);
+
+ when(mMockSatelliteController.isDemoModeEnabled()).thenReturn(true);
+ when(mMockSatelliteController.getDemoPointingAlignedDurationMillis()).thenReturn(
+ TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS);
+ when(mMockSatelliteController.getDemoPointingNotAlignedDurationMillis()).thenReturn(
+ TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS);
+
+ mTestDemoSimulator = new TestDemoSimulator(mContext, Looper.myLooper(),
+ mMockSatelliteController);
+ mTestDemoSimulator.setSatelliteListener(mISatelliteListener);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Test
+ public void testInitialState() {
+ assertNotNull(mTestDemoSimulator);
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ @Test
+ public void testStateTransition() {
+ // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED
+ moveToConnectedState();
+
+ // Device is not aligned with satellite. EVENT_DEVICE_NOT_ALIGNED timer should start
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(false);
+ processAllMessages();
+ assertTrue(mTestDemoSimulator.isDeviceNotAlignedTimerStarted());
+
+ // After timeout, DemoSimulator should move to NOT_CONNECTED state.
+ moveTimeForward(TEST_DEVICE_POINTING_NOT_ALIGNED_DURATION_MILLIS);
+ processAllMessages();
+ assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is OFF. DemoSimulator should move to POWER_OFF state.
+ mTestDemoSimulator.onSatelliteModeOff();
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ @Test
+ public void testNotConnectedState_enter() throws Exception {
+ clearInvocations(mISatelliteListener);
+
+ // State transitions: POWER_OFF -> NOT_CONNECTED
+ moveToNotConnectedState();
+
+ verify(mISatelliteListener).onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ ArgumentCaptor<NtnSignalStrength> ntnSignalStrength = ArgumentCaptor.forClass(
+ NtnSignalStrength.class);
+ verify(mISatelliteListener).onNtnSignalStrengthChanged(ntnSignalStrength.capture());
+ assertEquals(0, ntnSignalStrength.getValue().signalStrengthLevel);
+ }
+
+ @Test
+ public void testNotConnectedState() {
+ // State transitions: POWER_OFF -> NOT_CONNECTED
+ moveToNotConnectedState();
+
+ // Device is aligned with satellite. EVENT_DEVICE_ALIGNED timer should start.
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(true);
+ processAllMessages();
+ assertTrue(mTestDemoSimulator.isDeviceAlignedTimerStarted());
+
+ // Device is not aligned with satellite. EVENT_DEVICE_ALIGNED messages should be removed.
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(false);
+ processAllMessages();
+ assertFalse(mTestDemoSimulator.isDeviceAlignedTimerStarted());
+ assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is OFF. DemoSimulator should move to POWER_OFF state.
+ mTestDemoSimulator.onSatelliteModeOff();
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ @Test
+ public void testConnectedState_enter() throws Exception {
+ clearInvocations(mISatelliteListener);
+
+ // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED
+ moveToConnectedState();
+
+ verify(mISatelliteListener).onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ verify(mISatelliteListener).onSatelliteModemStateChanged(
+ SatelliteModemState.SATELLITE_MODEM_STATE_CONNECTED);
+ ArgumentCaptor<NtnSignalStrength> ntnSignalStrength = ArgumentCaptor.forClass(
+ NtnSignalStrength.class);
+ verify(mISatelliteListener, times(2))
+ .onNtnSignalStrengthChanged(ntnSignalStrength.capture());
+ NtnSignalStrength ntnSignalStrengthOnConnected = ntnSignalStrength.getAllValues().get(1);
+ assertEquals(2, ntnSignalStrengthOnConnected.signalStrengthLevel);
+ }
+
+ @Test
+ public void testConnectedState() {
+ // State transitions: POWER_OFF -> NOT_CONNECTED -> CONNECTED
+ moveToConnectedState();
+
+ // Device is not aligned with satellite. EVENT_DEVICE_NOT_ALIGNED timer should start
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(false);
+ processAllMessages();
+ assertTrue(mTestDemoSimulator.isDeviceNotAlignedTimerStarted());
+
+ // Device is aligned with satellite before timeout.
+ // EVENT_DEVICE_NOT_ALIGNED messages should be removed.
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(true);
+ processAllMessages();
+ assertFalse(mTestDemoSimulator.isDeviceNotAlignedTimerStarted());
+ assertEquals(STATE_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is off. DemoSimulator should move to POWER_OFF state
+ mTestDemoSimulator.onSatelliteModeOff();
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ private void moveToNotConnectedState() {
+ // DemoSimulator will initially be in POWER_OFF state.
+ assertNotNull(mTestDemoSimulator);
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is ON. DemoSimulator should move to NOT_CONNECTED state.
+ mTestDemoSimulator.onSatelliteModeOn();
+ processAllMessages();
+ assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ private void moveToConnectedState() {
+ // DemoSimulator will initially be in POWER_OFF state.
+ assertNotNull(mTestDemoSimulator);
+ processAllMessages();
+ assertEquals(STATE_POWER_OFF, mTestDemoSimulator.getCurrentStateName());
+
+ // Satellite mode is ON. DemoSimulator should move to NOT_CONNECTED state.
+ mTestDemoSimulator.onSatelliteModeOn();
+ processAllMessages();
+ assertEquals(STATE_NOT_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+
+ // Device is aligned with satellite. EVENT_DEVICE_ALIGNED timer should start.
+ mTestDemoSimulator.setDeviceAlignedWithSatellite(true);
+ processAllMessages();
+ assertTrue(mTestDemoSimulator.isDeviceAlignedTimerStarted());
+
+ // After timeout, DemoSimulator should move to CONNECTED state.
+ moveTimeForward(TEST_DEVICE_POINTING_ALIGNED_DURATION_MILLIS);
+ processAllMessages();
+ assertEquals(STATE_CONNECTED, mTestDemoSimulator.getCurrentStateName());
+ }
+
+ private static class TestDemoSimulator extends DemoSimulator {
+
+ TestDemoSimulator(@NonNull Context context, @NonNull Looper looper,
+ @NonNull SatelliteController satelliteController) {
+ super(context, looper, satelliteController);
+ }
+
+ String getCurrentStateName() {
+ return getCurrentState().getName();
+ }
+
+ boolean isDeviceAlignedTimerStarted() {
+ return hasMessages(EVENT_DEVICE_ALIGNED);
+ }
+
+ boolean isDeviceNotAlignedTimerStarted() {
+ return hasMessages(EVENT_DEVICE_NOT_ALIGNED);
+ }
+ }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
index f8827be..873078e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/NtnCapabilityResolverTest.java
@@ -30,6 +30,8 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
import android.annotation.NonNull;
import android.telephony.CellIdentity;
@@ -100,6 +102,7 @@
.mapToInt(Integer::intValue)
.toArray()));
NtnCapabilityResolver.resolveNtnCapability(satelliteNri, SUB_ID);
+ verify(mMockSatelliteController).getSatellitePlmnsForCarrier(anyInt());
assertNotEquals(satelliteNri, originalNri);
assertTrue(satelliteNri.isNonTerrestrialNetwork());
assertTrue(Arrays.equals(mSatelliteSupportedServices,
@@ -118,12 +121,32 @@
.mapToInt(Integer::intValue)
.toArray()));
NtnCapabilityResolver.resolveNtnCapability(cellularNri, SUB_ID);
+ verify(mMockSatelliteController, times(2)).getSatellitePlmnsForCarrier(anyInt());
assertEquals(cellularNri, originalNri);
assertFalse(cellularNri.isNonTerrestrialNetwork());
assertFalse(Arrays.equals(mSatelliteSupportedServices,
cellularNri.getAvailableServices().stream()
.mapToInt(Integer::intValue)
.toArray()));
+
+ // Test resolving an empty-PLMN NetworkRegistrationInfo.
+ NetworkRegistrationInfo emptyPlmnNri = createNetworkRegistrationInfo("");
+ originalNri = new NetworkRegistrationInfo(emptyPlmnNri);
+
+ assertEquals(emptyPlmnNri, originalNri);
+ assertFalse(emptyPlmnNri.isNonTerrestrialNetwork());
+ assertFalse(Arrays.equals(mSatelliteSupportedServices,
+ emptyPlmnNri.getAvailableServices().stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
+ NtnCapabilityResolver.resolveNtnCapability(emptyPlmnNri, SUB_ID);
+ verify(mMockSatelliteController, times(2)).getSatellitePlmnsForCarrier(anyInt());
+ assertEquals(emptyPlmnNri, originalNri);
+ assertFalse(emptyPlmnNri.isNonTerrestrialNetwork());
+ assertFalse(Arrays.equals(mSatelliteSupportedServices,
+ emptyPlmnNri.getAvailableServices().stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
}
private NetworkRegistrationInfo createNetworkRegistrationInfo(@NonNull String registeredPlmn) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
index 3917a32..36d32fe 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/PointingAppControllerTest.java
@@ -76,6 +76,8 @@
private static final String KEY_POINTING_UI_PACKAGE_NAME = "default_pointing_ui_package";
private static final String KEY_POINTING_UI_CLASS_NAME = "default_pointing_ui_class";
private static final String KEY_NEED_FULL_SCREEN = "needFullScreen";
+ private static final String KEY_IS_DEMO_MODE = "isDemoMode";
+ private static final String KEY_IS_EMERGENCY = "isEmergency";
private PointingAppController mPointingAppController;
InOrder mInOrder;
@@ -98,12 +100,13 @@
super.setUp(getClass().getSimpleName());
MockitoAnnotations.initMocks(this);
logd(TAG + " Setup!");
+ when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
mInOrderForPointingUi = inOrder(mContext);
replaceInstance(SatelliteModemInterface.class, "sInstance", null,
mMockSatelliteModemInterface);
replaceInstance(SatelliteController.class, "sInstance", null,
mMockSatelliteController);
- mPointingAppController = new PointingAppController(mContext);
+ mPointingAppController = new PointingAppController(mContext, mFeatureFlags);
mContextFixture.putResource(R.string.config_pointing_ui_package,
KEY_POINTING_UI_PACKAGE_NAME);
mContextFixture.putResource(R.string.config_pointing_ui_class,
@@ -150,6 +153,7 @@
}
private class TestSatelliteTransmissionUpdateCallback
extends ISatelliteTransmissionUpdateCallback.Stub {
+ int mDatagramType;
int mState;
int mSendPendingCount;
int mReceivePendingCount;
@@ -163,8 +167,9 @@
}
@Override
- public void onSendDatagramStateChanged(int state, int sendPendingCount,
+ public void onSendDatagramStateChanged(int datagramType, int state, int sendPendingCount,
int errorCode) {
+ mDatagramType = datagramType;
mState = state;
mSendPendingCount = sendPendingCount;
mErrorCode = errorCode;
@@ -191,6 +196,10 @@
}
}
+ public int getDatagramType() {
+ return mDatagramType;
+ }
+
public int getState() {
return mState;
}
@@ -208,7 +217,7 @@
}
}
- private boolean waitForReceiveDatagramStateChangedRessult(
+ private boolean waitForReceiveDatagramStateChangedResult(
int expectedNumberOfEvents) {
for (int i = 0; i < expectedNumberOfEvents; i++) {
try {
@@ -218,7 +227,7 @@
return false;
}
} catch (Exception ex) {
- loge("waitForReceiveDatagramStateChangedRessult: Got exception=" + ex);
+ loge("waitForReceiveDatagramStateChangedResult: Got exception=" + ex);
return false;
}
}
@@ -306,7 +315,7 @@
@Test
public void testStartPointingUI() throws Exception {
ArgumentCaptor<Intent> startedIntentCaptor = ArgumentCaptor.forClass(Intent.class);
- mPointingAppController.startPointingUI(true);
+ mPointingAppController.startPointingUI(true, true, true);
verify(mContext).startActivity(startedIntentCaptor.capture());
Intent intent = startedIntentCaptor.getValue();
assertEquals(KEY_POINTING_UI_PACKAGE_NAME, intent.getComponent().getPackageName());
@@ -314,19 +323,24 @@
Bundle b = intent.getExtras();
assertTrue(b.containsKey(KEY_NEED_FULL_SCREEN));
assertTrue(b.getBoolean(KEY_NEED_FULL_SCREEN));
+ assertTrue(b.containsKey(KEY_IS_DEMO_MODE));
+ assertTrue(b.getBoolean(KEY_IS_DEMO_MODE));
+ assertTrue(b.containsKey(KEY_IS_EMERGENCY));
+ assertTrue(b.getBoolean(KEY_IS_EMERGENCY));
}
@Test
public void testRestartPointingUi() throws Exception {
- mPointingAppController.startPointingUI(true);
+ mPointingAppController.startPointingUI(true, false, true);
mInOrderForPointingUi.verify(mContext).startActivity(any(Intent.class));
- testRestartPointingUi(true);
- mPointingAppController.startPointingUI(false);
+ testRestartPointingUi(true, false, true);
+ mPointingAppController.startPointingUI(false, true, false);
mInOrderForPointingUi.verify(mContext).startActivity(any(Intent.class));
- testRestartPointingUi(false);
+ testRestartPointingUi(false, true, false);
}
- private void testRestartPointingUi(boolean expectedFullScreen) {
+ private void testRestartPointingUi(boolean expectedFullScreen, boolean expectedDemoMode,
+ boolean expectedEmergency) {
when(mContext.getPackageManager()).thenReturn(mPackageManager);
doReturn(new String[]{KEY_POINTING_UI_PACKAGE_NAME}).when(mPackageManager)
.getPackagesForUid(anyInt());
@@ -340,6 +354,12 @@
assertTrue(b.containsKey(KEY_NEED_FULL_SCREEN));
// Checking if last value of KEY_NEED_FULL_SCREEN is taken or not
assertEquals(expectedFullScreen, b.getBoolean(KEY_NEED_FULL_SCREEN));
+ assertTrue(b.containsKey(KEY_IS_DEMO_MODE));
+ // Checking if last value of KEY_IS_DEMO_MODE is taken or not
+ assertEquals(expectedDemoMode, b.getBoolean(KEY_IS_DEMO_MODE));
+ assertTrue(b.containsKey(KEY_IS_EMERGENCY));
+ // Checking if last value of KEY_IS_EMERGENCY is taken or not
+ assertEquals(expectedEmergency, b.getBoolean(KEY_IS_EMERGENCY));
}
@Test
@@ -347,9 +367,12 @@
mPointingAppController.registerForSatelliteTransmissionUpdates(SUB_ID,
mSatelliteTransmissionUpdateCallback);
mPointingAppController.updateSendDatagramTransferState(SUB_ID,
+ SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS, 1,
SatelliteManager.SATELLITE_RESULT_SUCCESS);
assertTrue(waitForSendDatagramStateChangedRessult(1));
+ assertEquals(SatelliteManager.DATAGRAM_TYPE_KEEP_ALIVE,
+ mSatelliteTransmissionUpdateCallback.getDatagramType());
assertEquals(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS,
mSatelliteTransmissionUpdateCallback.getState());
assertEquals(1, mSatelliteTransmissionUpdateCallback.getSendPendingCount());
@@ -368,7 +391,7 @@
mPointingAppController.updateReceiveDatagramTransferState(SUB_ID,
SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS, 2,
SatelliteManager.SATELLITE_RESULT_SUCCESS);
- assertTrue(waitForReceiveDatagramStateChangedRessult(1));
+ assertTrue(waitForReceiveDatagramStateChangedResult(1));
assertEquals(SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS,
mSatelliteTransmissionUpdateCallback.getState());
assertEquals(2, mSatelliteTransmissionUpdateCallback.getReceivePendingCount());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteConfigParserTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteConfigParserTest.java
index e4f0255..7b4cf8d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteConfigParserTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteConfigParserTest.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.satellite;
import static junit.framework.Assert.assertNotNull;
+import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
@@ -24,6 +25,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.testing.AndroidTestingRunner;
@@ -34,11 +36,9 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.io.File;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
@@ -182,30 +182,27 @@
@Test
public void testGetSatelliteS2CellFile() {
- final String filePath = "/data/user_de/0/com.android.phone/app_satellite/s2_cell_file";
- Path targetSatS2FilePath = Paths.get(filePath);
-
- SatelliteConfigParser mockedSatelliteConfigParserNull = spy(
+ SatelliteConfigParser spySatelliteConfigParserNull = spy(
new SatelliteConfigParser((byte[]) null));
- assertNotNull(mockedSatelliteConfigParserNull);
- assertNull(mockedSatelliteConfigParserNull.getConfig());
+ assertNotNull(spySatelliteConfigParserNull);
+ assertNull(spySatelliteConfigParserNull.getConfig());
- SatelliteConfigParser mockedSatelliteConfigParserPlaceholder = spy(
+ SatelliteConfigParser spySatelliteConfigParserPlaceholder = spy(
new SatelliteConfigParser("test".getBytes()));
- assertNotNull(mockedSatelliteConfigParserPlaceholder);
- assertNull(mockedSatelliteConfigParserPlaceholder.getConfig());
+ assertNotNull(spySatelliteConfigParserPlaceholder);
+ assertNull(spySatelliteConfigParserPlaceholder.getConfig());
- SatelliteConfigParser mockedSatelliteConfigParser =
+ SatelliteConfigParser spySatelliteConfigParser =
spy(new SatelliteConfigParser(mBytesProtoBuffer));
- SatelliteConfig mockedSatelliteConfig = Mockito.mock(SatelliteConfig.class);
- doReturn(targetSatS2FilePath).when(mockedSatelliteConfig).getSatelliteS2CellFile(any());
- doReturn(mockedSatelliteConfig).when(mockedSatelliteConfigParser).getConfig();
-// assertNotNull(mockedSatelliteConfigParser.getConfig());
-// doReturn(false).when(mockedSatelliteConfigParser).getConfig().isFileExist(any());
-// doReturn(targetSatS2FilePath).when(mockedSatelliteConfigParser).getConfig()
-// .copySatS2FileToPhoneDirectory(any(), any());
- assertEquals(targetSatS2FilePath,
- mockedSatelliteConfigParser.getConfig().getSatelliteS2CellFile(mContext));
+ assertNotNull(spySatelliteConfigParser.getConfig());
+ assertFalse(spySatelliteConfigParser.getConfig().isFileExist(null));
+
+ SatelliteConfig mockedSatelliteConfig = mock(SatelliteConfig.class);
+ File mMockSatS2File = mock(File.class);
+ doReturn(mMockSatS2File).when(mockedSatelliteConfig).getSatelliteS2CellFile(any());
+ doReturn(mockedSatelliteConfig).when(spySatelliteConfigParser).getConfig();
+ assertEquals(mMockSatS2File,
+ spySatelliteConfigParser.getConfig().getSatelliteS2CellFile(mContext));
}
@Test
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
index f1a8de9..da40c32 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteControllerTest.java
@@ -16,8 +16,10 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.CarrierConfigManager.KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL;
import static android.telephony.CarrierConfigManager.KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT;
+import static android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_DATA;
import static android.telephony.SubscriptionManager.SATELLITE_ENTITLEMENT_STATUS;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GOOD;
import static android.telephony.satellite.NtnSignalStrength.NTN_SIGNAL_STRENGTH_GREAT;
@@ -57,6 +59,7 @@
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS;
import static android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS;
+import static com.android.internal.telephony.satellite.SatelliteController.DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS;
import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_MODE_ENABLED_FALSE;
import static com.android.internal.telephony.satellite.SatelliteController.SATELLITE_MODE_ENABLED_TRUE;
@@ -70,6 +73,7 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.anyVararg;
import static org.mockito.ArgumentMatchers.eq;
@@ -99,6 +103,8 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.telephony.CarrierConfigManager;
+import android.telephony.CellSignalStrength;
+import android.telephony.NetworkRegistrationInfo;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.satellite.INtnSignalStrengthCallback;
@@ -106,6 +112,7 @@
import android.telephony.satellite.ISatelliteDatagramCallback;
import android.telephony.satellite.ISatelliteModemStateCallback;
import android.telephony.satellite.ISatelliteProvisionStateCallback;
+import android.telephony.satellite.ISatelliteSupportedStateCallback;
import android.telephony.satellite.ISatelliteTransmissionUpdateCallback;
import android.telephony.satellite.NtnSignalStrength;
import android.telephony.satellite.SatelliteCapabilities;
@@ -170,6 +177,8 @@
private static final int[] ACTIVE_SUB_IDS = {SUB_ID};
private static final int TEST_WAIT_FOR_SATELLITE_ENABLING_RESPONSE_TIMEOUT_MILLIS =
(int) TimeUnit.SECONDS.toMillis(60);
+
+ private static final String SATELLITE_PLMN = "00103";
private List<Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener>>
mCarrierConfigChangedListenerList = new ArrayList<>();
@@ -193,7 +202,9 @@
@Mock private FeatureFlags mFeatureFlags;
@Mock private TelephonyConfigUpdateInstallReceiver mMockTelephonyConfigUpdateInstallReceiver;
@Mock private SatelliteConfigParser mMockConfigParser;
+ @Mock private CellSignalStrength mCellSignalStrength;
@Mock private SatelliteConfig mMockConfig;
+ @Mock private DemoSimulator mMockDemoSimulator;
private Semaphore mIIntegerConsumerSemaphore = new Semaphore(0);
private IIntegerConsumer mIIntegerConsumer = new IIntegerConsumer.Stub() {
@@ -467,12 +478,15 @@
replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[]{mPhone, mPhone2});
replaceInstance(TelephonyConfigUpdateInstallReceiver.class, "sReceiverAdaptorInstance",
null, mMockTelephonyConfigUpdateInstallReceiver);
+ replaceInstance(DemoSimulator.class, "sInstance", null, mMockDemoSimulator);
mServiceState2 = Mockito.mock(ServiceState.class);
when(mPhone.getServiceState()).thenReturn(mServiceState);
when(mPhone.getSubId()).thenReturn(SUB_ID);
+ when(mPhone.getPhoneId()).thenReturn(0);
when(mPhone2.getServiceState()).thenReturn(mServiceState2);
when(mPhone2.getSubId()).thenReturn(SUB_ID1);
+ when(mPhone2.getPhoneId()).thenReturn(1);
mContextFixture.putStringArrayResource(
R.array.config_satellite_providers,
@@ -513,13 +527,23 @@
doReturn(mMockSessionMetricsStats)
.when(mMockSessionMetricsStats).setInitializationResult(anyInt());
doReturn(mMockSessionMetricsStats)
- .when(mMockSessionMetricsStats).setRadioTechnology(anyInt());
+ .when(mMockSessionMetricsStats).setSatelliteTechnology(anyInt());
+ doReturn(mMockSessionMetricsStats)
+ .when(mMockSessionMetricsStats).setTerminationResult(anyInt());
+ doReturn(mMockSessionMetricsStats)
+ .when(mMockSessionMetricsStats).setInitializationProcessingTime(anyLong());
+ doReturn(mMockSessionMetricsStats)
+ .when(mMockSessionMetricsStats).setTerminationProcessingTime(anyLong());
+ doReturn(mMockSessionMetricsStats)
+ .when(mMockSessionMetricsStats).setSessionDurationSec(anyInt());
+ doReturn(mMockSessionMetricsStats)
+ .when(mMockSessionMetricsStats).setIsDemoMode(anyBoolean());
doNothing().when(mMockSessionMetricsStats).reportSessionMetrics();
doReturn(mMockProvisionMetricsStats).when(mMockProvisionMetricsStats)
.setResultCode(anyInt());
doReturn(mMockProvisionMetricsStats).when(mMockProvisionMetricsStats)
- .setIsProvisionRequest(eq(false));
+ .setIsProvisionRequest(anyBoolean());
doNothing().when(mMockProvisionMetricsStats).reportProvisionMetrics();
doNothing().when(mMockControllerMetricsStats).reportDeprovisionCount(anyInt());
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
@@ -557,58 +581,6 @@
}
@Test
- public void testRequestIsSatelliteCommunicationAllowedForCurrentLocation() {
- mSatelliteAllowedSemaphore.drainPermits();
- setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestIsSatelliteCommunicationAllowedForCurrentLocation(SUB_ID,
- mSatelliteAllowedReceiver);
- processAllMessages();
- assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(1));
- assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, mQueriedSatelliteAllowedResultCode);
-
- resetSatelliteControllerUT();
- mSatelliteControllerUT.requestIsSatelliteCommunicationAllowedForCurrentLocation(SUB_ID,
- mSatelliteAllowedReceiver);
- processAllMessages();
- assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, mQueriedSatelliteAllowedResultCode);
-
- resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestIsSatelliteAllowedForCurrentLocation(true,
- SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestIsSatelliteCommunicationAllowedForCurrentLocation(SUB_ID,
- mSatelliteAllowedReceiver);
- processAllMessages();
- assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(1));
- assertEquals(SATELLITE_RESULT_SUCCESS, mQueriedSatelliteAllowedResultCode);
- assertTrue(mQueriedSatelliteAllowed);
-
- resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpNullResponseForRequestIsSatelliteAllowedForCurrentLocation(SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestIsSatelliteCommunicationAllowedForCurrentLocation(SUB_ID,
- mSatelliteAllowedReceiver);
- processAllMessages();
- assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE, mQueriedSatelliteAllowedResultCode);
-
- resetSatelliteControllerUT();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- setUpNullResponseForRequestIsSatelliteAllowedForCurrentLocation(
- SATELLITE_RESULT_INVALID_MODEM_STATE);
- mSatelliteControllerUT.requestIsSatelliteCommunicationAllowedForCurrentLocation(SUB_ID,
- mSatelliteAllowedReceiver);
- processAllMessages();
- assertTrue(waitForRequestIsSatelliteAllowedForCurrentLocationResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, mQueriedSatelliteAllowedResultCode);
- }
-
- @Test
public void testRequestTimeForNextSatelliteVisibility() {
mSatelliteVisibilityTimeSemaphore.drainPermits();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
@@ -737,12 +709,44 @@
}
@Test
+ public void testRadioPowerOff() {
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ NetworkRegistrationInfo satelliteNri = new NetworkRegistrationInfo.Builder()
+ .setIsNonTerrestrialNetwork(true)
+ .setAvailableServices(List.of(NetworkRegistrationInfo.SERVICE_TYPE_DATA))
+ .build();
+ mCarrierConfigBundle.putInt(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 1 * 60);
+ mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ when(mServiceState.getNetworkRegistrationInfoList()).thenReturn(List.of(satelliteNri));
+ when(mServiceState.isUsingNonTerrestrialNetwork()).thenReturn(true);
+ sendServiceStateChangedEvent();
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertEquals(List.of(SERVICE_TYPE_DATA),
+ mSatelliteControllerUT.getCapabilitiesForCarrierRoamingSatelliteMode(mPhone));
+
+ when(mServiceState.isUsingNonTerrestrialNetwork()).thenReturn(false);
+ setRadioPower(false);
+ processAllMessages();
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertEquals(new ArrayList<>(),
+ mSatelliteControllerUT.getCapabilitiesForCarrierRoamingSatelliteMode(mPhone));
+ }
+
+ @Test
public void testRequestSatelliteEnabled() {
mIsSatelliteEnabledSemaphore.drainPermits();
// Fail to enable satellite when SatelliteController is not fully loaded yet.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
@@ -752,7 +756,8 @@
mIIntegerConsumerResults.clear();
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_NOT_SUPPORTED, (long) mIIntegerConsumerResults.get(0));
@@ -767,7 +772,8 @@
verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestIsSatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
@@ -780,13 +786,17 @@
// Successfully enable satellite
mIIntegerConsumerResults.clear();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
- setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
assertEquals(
SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
verify(mMockSatelliteSessionController, times(1)).onSatelliteEnabledStateChanged(eq(true));
@@ -797,7 +807,8 @@
// Successfully disable satellite when radio is turned off.
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
- setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
setRadioPower(false);
mSatelliteControllerUT.onCellularRadioPowerOffRequested();
processAllMessages();
@@ -805,6 +816,7 @@
processAllMessages();
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
assertEquals(
SATELLITE_MODE_ENABLED_FALSE, mSatelliteControllerUT.satelliteModeSettingValue);
verify(mMockSatelliteSessionController, times(2)).onSatelliteEnabledStateChanged(eq(false));
@@ -814,8 +826,9 @@
// Fail to enable satellite when radio is off.
mIIntegerConsumerResults.clear();
- setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
// Radio is not on, can not enable satellite
@@ -829,39 +842,45 @@
mIIntegerConsumerResults.clear();
clearInvocations(mMockPointingAppController);
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
- setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_INVALID_MODEM_STATE);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false,
+ SATELLITE_RESULT_INVALID_MODEM_STATE);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
- verify(mMockPointingAppController, never()).startPointingUI(anyBoolean());
+ verify(mMockPointingAppController, never()).startPointingUI(anyBoolean(), anyBoolean(),
+ anyBoolean());
assertFalse(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+ assertFalse(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
verify(mMockControllerMetricsStats, times(1)).reportServiceEnablementFailCount();
// Successfully enable satellite when radio is on.
mIIntegerConsumerResults.clear();
mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
- setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
assertEquals(SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
verify(mMockSatelliteSessionController, times(2)).onSatelliteEnabledStateChanged(eq(true));
verify(mMockSatelliteSessionController, times(4)).setDemoMode(eq(false));
verify(mMockDatagramController, times(4)).setDemoMode(eq(false));
verify(mMockControllerMetricsStats, times(2)).onSatelliteEnabled();
verify(mMockControllerMetricsStats, times(2)).reportServiceEnablementSuccessCount();
- verify(mMockSessionMetricsStats, times(7)).setInitializationResult(anyInt());
- verify(mMockSessionMetricsStats, times(7)).setRadioTechnology(anyInt());
- verify(mMockSessionMetricsStats, times(7)).reportSessionMetrics();
// Successfully enable satellite when it is already enabled.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -869,7 +888,8 @@
// Fail to enable satellite with a different demo mode when it is already enabled.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, true, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, true, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_ARGUMENTS, (long) mIIntegerConsumerResults.get(0));
@@ -877,8 +897,9 @@
// Successfully disable satellite.
mIIntegerConsumerResults.clear();
- setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -886,7 +907,8 @@
// Disable satellite when satellite is already disabled.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -894,7 +916,8 @@
// Disable satellite with a different demo mode when satellite is already disabled.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, true, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, true, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -902,11 +925,13 @@
// Send a second request while the first request in progress
mIIntegerConsumerResults.clear();
- setUpNoResponseForRequestSatelliteEnabled(true, false);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ setUpNoResponseForRequestSatelliteEnabled(true, false, false);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_REQUEST_IN_PROGRESS, (long) mIIntegerConsumerResults.get(0));
@@ -918,14 +943,16 @@
assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
// Move to satellite-disabling in progress.
- setUpNoResponseForRequestSatelliteEnabled(false, false);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ setUpNoResponseForRequestSatelliteEnabled(false, false, false);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
// Disable is in progress. Thus, a new request to enable satellite will be rejected.
mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_ERROR, (long) mIIntegerConsumerResults.get(0));
@@ -936,20 +963,30 @@
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_INVALID_MODEM_STATE, (long) mIIntegerConsumerResults.get(0));
+ verify(mMockSessionMetricsStats, times(15)).setInitializationResult(anyInt());
+ verify(mMockSessionMetricsStats, times(15)).setSatelliteTechnology(anyInt());
+ verify(mMockSessionMetricsStats, times(3)).setInitializationProcessingTime(anyLong());
+ verify(mMockSessionMetricsStats, times(2)).setTerminationResult(anyInt());
+ verify(mMockSessionMetricsStats, times(2)).setTerminationProcessingTime(anyLong());
+ verify(mMockSessionMetricsStats, times(2)).setSessionDurationSec(anyInt());
+ verify(mMockSessionMetricsStats, times(15)).reportSessionMetrics();
+
/**
* Make areAllRadiosDisabled return false and move mWaitingForRadioDisabled to true, which
* will lead to no response for requestSatelliteEnabled.
*/
mSatelliteControllerUT.allRadiosDisabled = false;
- setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
resetSatelliteControllerUTEnabledState();
mIIntegerConsumerResults.clear();
- setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
processAllMessages();
// We should receive 2 callbacks for the above 2 requests.
assertTrue(waitForIIntegerConsumerResult(2));
@@ -960,15 +997,17 @@
// Repeat the same test as above but with error response from modem for the second request
mSatelliteControllerUT.allRadiosDisabled = false;
- setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
resetSatelliteControllerUTEnabledState();
mIIntegerConsumerResults.clear();
- setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_NO_RESOURCES);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_NO_RESOURCES);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
processAllMessages();
// We should receive 2 callbacks for the above 2 requests.
assertTrue(waitForIIntegerConsumerResult(2));
@@ -1252,7 +1291,7 @@
setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
setUpResponseForRequestIsSatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.onSatelliteServiceConnected();
@@ -1278,6 +1317,7 @@
.registerForSatelliteModemStateChanged(callback);
resetSatelliteControllerUTToSupportedAndProvisionedState();
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
errorCode = mSatelliteControllerUT.registerForSatelliteModemStateChanged(
SUB_ID, callback);
@@ -1298,7 +1338,7 @@
.unregisterForSatelliteModemStateChanged(callback);
resetSatelliteControllerUTToSupportedAndProvisionedState();
-
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
mSatelliteControllerUT.unregisterForModemStateChanged(SUB_ID, callback);
verify(mMockSatelliteSessionController).unregisterForSatelliteModemStateChanged(callback);
}
@@ -1388,45 +1428,54 @@
String mText = "This is a test datagram message from user";
SatelliteDatagram datagram = new SatelliteDatagram(mText.getBytes());
- mIIntegerConsumerResults.clear();
- mSatelliteControllerUT.sendDatagram(SUB_ID,
- SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
- (long) mIIntegerConsumerResults.get(0));
- verify(mMockDatagramController, never()).sendSatelliteDatagram(anyInt(),
- eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE), eq(datagram), eq(true),
- any());
+ int[] sosDatagramTypes = {SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE,
+ SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_STILL_NEED_HELP,
+ SatelliteManager.DATAGRAM_TYPE_LAST_SOS_MESSAGE_NO_HELP_NEEDED};
+ for (int datagramType : sosDatagramTypes) {
+ mSatelliteControllerUT =
+ new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
+ mIIntegerConsumerSemaphore.drainPermits();
+ mIIntegerConsumerResults.clear();
+ clearInvocations(mMockDatagramController);
+ clearInvocations(mMockPointingAppController);
- mIIntegerConsumerResults.clear();
- setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
- sendProvisionedStateChangedEvent(false, null);
- processAllMessages();
- verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.sendDatagram(SUB_ID,
- SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer);
- processAllMessages();
- assertTrue(waitForIIntegerConsumerResult(1));
- assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
- (long) mIIntegerConsumerResults.get(0));
- verify(mMockDatagramController, never()).sendSatelliteDatagram(anyInt(),
- eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE), eq(datagram), eq(true),
- any());
+ mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_INVALID_TELEPHONY_STATE,
+ (long) mIIntegerConsumerResults.get(0));
+ verify(mMockDatagramController, never()).sendSatelliteDatagram(anyInt(),
+ eq(datagramType), eq(datagram), eq(true), any());
- mIIntegerConsumerResults.clear();
- sendProvisionedStateChangedEvent(true, null);
- processAllMessages();
- verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.sendDatagram(SUB_ID,
- SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE, datagram, true, mIIntegerConsumer);
- processAllMessages();
- assertFalse(waitForIIntegerConsumerResult(1));
- verify(mMockDatagramController, times(1)).sendSatelliteDatagram(anyInt(),
- eq(SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE), eq(datagram), eq(true),
- any());
- verify(mMockPointingAppController, times(1)).startPointingUI(eq(true));
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ sendProvisionedStateChangedEvent(false, null);
+ processAllMessages();
+ verifySatelliteProvisioned(false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SERVICE_NOT_PROVISIONED,
+ (long) mIIntegerConsumerResults.get(0));
+ verify(mMockDatagramController, never()).sendSatelliteDatagram(anyInt(),
+ eq(datagramType), eq(datagram), eq(true), any());
+
+ mIIntegerConsumerResults.clear();
+ sendProvisionedStateChangedEvent(true, null);
+ processAllMessages();
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.sendDatagram(SUB_ID, datagramType, datagram, true,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertFalse(waitForIIntegerConsumerResult(1));
+ verify(mMockDatagramController, times(1)).sendSatelliteDatagram(anyInt(),
+ eq(datagramType), eq(datagram), eq(true), any());
+ verify(mMockPointingAppController, times(1)).startPointingUI(eq(true), anyBoolean(),
+ anyBoolean());
+ }
}
@Test
@@ -1686,7 +1735,7 @@
}
@Test
- public void testSupportedSatelliteServices() {
+ public void testSupportedSatelliteServices() throws Exception {
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
List<String> satellitePlmnList = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
SUB_ID);
@@ -1700,6 +1749,7 @@
R.array.config_satellite_providers, satelliteProviderStrArray);
int[] expectedSupportedServices2 = {2};
int[] expectedSupportedServices3 = {1, 3};
+ int[] defaultSupportedServices = {5, 6};
PersistableBundle carrierSupportedSatelliteServicesPerProvider = new PersistableBundle();
carrierSupportedSatelliteServicesPerProvider.putIntArray(
"00102", expectedSupportedServices2);
@@ -1709,6 +1759,9 @@
mCarrierConfigBundle.putPersistableBundle(CarrierConfigManager
.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE,
carrierSupportedSatelliteServicesPerProvider);
+ mCarrierConfigBundle.putIntArray(
+ CarrierConfigManager.KEY_CARRIER_ROAMING_SATELLITE_DEFAULT_SERVICES_INT_ARRAY,
+ defaultSupportedServices);
TestSatelliteController testSatelliteController =
new TestSatelliteController(mContext, Looper.myLooper(), mFeatureFlags);
@@ -1718,6 +1771,9 @@
testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00101");
assertTrue(supportedSatelliteServices.isEmpty());
+ // Add entitlement provided PLMNs.
+ setEntitlementPlmnList(testSatelliteController, SUB_ID,
+ Arrays.asList("00102", "00104", "00105"));
// Carrier config changed with carrierEnabledSatelliteFlag disabled
for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
: mCarrierConfigChangedListenerList) {
@@ -1733,9 +1789,17 @@
supportedSatelliteServices =
testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
assertTrue(supportedSatelliteServices.isEmpty());
+ supportedSatelliteServices =
+ testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ assertTrue(supportedSatelliteServices.isEmpty());
+ supportedSatelliteServices =
+ testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ assertTrue(supportedSatelliteServices.isEmpty());
// Trigger carrier config changed with carrierEnabledSatelliteFlag enabled
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
: mCarrierConfigChangedListenerList) {
pair.first.execute(() -> pair.second.onCarrierConfigChanged(
@@ -1749,6 +1813,7 @@
expectedSupportedSatellitePlmns, satellitePlmnList.stream().toArray()));
supportedSatelliteServices =
mSatelliteControllerUT.getSupportedSatelliteServices(SUB_ID, "00102");
+ // "00101" should return carrier config assigned value, though it is in allowed list.
assertTrue(Arrays.equals(expectedSupportedServices2,
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
@@ -1759,6 +1824,19 @@
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
+ // "00104", and "00105" should return default supported service.
+ supportedSatelliteServices =
+ testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ assertTrue(Arrays.equals(defaultSupportedServices,
+ supportedSatelliteServices.stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
+ supportedSatelliteServices =
+ testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ assertTrue(Arrays.equals(defaultSupportedServices,
+ supportedSatelliteServices.stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
// Subscriptions changed
int[] newActiveSubIds = {SUB_ID1};
@@ -1773,13 +1851,32 @@
satellitePlmnList = testSatelliteController.getSatellitePlmnsForCarrier(SUB_ID);
assertTrue(satellitePlmnList.isEmpty());
+ // "00102" and "00103" should return default supported service for SUB_ID.
supportedSatelliteServices =
testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00102");
- assertTrue(supportedSatelliteServices.isEmpty());
+ assertTrue(Arrays.equals(defaultSupportedServices,
+ supportedSatelliteServices.stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
supportedSatelliteServices =
testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00103");
- assertTrue(supportedSatelliteServices.isEmpty());
-
+ assertTrue(Arrays.equals(defaultSupportedServices,
+ supportedSatelliteServices.stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
+ // "00104", and "00105" should return default supported service for SUB_ID.
+ supportedSatelliteServices =
+ testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00104");
+ assertTrue(Arrays.equals(defaultSupportedServices,
+ supportedSatelliteServices.stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
+ supportedSatelliteServices =
+ testSatelliteController.getSupportedSatelliteServices(SUB_ID, "00105");
+ assertTrue(Arrays.equals(defaultSupportedServices,
+ supportedSatelliteServices.stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
supportedSatelliteServices =
testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00102");
@@ -1795,6 +1892,19 @@
supportedSatelliteServices.stream()
.mapToInt(Integer::intValue)
.toArray()));
+ /* "00104", and "00105" should return default supported service. */
+ supportedSatelliteServices =
+ testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00104");
+ assertTrue(Arrays.equals(defaultSupportedServices,
+ supportedSatelliteServices.stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
+ supportedSatelliteServices =
+ testSatelliteController.getSupportedSatelliteServices(SUB_ID1, "00105");
+ assertTrue(Arrays.equals(defaultSupportedServices,
+ supportedSatelliteServices.stream()
+ .mapToInt(Integer::intValue)
+ .toArray()));
}
@Test
@@ -2154,6 +2264,7 @@
SATELLITE_MODEM_STATE_CONNECTED);
resetSatelliteControllerUTToSupportedAndProvisionedState();
+ mSatelliteControllerUT.setSatelliteSessionController(mMockSatelliteSessionController);
clearInvocations(mMockSatelliteSessionController);
clearInvocations(mMockDatagramController);
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_UNAVAILABLE, null);
@@ -2366,6 +2477,24 @@
doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
provisionSatelliteService();
setUpResponseForStartSendingNtnSignalStrength(expectedResult);
+
+ // but it is ignored because satellite is disabled
+ setUpResponseForRequestIsSatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ sendCmdStartSendingNtnSignalStrengthChangedEvent(true);
+ processAllMessages();
+ verify(mMockSatelliteModemInterface, never())
+ .startSendingNtnSignalStrength(any(Message.class));
+
+ // after satellite is enabled, startSendingNtnSignalStrength() is requested normally
+ resetSatelliteControllerUT();
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ provisionSatelliteService();
+ setUpResponseForStartSendingNtnSignalStrength(expectedResult);
+ setUpResponseForRequestIsSatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ processAllMessages();
sendCmdStartSendingNtnSignalStrengthChangedEvent(true);
processAllMessages();
verify(mMockSatelliteModemInterface, times(1))
@@ -2493,10 +2622,12 @@
}
@Test
- public void testCarrierEnabledSatelliteConnectionHysteresisTime() {
+ public void testCarrierEnabledSatelliteConnectionHysteresisTime() throws Exception {
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
mCarrierConfigBundle.putInt(KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT, 1 * 60);
mCarrierConfigBundle.putBoolean(KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
@@ -2506,15 +2637,28 @@
/*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
);
}
+ doReturn(mSignalStrength).when(mPhone).getSignalStrength();
+ doReturn(mSignalStrength).when(mPhone2).getSignalStrength();
+ List<CellSignalStrength> cellSignalStrengthList = new ArrayList<>();
+ cellSignalStrengthList.add(mCellSignalStrength);
+ doReturn(cellSignalStrengthList).when(mSignalStrength).getCellSignalStrengths();
processAllMessages();
mSatelliteControllerUT.elapsedRealtime = 0;
assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
when(mServiceState.isUsingNonTerrestrialNetwork()).thenReturn(false);
when(mServiceState2.isUsingNonTerrestrialNetwork()).thenReturn(false);
sendServiceStateChangedEvent();
processAllMessages();
assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
+ verify(mPhone, times(1)).notifyCarrierRoamingNtnModeChanged(eq(false));
+ verify(mPhone2, times(1)).notifyCarrierRoamingNtnModeChanged(eq(false));
+ clearInvocations(mPhone);
+ clearInvocations(mPhone2);
// Last satellite connected time of Phone2 should be 0
when(mServiceState2.isUsingNonTerrestrialNetwork()).thenReturn(true);
@@ -2524,6 +2668,12 @@
mSatelliteControllerUT.elapsedRealtime = 2 * 60 * 1000;
// But Phone2 is connected to NTN right now
assertTrue(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertTrue(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
+ verify(mPhone, times(0)).notifyCarrierRoamingNtnModeChanged(eq(false));
+ verify(mPhone2, times(1)).notifyCarrierRoamingNtnModeChanged(eq(true));
+ clearInvocations(mPhone);
+ clearInvocations(mPhone2);
// Last satellite disconnected time of Phone2 should be 2 * 60 * 1000
when(mServiceState2.isUsingNonTerrestrialNetwork()).thenReturn(false);
@@ -2531,10 +2681,22 @@
processAllMessages();
// Current time (2) - last disconnected time (2) < hysteresis timeout (1)
assertTrue(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertTrue(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
+ verify(mPhone, times(0)).notifyCarrierRoamingNtnModeChanged(eq(false));
+ verify(mPhone2, times(0)).notifyCarrierRoamingNtnModeChanged(anyBoolean());
+ clearInvocations(mPhone);
+ clearInvocations(mPhone2);
// Current time (4) - last disconnected time (2) > hysteresis timeout (1)
mSatelliteControllerUT.elapsedRealtime = 4 * 60 * 1000;
+ moveTimeForward(2 * 60 * 1000);
+ processAllMessages();
assertFalse(mSatelliteControllerUT.isSatelliteConnectedViaCarrierWithinHysteresisTime());
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone));
+ assertFalse(mSatelliteControllerUT.isInSatelliteModeForCarrierRoaming(mPhone2));
+ verify(mPhone, times(0)).notifyCarrierRoamingNtnModeChanged(eq(false));
+ verify(mPhone2, times(1)).notifyCarrierRoamingNtnModeChanged(eq(false));
}
@Test
@@ -2667,7 +2829,7 @@
// Verify call the requestSetSatelliteEnabledForCarrier to enable the satellite when
// satellite service is enabled by entitlement server.
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true, new ArrayList<>(),
- mIIntegerConsumer);
+ new ArrayList<>(), mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -2687,7 +2849,7 @@
.when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
setUpResponseForRequestSetSatelliteEnabledForCarrier(false, SATELLITE_RESULT_SUCCESS);
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, new ArrayList<>(),
- mIIntegerConsumer);
+ new ArrayList<>(), mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
@@ -2701,51 +2863,42 @@
throws Exception {
logd("testPassSatellitePlmnToModemAfterUpdateSatelliteEntitlementStatus");
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
mSatelliteControllerUT, new SparseArray<>());
- List<String> overlayConfigPlmnList = new ArrayList<>();
+ List<String> overlayConfigPlmnList = new ArrayList<>();
replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
mSatelliteControllerUT, overlayConfigPlmnList);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL,
+ true);
- // If the PlmnListPerCarrier and the overlay config plmn list are empty verify passing to
- // the modem.
+ // If the entitlement plmn list, the carrier plmn list, the overlay config plmn list and
+ // the barred plmn list are empty, verify not passing to the modem.
+ reset(mMockSatelliteModemInterface);
List<String> entitlementPlmnList = new ArrayList<>();
+ List<String> barredPlmnList = new ArrayList<>();
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
- entitlementPlmnList, mIIntegerConsumer);
+ entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
+ anyBoolean(), anyBoolean(), any(Message.class));
- List<String> plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
- SUB_ID);
- List<String> allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
- plmnListPerCarrier, overlayConfigPlmnList);
-
- assertEquals(new ArrayList<>(), plmnListPerCarrier);
- assertEquals(new ArrayList<>(), allSatellitePlmnList);
- verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
- eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
-
- // If the PlmnListPerCarrier and the overlay config plmn list are exist verify passing
- // the modem.
+ // If the entitlement plmn list and the overlay config plmn list are available and the
+ // carrier plmn list and the barred plmn list are empty, verify passing to the modem.
+ reset(mMockSatelliteModemInterface);
entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "00103"}).toList();
+ List<String> mergedPlmnList = entitlementPlmnList;
overlayConfigPlmnList =
Arrays.stream(new String[]{"00101", "00102", "00104"}).toList();
replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
mSatelliteControllerUT, overlayConfigPlmnList);
+ verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
+ overlayConfigPlmnList, barredPlmnList);
- mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true,
- entitlementPlmnList, mIIntegerConsumer);
-
- plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
- allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
- plmnListPerCarrier, overlayConfigPlmnList);
-
- assertEquals(entitlementPlmnList, plmnListPerCarrier);
- verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
- eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
-
- // If the PlmnListPerCarrier and the overlay config plmn list are exist verify passing
- // the modem.
+ // If the entitlement plmn list, the overlay config plmn list and the carrier plmn list
+ // are available and the barred plmn list is empty, verify passing to the modem.
reset(mMockSatelliteModemInterface);
- entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "00103"}).toList();
Map<Integer, Map<String, Set<Integer>>>
satelliteServicesSupportedByCarriers = new HashMap<>();
List<String> carrierConfigPlmnList = Arrays.stream(new String[]{"00105", "00106"}).toList();
@@ -2755,19 +2908,80 @@
satelliteServicesSupportedByCarriers.put(SUB_ID, plmnAndService);
replaceInstance(SatelliteController.class, "mSatelliteServicesSupportedByCarriers",
mSatelliteControllerUT, satelliteServicesSupportedByCarriers);
- overlayConfigPlmnList = Arrays.stream(new String[]{"00101", "00102", "00104"}).toList();
- replaceInstance(SatelliteController.class, "mSatellitePlmnListFromOverlayConfig",
- mSatelliteControllerUT, overlayConfigPlmnList);
- List<String> mergedPlmnList = entitlementPlmnList;
+ verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
+ overlayConfigPlmnList, barredPlmnList);
- mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true,
- entitlementPlmnList, mIIntegerConsumer);
+ // If the entitlement plmn list is empty and the overlay config plmn list and the carrier
+ // plmn list are available, verify passing to the modem.
+ reset(mMockSatelliteModemInterface);
+ entitlementPlmnList = new ArrayList<>();
+ mergedPlmnList = carrierConfigPlmnList;
+ verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
+ overlayConfigPlmnList, barredPlmnList);
- plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(SUB_ID);
- allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
- plmnListPerCarrier, overlayConfigPlmnList);
+ // If the entitlement plmn list is empty and the overlay config plmn list, the carrier
+ // plmn list and the barred plmn list are available, verify passing to the modem.
+ reset(mMockSatelliteModemInterface);
+ barredPlmnList = Arrays.stream(new String[]{"00105", "00107"}).toList();
+ verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
+ overlayConfigPlmnList, barredPlmnList);
+
+ // If the entitlement plmn list is null and the overlay config plmn list and the carrier
+ // plmn list are available, verify passing to the modem.
+ reset(mMockSatelliteModemInterface);
+ entitlementPlmnList = null;
+ mergedPlmnList = carrierConfigPlmnList;
+ verifyPassingToModemAfterQueryCompleted(entitlementPlmnList, mergedPlmnList,
+ overlayConfigPlmnList, barredPlmnList);
+
+ // If the entitlement plmn list is invalid, verify not passing to the modem.
+ reset(mMockSatelliteModemInterface);
+ entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", ""}).toList();
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
+ anyBoolean(), anyBoolean(), any(Message.class));
+
+ // If the entitlement plmn list is invalid, verify not passing to the modem.
+ reset(mMockSatelliteModemInterface);
+ entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "123456789"}).toList();
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
+ anyBoolean(), anyBoolean(), any(Message.class));
+
+ // If the entitlement plmn list is invalid, verify not passing to the modem.
+ reset(mMockSatelliteModemInterface);
+ entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "12"}).toList();
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
+ anyBoolean(), anyBoolean(), any(Message.class));
+
+ // If the entitlement plmn list is invalid, verify not passing to the modem.
+ reset(mMockSatelliteModemInterface);
+ entitlementPlmnList = Arrays.stream(new String[]{"00101", "00102", "1234"}).toList();
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+ verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
+ anyBoolean(), anyBoolean(), any(Message.class));
+ }
+
+ private void verifyPassingToModemAfterQueryCompleted(List<String> entitlementPlmnList,
+ List<String> mergedPlmnList, List<String> overlayConfigPlmnList,
+ List<String> barredPlmnList) {
+ mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false,
+ entitlementPlmnList, barredPlmnList, mIIntegerConsumer);
+
+ List<String> plmnListPerCarrier = mSatelliteControllerUT.getSatellitePlmnsForCarrier(
+ SUB_ID);
+ List<String> allSatellitePlmnList = SatelliteServiceUtils.mergeStrLists(
+ plmnListPerCarrier, overlayConfigPlmnList, barredPlmnList);
assertEquals(mergedPlmnList, plmnListPerCarrier);
+ if (overlayConfigPlmnList.isEmpty()) {
+ assertEquals(plmnListPerCarrier, allSatellitePlmnList);
+ }
verify(mMockSatelliteModemInterface, times(1)).setSatellitePlmn(anyInt(),
eq(plmnListPerCarrier), eq(allSatellitePlmnList), any(Message.class));
}
@@ -2852,6 +3066,17 @@
mSatelliteControllerUT, entitlementPlmnListPerCarrier);
}
+ private void setEntitlementPlmnList(SatelliteController targetClass, int subId,
+ List<String> plmnList) throws Exception {
+ SparseArray<List<String>> entitlementPlmnListPerCarrier = new SparseArray<>();
+ if (!plmnList.isEmpty()) {
+ entitlementPlmnListPerCarrier.clear();
+ entitlementPlmnListPerCarrier.put(subId, plmnList);
+ }
+ replaceInstance(SatelliteController.class, "mEntitlementPlmnListPerCarrier",
+ targetClass, entitlementPlmnListPerCarrier);
+ }
+
private void setConfigDataPlmnList(List<String> plmnList) {
doReturn(plmnList).when(mMockConfig).getAllSatellitePlmnsForCarrier(anyInt());
doReturn(mMockConfig).when(mMockConfigParser).getConfig();
@@ -2895,8 +3120,11 @@
public void testUpdatePlmnListPerCarrier() throws Exception {
logd("testUpdatePlmnListPerCarrier");
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+
replaceInstance(SatelliteController.class, "mMergedPlmnListPerCarrier",
mSatelliteControllerUT, new SparseArray<>());
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL, true);
List<String> plmnListPerCarrier;
// verify whether an empty list is returned with conditions below
@@ -2957,21 +3185,21 @@
// Change SUB_ID's EntitlementStatus to true
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, true, new ArrayList<>(),
- mIIntegerConsumer);
+ new ArrayList<>(), mIIntegerConsumer);
assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID));
assertEquals(false, satelliteEnabledPerCarrier.get(SUB_ID1));
// Change SUB_ID1's EntitlementStatus to true
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID1, true, new ArrayList<>(),
- mIIntegerConsumer);
+ new ArrayList<>(), mIIntegerConsumer);
assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID));
assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1));
// Change SUB_ID's EntitlementStatus to false
mSatelliteControllerUT.onSatelliteEntitlementStatusUpdated(SUB_ID, false, new ArrayList<>(),
- mIIntegerConsumer);
+ new ArrayList<>(), mIIntegerConsumer);
assertEquals(false, satelliteEnabledPerCarrier.get(SUB_ID));
assertEquals(true, satelliteEnabledPerCarrier.get(SUB_ID1));
@@ -3012,8 +3240,8 @@
logd("testUpdateEntitlementPlmnListPerCarrier");
when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
- // If the Satellite entitlement plmn list read from the DB is empty and carrier config
- // plmn list also is empty , check whether an empty list is returned when calling
+ // If the Satellite entitlement plmn list read from the DB is empty list and carrier
+ // config plmn list also is empty , check whether an empty list is returned when calling
// getSatellitePlmnsForCarrier before the entitlement query.
doReturn(new ArrayList<>()).when(
mMockSubscriptionManagerService).getSatelliteEntitlementPlmnList(anyInt());
@@ -3140,8 +3368,9 @@
// Successfully disable satellite
mIIntegerConsumerResults.clear();
- setUpResponseForRequestSatelliteEnabled(false, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3150,11 +3379,12 @@
// Time out to enable satellite
ArgumentCaptor<Message> enableSatelliteResponse = ArgumentCaptor.forClass(Message.class);
mIIntegerConsumerResults.clear();
- setUpNoResponseForRequestSatelliteEnabled(true, false);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ setUpNoResponseForRequestSatelliteEnabled(true, false, false);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
- verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(true), eq(false),
+ verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(true), eq(false), eq(false),
enableSatelliteResponse.capture());
clearInvocations(mMockSatelliteModemInterface);
@@ -3162,8 +3392,8 @@
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_MODEM_TIMEOUT, (long) mIIntegerConsumerResults.get(0));
- verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(false), eq(false), any(
- Message.class));
+ verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(false), eq(false),
+ eq(false), any(Message.class));
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
// Send the response for the above request to enable satellite. SatelliteController should
@@ -3176,8 +3406,9 @@
// Successfully enable satellite
mIIntegerConsumerResults.clear();
- setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3187,11 +3418,13 @@
ArgumentCaptor<Message> disableSatelliteResponse = ArgumentCaptor.forClass(Message.class);
mIIntegerConsumerResults.clear();
clearInvocations(mMockSatelliteModemInterface);
- setUpNoResponseForRequestSatelliteEnabled(false, false);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, mIIntegerConsumer);
+ setUpNoResponseForRequestSatelliteEnabled(false, false, false);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertFalse(waitForIIntegerConsumerResult(1));
verify(mMockSatelliteModemInterface).requestSatelliteEnabled(eq(false), eq(false),
+ eq(false),
disableSatelliteResponse.capture());
clearInvocations(mMockSatelliteModemInterface);
@@ -3200,7 +3433,7 @@
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_MODEM_TIMEOUT, (long) mIIntegerConsumerResults.get(0));
verify(mMockSatelliteModemInterface, never()).requestSatelliteEnabled(anyBoolean(),
- anyBoolean(), any(Message.class));
+ anyBoolean(), anyBoolean(), any(Message.class));
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
// Send the response for the above request to disable satellite. SatelliteController should
@@ -3212,6 +3445,321 @@
verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
}
+ @Test
+ public void testUpdateNtnSignalStrentghReportWithFeatureFlagEnabled() {
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ mIsSatelliteEnabledSemaphore.drainPermits();
+ mIIntegerConsumerResults.clear();
+ resetSatelliteControllerUT();
+
+ // Successfully provisioned
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ sendProvisionedStateChangedEvent(true, null);
+ setUpResponseForRequestIsSatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ sendProvisionedStateChangedEvent(true, null);
+ processAllMessages();
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+
+ // startSendingNtnSignalStrength should be invoked when satellite is enabled
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
+ assertEquals(
+ SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
+ verify(mMockSatelliteModemInterface, times(1)).startSendingNtnSignalStrength(
+ any(Message.class));
+
+ // Ignore request ntn signal strength for redundant enable request
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteModemInterface, never()).startSendingNtnSignalStrength(
+ any(Message.class));
+
+ // stopSendingNtnSignalStrength should be invoked when satellite is successfully off.
+ mIIntegerConsumerResults.clear();
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteModemInterface, times(1)).stopSendingNtnSignalStrength(
+ any(Message.class));
+
+ // Ignore redundant request for stop reporting ntn signal strength.
+ mIIntegerConsumerResults.clear();
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, false, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+ verify(mMockSatelliteModemInterface, never()).stopSendingNtnSignalStrength(
+ any(Message.class));
+
+ // startSendingNtnSignalStrength is invoked when satellite is enabled again.
+ mIIntegerConsumerResults.clear();
+ reset(mMockSatelliteModemInterface);
+ doReturn(true).when(mMockSatelliteModemInterface).isSatelliteServiceSupported();
+ mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled = false;
+ mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled = false;
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyForSatelliteModeCalled);
+ assertTrue(mSatelliteControllerUT.setSettingsKeyToAllowDeviceRotationCalled);
+ assertEquals(
+ SATELLITE_MODE_ENABLED_TRUE, mSatelliteControllerUT.satelliteModeSettingValue);
+ verify(mMockSatelliteModemInterface, times(1)).startSendingNtnSignalStrength(
+ any(Message.class));
+ }
+
+ @Test
+ public void testRegisterForSatelliteSupportedStateChanged_WithFeatureFlagEnabled() {
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
+
+ Semaphore semaphore = new Semaphore(0);
+ final boolean[] isSupported = new boolean[1];
+ ISatelliteSupportedStateCallback callback =
+ new ISatelliteSupportedStateCallback.Stub() {
+ @Override
+ public void onSatelliteSupportedStateChanged(boolean supported) {
+ logd("onSatelliteSupportedStateChanged: supported=" + supported);
+ isSupported[0] = supported;
+ try {
+ semaphore.release();
+ } catch (Exception ex) {
+ loge("onSatelliteSupportedStateChanged: Got exception in releasing "
+ + "semaphore, ex=" + ex);
+ }
+ }
+ };
+
+ resetSatelliteControllerUT();
+ setUpResponseForRequestIsSatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+ int errorCode = mSatelliteControllerUT.registerForSatelliteSupportedStateChanged(
+ SUB_ID, callback);
+ assertEquals(SATELLITE_RESULT_SUCCESS, errorCode);
+
+ sendSatelliteSupportedStateChangedEvent(true, null);
+ processAllMessages();
+ // Verify redundant report is ignored
+ assertFalse(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+
+ // Verify updated state is reported
+ sendSatelliteSupportedStateChangedEvent(false, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ assertEquals(false, isSupported[0]);
+ verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
+
+ // Verify redundant report is ignored
+ sendSatelliteSupportedStateChangedEvent(false, null);
+ processAllMessages();
+ assertFalse(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ verifySatelliteSupported(false, SATELLITE_RESULT_SUCCESS);
+
+ // Verify updated state is reported
+ sendSatelliteSupportedStateChangedEvent(true, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ assertEquals(true, isSupported[0]);
+ verifySatelliteSupported(true, SATELLITE_RESULT_SUCCESS);
+
+ // Successfully enable satellite
+ sendProvisionedStateChangedEvent(true, null);
+ processAllMessages();
+ verifySatelliteProvisioned(true, SATELLITE_RESULT_SUCCESS);
+ mIIntegerConsumerResults.clear();
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
+ processAllMessages();
+ assertTrue(waitForIIntegerConsumerResult(1));
+ assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
+ verifySatelliteEnabled(true, SATELLITE_RESULT_SUCCESS);
+
+ // Send satellite is not supported state from modem to disable satellite
+ setUpResponseForRequestSatelliteEnabled(false, false, false, SATELLITE_RESULT_SUCCESS);
+ sendSatelliteSupportedStateChangedEvent(false, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ assertEquals(false, isSupported[0]);
+
+ // It is needed to set satellite as support to check whether satellite is enabled or not
+ sendSatelliteSupportedStateChangedEvent(true, null);
+ processAllMessages();
+ assertTrue(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ assertEquals(true, isSupported[0]);
+ // Verify satellite was disabled
+ verifySatelliteEnabled(false, SATELLITE_RESULT_SUCCESS);
+
+ mSatelliteControllerUT.unregisterForSatelliteSupportedStateChanged(SUB_ID, callback);
+ sendSatelliteSupportedStateChangedEvent(true, null);
+ processAllMessages();
+ assertFalse(waitForForEvents(
+ semaphore, 1, "testRegisterForSatelliteSupportedStateChanged"));
+ }
+
+ @Test
+ public void testRegisterForSatelliteSupportedStateChanged_WithFeatureFlagDisabled() {
+ when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(false);
+
+ Semaphore semaphore = new Semaphore(0);
+ ISatelliteSupportedStateCallback callback =
+ new ISatelliteSupportedStateCallback.Stub() {
+ @Override
+ public void onSatelliteSupportedStateChanged(boolean supported) {
+ logd("onSatelliteSupportedStateChanged: supported=" + supported);
+ try {
+ semaphore.release();
+ } catch (Exception ex) {
+ loge("onSatelliteSupportedStateChanged: Got exception in releasing "
+ + "semaphore, ex=" + ex);
+ }
+ }
+ };
+ int errorCode = mSatelliteControllerUT.registerForSatelliteSupportedStateChanged(
+ SUB_ID, callback);
+ assertEquals(SATELLITE_RESULT_REQUEST_NOT_SUPPORTED, errorCode);
+ }
+
+ @Test
+ public void testIsSatelliteEmergencyMessagingSupportedViaCarrier() {
+ // Carrier-enabled flag is off
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
+ assertFalse(mSatelliteControllerUT.isSatelliteEmergencyMessagingSupportedViaCarrier());
+
+ // Carrier-enabled flag is on and satellite attach is not supported
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ assertFalse(mSatelliteControllerUT.isSatelliteEmergencyMessagingSupportedViaCarrier());
+
+ // Trigger carrier config changed to enable satellite attach
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+ assertFalse(mSatelliteControllerUT.isSatelliteEmergencyMessagingSupportedViaCarrier());
+
+ // Trigger carrier config changed to enable satellite attach & emergency messaging
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ mCarrierConfigBundle.putBoolean(
+ CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, true);
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+ assertTrue(mSatelliteControllerUT.isSatelliteEmergencyMessagingSupportedViaCarrier());
+ }
+
+ @Test
+ public void testGetCarrierEmergencyCallWaitForConnectionTimeoutMillis() {
+ // Carrier-enabled flag is off
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(false);
+ assertEquals(DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS,
+ mSatelliteControllerUT.getCarrierEmergencyCallWaitForConnectionTimeoutMillis());
+
+ // Carrier-enabled flag is on
+ when(mFeatureFlags.carrierEnabledSatelliteFlag()).thenReturn(true);
+ assertEquals(DEFAULT_CARRIER_EMERGENCY_CALL_WAIT_FOR_CONNECTION_TIMEOUT_MILLIS,
+ mSatelliteControllerUT.getCarrierEmergencyCallWaitForConnectionTimeoutMillis());
+
+ // Trigger carrier config changed to enable satellite attach
+ int timeoutMillisForCarrier1 = 1000;
+ PersistableBundle carrierConfigBundle1 = new PersistableBundle();
+ carrierConfigBundle1.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ carrierConfigBundle1.putBoolean(
+ CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, true);
+ carrierConfigBundle1.putInt(
+ KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
+ timeoutMillisForCarrier1);
+ doReturn(carrierConfigBundle1)
+ .when(mCarrierConfigManager).getConfigForSubId(eq(SUB_ID), anyVararg());
+
+ int timeoutMillisForCarrier2 = 2000;
+ PersistableBundle carrierConfigBundle2 = new PersistableBundle();
+ carrierConfigBundle2.putBoolean(
+ CarrierConfigManager.KEY_SATELLITE_ATTACH_SUPPORTED_BOOL, true);
+ carrierConfigBundle2.putBoolean(
+ CarrierConfigManager.KEY_EMERGENCY_MESSAGING_SUPPORTED_BOOL, true);
+ carrierConfigBundle2.putInt(
+ KEY_EMERGENCY_CALL_TO_SATELLITE_T911_HANDOVER_TIMEOUT_MILLIS_INT,
+ timeoutMillisForCarrier2);
+ doReturn(carrierConfigBundle2)
+ .when(mCarrierConfigManager).getConfigForSubId(eq(SUB_ID1), anyVararg());
+
+ for (Pair<Executor, CarrierConfigManager.CarrierConfigChangeListener> pair
+ : mCarrierConfigChangedListenerList) {
+ pair.first.execute(() -> pair.second.onCarrierConfigChanged(
+ /*slotIndex*/ 0, /*subId*/ SUB_ID, /*carrierId*/ 0, /*specificCarrierId*/ 0)
+ );
+ }
+ processAllMessages();
+
+ // Both phones are not in satellite mode for carrier roaming, and thus the max timeout
+ // duration - timeoutMillisForCarrier2 - is used
+ assertEquals(timeoutMillisForCarrier2,
+ mSatelliteControllerUT.getCarrierEmergencyCallWaitForConnectionTimeoutMillis());
+
+ // Phone 1 is in satellite mode for carrier roaming
+ when(mServiceState.isUsingNonTerrestrialNetwork()).thenReturn(true);
+ assertEquals(timeoutMillisForCarrier1,
+ mSatelliteControllerUT.getCarrierEmergencyCallWaitForConnectionTimeoutMillis());
+
+ // Both phones are in satellite mode for carrier roaming. The timeout duration of the first
+ // phone will be selected
+ when(mServiceState2.isUsingNonTerrestrialNetwork()).thenReturn(true);
+ assertEquals(timeoutMillisForCarrier1,
+ mSatelliteControllerUT.getCarrierEmergencyCallWaitForConnectionTimeoutMillis());
+ }
+
private void resetSatelliteControllerUTEnabledState() {
logd("resetSatelliteControllerUTEnabledState");
setUpResponseForRequestIsSatelliteSupported(false, SATELLITE_RESULT_RADIO_NOT_AVAILABLE);
@@ -3263,8 +3811,9 @@
setRadioPower(true);
processAllMessages();
- setUpResponseForRequestSatelliteEnabled(true, false, SATELLITE_RESULT_SUCCESS);
- mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, mIIntegerConsumer);
+ setUpResponseForRequestSatelliteEnabled(true, false, false, SATELLITE_RESULT_SUCCESS);
+ mSatelliteControllerUT.requestSatelliteEnabled(SUB_ID, true, false, false,
+ mIIntegerConsumer);
processAllMessages();
assertTrue(waitForIIntegerConsumerResult(1));
assertEquals(SATELLITE_RESULT_SUCCESS, (long) mIIntegerConsumerResults.get(0));
@@ -3296,32 +3845,6 @@
}).when(mMockSatelliteModemInterface).requestIsSatelliteSupported(any(Message.class));
}
- private void setUpResponseForRequestIsSatelliteAllowedForCurrentLocation(
- boolean isSatelliteAllowed, @SatelliteManager.SatelliteResult int error) {
- SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
- ? null : new SatelliteException(error);
- doAnswer(invocation -> {
- Message message = (Message) invocation.getArguments()[0];
- AsyncResult.forMessage(message, isSatelliteAllowed, exception);
- message.sendToTarget();
- return null;
- }).when(mMockSatelliteModemInterface)
- .requestIsSatelliteCommunicationAllowedForCurrentLocation(any(Message.class));
- }
-
- private void setUpNullResponseForRequestIsSatelliteAllowedForCurrentLocation(
- @SatelliteManager.SatelliteResult int error) {
- SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
- ? null : new SatelliteException(error);
- doAnswer(invocation -> {
- Message message = (Message) invocation.getArguments()[0];
- AsyncResult.forMessage(message, null, exception);
- message.sendToTarget();
- return null;
- }).when(mMockSatelliteModemInterface)
- .requestIsSatelliteCommunicationAllowedForCurrentLocation(any(Message.class));
- }
-
private void setUpResponseForRequestTimeForNextSatelliteVisibility(
int satelliteVisibilityTime, @SatelliteManager.SatelliteResult int error) {
SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
@@ -3363,19 +3886,21 @@
}
private void setUpResponseForRequestSatelliteEnabled(
- boolean enabled, boolean demoMode, @SatelliteManager.SatelliteResult int error) {
+ boolean enabled, boolean demoMode, boolean emergency,
+ @SatelliteManager.SatelliteResult int error) {
SatelliteException exception = (error == SATELLITE_RESULT_SUCCESS)
? null : new SatelliteException(error);
doAnswer(invocation -> {
if (exception == null && !enabled) {
sendSatelliteModemStateChangedEvent(SATELLITE_MODEM_STATE_OFF, null);
}
- Message message = (Message) invocation.getArguments()[2];
+ Message message = (Message) invocation.getArguments()[3];
AsyncResult.forMessage(message, null, exception);
message.sendToTarget();
return null;
}).when(mMockSatelliteModemInterface)
- .requestSatelliteEnabled(eq(enabled), eq(demoMode), any(Message.class));
+ .requestSatelliteEnabled(eq(enabled), eq(demoMode), eq(emergency),
+ any(Message.class));
}
private void setUpResponseForRequestSetSatelliteEnabledForCarrier(
@@ -3391,9 +3916,11 @@
.requestSetSatelliteEnabledForCarrier(anyInt(), eq(enabled), any(Message.class));
}
- private void setUpNoResponseForRequestSatelliteEnabled(boolean enabled, boolean demoMode) {
+ private void setUpNoResponseForRequestSatelliteEnabled(boolean enabled, boolean demoMode,
+ boolean emergency) {
doNothing().when(mMockSatelliteModemInterface)
- .requestSatelliteEnabled(eq(enabled), eq(demoMode), any(Message.class));
+ .requestSatelliteEnabled(eq(enabled), eq(demoMode), eq(emergency),
+ any(Message.class));
}
private void setUpResponseForProvisionSatelliteService(
@@ -3545,24 +4072,6 @@
return true;
}
- private boolean waitForRequestIsSatelliteAllowedForCurrentLocationResult(
- int expectedNumberOfEvents) {
- for (int i = 0; i < expectedNumberOfEvents; i++) {
- try {
- if (!mSatelliteAllowedSemaphore.tryAcquire(TIMEOUT, TimeUnit.MILLISECONDS)) {
- loge("Timeout to receive "
- + "requestIsCommunicationAllowedForCurrentLocation()"
- + " callback");
- return false;
- }
- } catch (Exception ex) {
- loge("waitForRequestIsSatelliteSupportedResult: Got exception=" + ex);
- return false;
- }
- }
- return true;
- }
-
private boolean waitForRequestTimeForNextSatelliteVisibilityResult(
int expectedNumberOfEvents) {
for (int i = 0; i < expectedNumberOfEvents; i++) {
@@ -3773,6 +4282,13 @@
msg.sendToTarget();
}
+ private void sendSatelliteSupportedStateChangedEvent(boolean supported, Throwable exception) {
+ Message msg = mSatelliteControllerUT.obtainMessage(
+ 41 /* EVENT_SATELLITE_SUPPORTED_STATE_CHANGED */);
+ msg.obj = new AsyncResult(null, supported, exception);
+ msg.sendToTarget();
+ }
+
private void setRadioPower(boolean on) {
mSimulatedCommands.setRadioPower(on, false, false, null);
}
@@ -3975,6 +4491,7 @@
public boolean allRadiosDisabled = true;
public long elapsedRealtime = 0;
public int satelliteModeSettingValue = SATELLITE_MODE_ENABLED_FALSE;
+ public boolean setSettingsKeyToAllowDeviceRotationCalled = false;
TestSatelliteController(
Context context, Looper looper, @NonNull FeatureFlags featureFlags) {
@@ -3995,6 +4512,12 @@
}
@Override
+ protected void setSettingsKeyToAllowDeviceRotation(int val) {
+ logd("setSettingsKeyToAllowDeviceRotation: val=" + val);
+ setSettingsKeyToAllowDeviceRotationCalled = true;
+ }
+
+ @Override
protected boolean areAllRadiosDisabled() {
return allRadiosDisabled;
}
@@ -4010,5 +4533,9 @@
protected long getElapsedRealtime() {
return elapsedRealtime;
}
+
+ void setSatelliteSessionController(SatelliteSessionController satelliteSessionController) {
+ mSatelliteSessionController = satelliteSessionController;
+ }
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
index d12828a..876fc51 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSOSMessageRecommenderTest.java
@@ -16,6 +16,8 @@
package com.android.internal.telephony.satellite;
+import static android.telephony.ServiceState.STATE_IN_SERVICE;
+import static android.telephony.ServiceState.STATE_OUT_OF_SERVICE;
import static android.telephony.TelephonyManager.EXTRA_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
import static android.telephony.TelephonyManager.EXTRA_EMERGENCY_CALL_TO_SATELLITE_LAUNCH_INTENT;
import static android.telephony.satellite.SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_SOS;
@@ -38,11 +40,13 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Looper;
import android.os.OutcomeReceiver;
import android.os.RemoteException;
import android.telecom.Connection;
+import android.telecom.TelecomManager;
import android.telephony.BinderCacheManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionManager;
@@ -86,7 +90,7 @@
@TestableLooper.RunWithLooper
public class SatelliteSOSMessageRecommenderTest extends TelephonyTest {
private static final String TAG = "SatelliteSOSMessageRecommenderTest";
- private static final long TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS = 500;
+ private static final int TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS = 500;
private static final int PHONE_ID = 0;
private static final int PHONE_ID2 = 1;
private static final String CALL_ID = "CALL_ID";
@@ -96,6 +100,7 @@
"android.com.google.default.SmsMmsApp";
private static final String DEFAULT_HANDOVER_INTENT_ACTION =
"android.com.vendor.action.EMERGENCY_MESSAGING";
+ private static final String DEFAULT_T911_HANDOVER_INTENT_ACTION = Intent.ACTION_SENDTO;
private TestSatelliteController mTestSatelliteController;
private TestImsManager mTestImsManager;
@Mock
@@ -105,6 +110,7 @@
@Mock
private FeatureFlags mFeatureFlags;
private TestConnection mTestConnection;
+ private Uri mTestConnectionAddress = Uri.parse("tel:1234");
private TestSOSMessageRecommender mTestSOSMessageRecommender;
private ServiceState mServiceState2;
@@ -118,12 +124,16 @@
.thenReturn("");
when(mResources.getString(R.string.config_satellite_emergency_handover_intent_action))
.thenReturn(DEFAULT_HANDOVER_INTENT_ACTION);
+ when(mResources.getInteger(
+ R.integer.config_emergency_call_wait_for_connection_timeout_millis))
+ .thenReturn(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
when(mFeatureFlags.oemEnabledSatelliteFlag()).thenReturn(true);
mTestSatelliteController = new TestSatelliteController(mContext,
Looper.myLooper(), mFeatureFlags);
mTestImsManager = new TestImsManager(
mContext, PHONE_ID, mMmTelFeatureConnectionFactory, null, null, null);
mTestConnection = new TestConnection(CALL_ID);
+ mTestConnection.setAddress(mTestConnectionAddress, TelecomManager.PRESENTATION_ALLOWED);
mPhones = new Phone[] {mPhone, mPhone2};
replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
mServiceState2 = Mockito.mock(ServiceState.class);
@@ -132,10 +142,9 @@
when(mPhone2.getServiceState()).thenReturn(mServiceState2);
when(mPhone2.getPhoneId()).thenReturn(PHONE_ID2);
mTestSOSMessageRecommender = new TestSOSMessageRecommender(mContext, Looper.myLooper(),
- mTestSatelliteController, mTestImsManager,
- TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
- when(mServiceState.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
- when(mServiceState2.getState()).thenReturn(ServiceState.STATE_OUT_OF_SERVICE);
+ mTestSatelliteController, mTestImsManager);
+ when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
+ when(mServiceState2.getState()).thenReturn(STATE_OUT_OF_SERVICE);
when(mPhone.isImsRegistered()).thenReturn(false);
when(mPhone2.isImsRegistered()).thenReturn(false);
}
@@ -149,7 +158,7 @@
public void testTimeoutBeforeEmergencyCallEnd_T911() {
testTimeoutBeforeEmergencyCallEnd(EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS,
- DEFAULT_HANDOVER_INTENT_ACTION);
+ DEFAULT_T911_HANDOVER_INTENT_ACTION);
}
@Test
@@ -267,7 +276,7 @@
assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911,
DEFAULT_SATELLITE_MESSAGING_PACKAGE, DEFAULT_SATELLITE_MESSAGING_CLASS,
- DEFAULT_HANDOVER_INTENT_ACTION));
+ DEFAULT_T911_HANDOVER_INTENT_ACTION));
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
mTestSatelliteController.isOemEnabledSatelliteSupported = true;
@@ -284,7 +293,7 @@
}
@Test
- public void testImsRegistrationStateChangedBeforeTimeout() {
+ public void testNetworkStateChangedBeforeTimeout() {
mTestSOSMessageRecommender.isSatelliteAllowedCallback = null;
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
@@ -295,6 +304,7 @@
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
when(mPhone.isImsRegistered()).thenReturn(true);
+ when(mServiceState.getState()).thenReturn(STATE_IN_SERVICE);
mTestImsManager.sendImsRegistrationStateChangedEvent(0, true);
processAllMessages();
@@ -304,18 +314,30 @@
assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0);
when(mPhone.isImsRegistered()).thenReturn(false);
+ when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
+ mTestImsManager.sendImsRegistrationStateChangedEvent(0, true);
+ processAllMessages();
+
+ assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
+ assertTrue(mTestSOSMessageRecommender.isTimerStarted());
+ assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0);
+
+ when(mPhone.isImsRegistered()).thenReturn(false);
when(mPhone2.isImsRegistered()).thenReturn(true);
+ when(mServiceState.getState()).thenReturn(STATE_IN_SERVICE);
mTestImsManager.sendImsRegistrationStateChangedEvent(1, true);
processAllMessages();
assertFalse(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE));
assertFalse(mTestSOSMessageRecommender.isTimerStarted());
- assertEquals(1, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertUnregisterForStateChangedEventsTriggered(mPhone, 0, 0, 0);
when(mPhone2.isImsRegistered()).thenReturn(false);
+ when(mServiceState.getState()).thenReturn(STATE_OUT_OF_SERVICE);
mTestImsManager.sendImsRegistrationStateChangedEvent(1, false);
processAllMessages();
- assertEquals(2, mTestSOSMessageRecommender.getCountOfTimerStarted());
+ assertEquals(3, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertNull(mTestSOSMessageRecommender.isSatelliteAllowedCallback);
// Move Location service to emergency mode
@@ -331,7 +353,7 @@
assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
- DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_HANDOVER_INTENT_ACTION));
+ DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -380,7 +402,7 @@
assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
- DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_HANDOVER_INTENT_ACTION));
+ DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
assertFalse(mTestSOSMessageRecommender.isTimerStarted());
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
assertUnregisterForStateChangedEventsTriggered(mPhone, 2, 4, 2);
@@ -419,7 +441,7 @@
assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
- DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_HANDOVER_INTENT_ACTION));
+ DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -429,7 +451,7 @@
@Test
public void testCellularServiceStateChangedBeforeTimeout_InServiceToOutOfService() {
testCellularServiceStateChangedBeforeTimeout(
- ServiceState.STATE_IN_SERVICE, ServiceState.STATE_OUT_OF_SERVICE);
+ ServiceState.STATE_IN_SERVICE, STATE_OUT_OF_SERVICE);
}
@Test
@@ -441,7 +463,7 @@
@Test
public void testCellularServiceStateChangedBeforeTimeout_EmergencyOnlyToOutOfService() {
testCellularServiceStateChangedBeforeTimeout(
- ServiceState.STATE_EMERGENCY_ONLY, ServiceState.STATE_OUT_OF_SERVICE);
+ ServiceState.STATE_EMERGENCY_ONLY, STATE_OUT_OF_SERVICE);
}
@Test
@@ -505,8 +527,7 @@
TestSOSMessageRecommender testSOSMessageRecommender = new TestSOSMessageRecommender(
mContext,
Looper.myLooper(),
- satelliteController, mTestImsManager,
- TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS);
+ satelliteController, mTestImsManager);
testSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
processAllMessages();
@@ -532,6 +553,32 @@
originalIsSatelliteViaOemProvisioned;
}
+ @Test
+ public void testSelectEmergencyCallWaitForConnectionTimeoutDuration() {
+ // Both OEM and carrier don't support satellite
+ mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = false;
+ mTestSatelliteController.isOemEnabledSatelliteSupported = false;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ processAllMessages();
+ assertEquals(0, mTestSOSMessageRecommender.getTimeOutMillis());
+
+ // Only OEM support satellite
+ mTestSatelliteController.isOemEnabledSatelliteSupported = true;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ processAllMessages();
+ assertEquals(TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS,
+ mTestSOSMessageRecommender.getTimeOutMillis());
+
+ // Both OEM and carrier support satellite. Thus, carrier's timeout duration will be used
+ long carrierTimeoutMillis = 1000;
+ mTestSatelliteController.isSatelliteEmergencyMessagingSupportedViaCarrier = true;
+ mTestSatelliteController.carrierEmergencyCallWaitForConnectionTimeoutMillis =
+ carrierTimeoutMillis;
+ mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
+ processAllMessages();
+ assertEquals(carrierTimeoutMillis, mTestSOSMessageRecommender.getTimeOutMillis());
+ }
+
private void testStopTrackingCallBeforeTimeout(
@Connection.ConnectionState int connectionState) {
mTestSOSMessageRecommender.onEmergencyCallStarted(mTestConnection);
@@ -599,7 +646,7 @@
assertTrue(mTestConnection.isEventSent(TelephonyManager.EVENT_DISPLAY_EMERGENCY_MESSAGE,
EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911, DEFAULT_SATELLITE_MESSAGING_PACKAGE,
- DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_HANDOVER_INTENT_ACTION));
+ DEFAULT_SATELLITE_MESSAGING_CLASS, DEFAULT_T911_HANDOVER_INTENT_ACTION));
assertUnregisterForStateChangedEventsTriggered(mPhone, 1, 2, 1);
assertUnregisterForStateChangedEventsTriggered(mPhone2, 1, 2, 1);
assertEquals(0, mTestSOSMessageRecommender.getCountOfTimerStarted());
@@ -636,6 +683,9 @@
private boolean mIsSatelliteConnectedViaCarrierWithinHysteresisTime = true;
public boolean isOemEnabledSatelliteSupported = true;
public boolean isCarrierEnabledSatelliteSupported = true;
+ public boolean isSatelliteEmergencyMessagingSupportedViaCarrier = true;
+ public long carrierEmergencyCallWaitForConnectionTimeoutMillis =
+ TEST_EMERGENCY_CALL_TO_SOS_MSG_HYSTERESIS_TIMEOUT_MILLIS;
/**
* Create a SatelliteController to act as a backend service of
@@ -696,6 +746,16 @@
return INVALID_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE;
}
+ @Override
+ public boolean isSatelliteEmergencyMessagingSupportedViaCarrier() {
+ return isSatelliteEmergencyMessagingSupportedViaCarrier;
+ }
+
+ @Override
+ public long getCarrierEmergencyCallWaitForConnectionTimeoutMillis() {
+ return carrierEmergencyCallWaitForConnectionTimeoutMillis;
+ }
+
public void setSatelliteConnectedViaCarrierWithinHysteresisTime(
boolean connectedViaCarrier) {
mIsSatelliteConnectedViaCarrierWithinHysteresisTime = connectedViaCarrier;
@@ -811,12 +871,10 @@
* @param imsManager The ImsManager instance associated with the phone, which is
* used for making the emergency call. This argument is not
* null only in unit tests.
- * @param timeoutMillis The timeout duration of the timer.
*/
TestSOSMessageRecommender(Context context, Looper looper,
- SatelliteController satelliteController, ImsManager imsManager,
- long timeoutMillis) {
- super(context, looper, satelliteController, imsManager, timeoutMillis);
+ SatelliteController satelliteController, ImsManager imsManager) {
+ super(context, looper, satelliteController, imsManager);
}
@Override
@@ -843,6 +901,10 @@
public void sendServiceStateChangedEvent() {
sendMessage(obtainMessage(EVENT_SERVICE_STATE_CHANGED));
}
+
+ public long getTimeOutMillis() {
+ return mTimeoutMillis;
+ }
}
private static class TestConnection extends Connection {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
index 28874df..0e4adcd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteServiceUtilsTest.java
@@ -17,6 +17,7 @@
package com.android.internal.telephony.satellite;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.os.PersistableBundle;
@@ -60,6 +61,8 @@
String plmn1 = "10101";
String plmn2 = "10102";
String plmn3 = "10103";
+ String plmn4 = "";
+ String plmn5 = "123456789";
int[] supportedServicesForPlmn1 = {1, 2, 3};
int[] supportedServicesForPlmn2 = {3, 4, 100};
int[] expectedServicesForPlmn1 = {1, 2, 3};
@@ -74,6 +77,8 @@
supportedServicesBundle.putIntArray(plmn1, supportedServicesForPlmn1);
supportedServicesBundle.putIntArray(plmn2, supportedServicesForPlmn2);
supportedServicesBundle.putIntArray(plmn3, new int[0]);
+ supportedServicesBundle.putIntArray(plmn4, supportedServicesForPlmn1);
+ supportedServicesBundle.putIntArray(plmn5, supportedServicesForPlmn2);
supportedServiceMap =
SatelliteServiceUtils.parseSupportedSatelliteServices(supportedServicesBundle);
@@ -96,6 +101,9 @@
assertTrue(supportedServiceMap.containsKey(plmn3));
supportedServices = supportedServiceMap.get(plmn3);
assertTrue(supportedServices.isEmpty());
+
+ assertFalse(supportedServiceMap.containsKey(plmn4));
+ assertFalse(supportedServiceMap.containsKey(plmn5));
}
@Test
@@ -105,5 +113,10 @@
List<String> expectedMergedList = Arrays.asList("1", "2", "3");
List<String> mergedList = SatelliteServiceUtils.mergeStrLists(l1, l2);
assertEquals(expectedMergedList, mergedList);
+
+ List<String> l3 = Arrays.asList("2", "3", "4");
+ expectedMergedList = Arrays.asList("1", "2", "3", "4");
+ mergedList = SatelliteServiceUtils.mergeStrLists(l1, l2, l3);
+ assertEquals(expectedMergedList, mergedList);
}
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
index a1c2cfc..78763d1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/satellite/SatelliteSessionControllerTest.java
@@ -45,6 +45,7 @@
import android.testing.TestableLooper;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
import org.junit.After;
import org.junit.Before;
@@ -53,6 +54,8 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.ArrayList;
+import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -69,6 +72,8 @@
private static final String STATE_UNAVAILABLE = "UnavailableState";
private static final String STATE_POWER_OFF = "PowerOffState";
+ private static final String STATE_ENABLING_SATELLITE = "EnablingState";
+ private static final String STATE_DISABLING_SATELLITE = "DisablingState";
private static final String STATE_IDLE = "IdleState";
private static final String STATE_TRANSFERRING = "TransferringState";
private static final String STATE_LISTENING = "ListeningState";
@@ -101,11 +106,12 @@
Resources resources = mContext.getResources();
when(resources.getInteger(anyInt())).thenReturn(TEST_SATELLITE_TIMEOUT_MILLIS);
+ when(mFeatureFlags.satellitePersistentLogging()).thenReturn(true);
when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(false);
mSatelliteModemInterface = new TestSatelliteModemInterface(
- mContext, mMockSatelliteController, Looper.myLooper());
+ mContext, mMockSatelliteController, Looper.myLooper(), mFeatureFlags);
mTestSatelliteSessionController = new TestSatelliteSessionController(mContext,
- Looper.myLooper(), true, mSatelliteModemInterface);
+ Looper.myLooper(), mFeatureFlags, true, mSatelliteModemInterface);
processAllMessages();
mTestSatelliteModemStateCallback = new TestSatelliteModemStateCallback();
@@ -127,7 +133,7 @@
* state.
*/
TestSatelliteSessionController sessionController1 = new TestSatelliteSessionController(
- mContext, Looper.myLooper(), false, mSatelliteModemInterface);
+ mContext, Looper.myLooper(), mFeatureFlags, false, mSatelliteModemInterface);
assertNotNull(sessionController1);
processAllMessages();
assertEquals(STATE_UNAVAILABLE, sessionController1.getCurrentStateName());
@@ -136,7 +142,7 @@
* Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
*/
TestSatelliteSessionController sessionController2 = new TestSatelliteSessionController(
- mContext, Looper.myLooper(), true, mSatelliteModemInterface);
+ mContext, Looper.myLooper(), mFeatureFlags, true, mSatelliteModemInterface);
assertNotNull(sessionController2);
processAllMessages();
assertEquals(STATE_POWER_OFF, sessionController2.getCurrentStateName());
@@ -149,7 +155,7 @@
* state.
*/
TestSatelliteSessionController sessionController = new TestSatelliteSessionController(
- mContext, Looper.myLooper(), false, mSatelliteModemInterface);
+ mContext, Looper.myLooper(), mFeatureFlags, false, mSatelliteModemInterface);
assertNotNull(sessionController);
processAllMessages();
assertEquals(STATE_UNAVAILABLE, sessionController.getCurrentStateName());
@@ -171,9 +177,7 @@
assertNotNull(mTestSatelliteSessionController);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
- // Power on the modem.
- mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
- processAllMessages();
+ powerOnSatelliteModem();
// SatelliteSessionController should move to IDLE state after the modem is powered on.
assertSuccessfulModemStateChangedCallback(
@@ -191,9 +195,7 @@
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
- // Power on the modem.
- mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
- processAllMessages();
+ powerOnSatelliteModem();
// SatelliteSessionController should move to IDLE state after radio is turned on.
assertSuccessfulModemStateChangedCallback(
@@ -414,9 +416,7 @@
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
setupDatagramTransferringState(false);
- // Power on the modem.
- mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
- processAllMessages();
+ powerOnSatelliteModem();
// SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
// is powered on.
@@ -448,9 +448,7 @@
SatelliteManager.SATELLITE_MODEM_STATE_OFF);
clearInvocations(mMockDatagramController);
- // Power on the modem.
- mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
- processAllMessages();
+ powerOnSatelliteModem();
// SatelliteSessionController should move to NOT_CONNECTED state after radio is turned on.
assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
@@ -679,9 +677,7 @@
SatelliteManager.SATELLITE_MODEM_STATE_OFF);
clearInvocations(mMockDatagramController);
- // Power on the modem.
- mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
- processAllMessages();
+ powerOnSatelliteModem();
// SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
// is powered on.
@@ -736,9 +732,7 @@
mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
- // Power on the modem.
- mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
- processAllMessages();
+ powerOnSatelliteModem();
// SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
// is powered on.
@@ -764,9 +758,7 @@
mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
- // Power on the modem.
- mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
- processAllMessages();
+ powerOnSatelliteModem();
// SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
// is powered on.
@@ -804,6 +796,194 @@
assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Power off the modem.
+ mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
+ processAllMessages();
+
+ // SatelliteSessionController should move to POWER_OFF
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ moveSatelliteToEnablingState();
+
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ processAllMessages();
+
+ // The modem state changed events should be deferred
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(
+ STATE_ENABLING_SATELLITE, mTestSatelliteSessionController.getCurrentStateName());
+ assertTrue(mTestSatelliteSessionController.isEventDeferred(
+ 4 /* EVENT_SATELLITE_MODEM_STATE_CHANGED */));
+
+ // Modem is powered on
+ mTestSatelliteModemStateCallback.clearModemStates();
+ mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
+ processAllMessages();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on. Then, it should move to CONNECTED and then back to NOT_CONNECTED state
+ // because of the above deferred events.
+ assertEquals(3, mTestSatelliteModemStateCallback.getNumberOfModemStates());
+ assertEquals(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED,
+ mTestSatelliteModemStateCallback.getModemState(0));
+ assertEquals(SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED,
+ mTestSatelliteModemStateCallback.getModemState(1));
+ assertEquals(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED,
+ mTestSatelliteModemStateCallback.getModemState(2));
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Power off the modem.
+ mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
+ processAllMessages();
+
+ // SatelliteSessionController should move to POWER_OFF
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ moveSatelliteToEnablingState();
+
+ mTestSatelliteModemStateCallback.clearSemaphorePermits();
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ processAllMessages();
+
+ // The modem state changed events should be deferred
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(
+ STATE_ENABLING_SATELLITE, mTestSatelliteSessionController.getCurrentStateName());
+ assertTrue(mTestSatelliteSessionController.isEventDeferred(
+ 4 /* EVENT_SATELLITE_MODEM_STATE_CHANGED */));
+
+ // Modem got reset. The deferred messages should be removed.
+ mTestSatelliteModemStateCallback.clearSemaphorePermits();
+ mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
+ processAllMessages();
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isEventDeferred(
+ 4 /* EVENT_SATELLITE_MODEM_STATE_CHANGED */));
+
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(1, mTestSatelliteModemStateCallback.getNumberOfModemStates());
+ assertEquals(SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED,
+ mTestSatelliteModemStateCallback.getModemState(0));
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ }
+
+ @Test
+ public void testEnablingSatellite() {
+ /*
+ * Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ */
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Power off satellite
+ mTestSatelliteSessionController.onSatelliteEnablementStarted(false);
+ processAllMessages();
+
+ // Satellite should stay at POWER_OFF state
+ assertModemStateChangedCallbackNotCalled(mTestSatelliteModemStateCallback);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ moveSatelliteToEnablingState();
+
+ // Satellite enablement has failed
+ mTestSatelliteSessionController.onSatelliteEnablementFailed();
+ processAllMessages();
+
+ // Satellite should move back to POWER_OFF state
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ moveSatelliteToEnablingState();
+
+ // Modem reset
+ mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
+ processAllMessages();
+
+ // Satellite should move back to POWER_OFF state
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ powerOnSatelliteModem();
+ }
+
+ @Test
+ public void testDisablingSatellite() {
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ // IDLE -> DISABLING
+ moveToIdleState();
+ moveSatelliteToDisablingState();
+
+ // DISABLING -> POWER_OFF
+ moveToPowerOffState();
+
+ // TRANSFERRING -> DISABLING
+ moveToIdleState();
+ moveIdleToTransferringState();
+ moveSatelliteToDisablingState();
+
+ // DISABLING -> POWER_OFF
+ moveToPowerOffState();
+
+ // LISTENING -> DISABLING
+ moveToIdleState();
+ moveIdleToTransferringState();
+ moveTransferringToListeningState();
+ moveSatelliteToDisablingState();
+
+ // DISABLING -> POWER_OFF
+ moveToPowerOffState();
+ }
+
+ @Test
+ public void testDisablingSatelliteForNblot() {
+ when(mMockSatelliteController.isSatelliteAttachRequired()).thenReturn(true);
+
+ // Since satellite is supported, SatelliteSessionController should move to POWER_OFF state.
+ assertNotNull(mTestSatelliteSessionController);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ setupDatagramTransferringState(false);
+
+ // NOT_CONNECTED -> DISABLING
+ moveToNotConnectedState();
+ moveSatelliteToDisablingState();
+
+ // DISABLING -> POWER_OFF
+ moveToPowerOffState();
+
+ // CONNECTED -> DISABLING
+ moveToNotConnectedState();
+ moveNotConnectedToConnectedState();
+ moveSatelliteToDisablingState();
+
+ // DISABLING -> POWER_OFF
+ moveToPowerOffState();
}
private void setupDatagramTransferringState(boolean isTransferring) {
@@ -811,6 +991,127 @@
when(mMockDatagramController.isPollingInIdleState()).thenReturn(isTransferring);
}
+ private void powerOnSatelliteModem() {
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Power on the modem.
+ mTestSatelliteSessionController.onSatelliteEnablementStarted(true);
+ processAllMessages();
+
+ // SatelliteSessionController should move to ENABLING state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE);
+ assertEquals(
+ STATE_ENABLING_SATELLITE, mTestSatelliteSessionController.getCurrentStateName());
+
+ // Satellite is powered on
+ mTestSatelliteModemStateCallback.clearModemStates();
+ mTestSatelliteSessionController.onSatelliteEnabledStateChanged(true);
+ processAllMessages();
+ }
+
+ private void moveSatelliteToEnablingState() {
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ mTestSatelliteModemStateCallback.clearModemStates();
+
+ // Power on the modem.
+ mTestSatelliteSessionController.onSatelliteEnablementStarted(true);
+ processAllMessages();
+
+ // SatelliteSessionController should move to ENABLING state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_ENABLING_SATELLITE);
+ assertEquals(
+ STATE_ENABLING_SATELLITE, mTestSatelliteSessionController.getCurrentStateName());
+ mTestSatelliteModemStateCallback.clearModemStates();
+ }
+
+ private void moveToPowerOffState() {
+ mTestSatelliteSessionController.onSatelliteEnabledStateChanged(false);
+ processAllMessages();
+
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_OFF);
+ assertEquals(STATE_POWER_OFF, mTestSatelliteSessionController.getCurrentStateName());
+ }
+
+ private void moveToIdleState() {
+ powerOnSatelliteModem();
+
+ // SatelliteSessionController should move to IDLE state after the modem is powered on.
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_IDLE);
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
+ }
+
+ private void moveIdleToTransferringState() {
+ assertEquals(STATE_IDLE, mTestSatelliteSessionController.getCurrentStateName());
+ // Start sending datagrams
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING, SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ processAllMessages();
+
+ // SatelliteSessionController should move to TRANSFERRING state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING);
+ assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
+ assertTrue(mTestSatelliteSessionController.isSendingTriggeredDuringTransferringState());
+ }
+
+ private void moveTransferringToListeningState() {
+ assertEquals(STATE_TRANSFERRING, mTestSatelliteSessionController.getCurrentStateName());
+ // Sending datagrams is successful and done.
+ mTestSatelliteSessionController.onDatagramTransferStateChanged(
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE);
+ processAllMessages();
+
+ // SatelliteSessionController should move to LISTENING state.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_LISTENING);
+ assertEquals(STATE_LISTENING, mTestSatelliteSessionController.getCurrentStateName());
+ }
+
+ private void moveToNotConnectedState() {
+ powerOnSatelliteModem();
+ // SatelliteSessionController should move to NOT_CONNECTED state after the satellite modem
+ // is powered on.
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ assertEquals(STATE_NOT_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ assertFalse(mTestSatelliteSessionController.isNbIotInactivityTimerStarted());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_NOT_CONNECTED);
+ clearInvocations(mMockDatagramController);
+ }
+
+ private void moveNotConnectedToConnectedState() {
+ // Satellite modem is connected to a satellite network.
+ mTestSatelliteSessionController.onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ processAllMessages();
+
+ // SatelliteSessionController should move to CONNECTED state
+ assertSuccessfulModemStateChangedCallback(
+ mTestSatelliteModemStateCallback, SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ assertEquals(STATE_CONNECTED, mTestSatelliteSessionController.getCurrentStateName());
+ verify(mMockDatagramController).onSatelliteModemStateChanged(
+ SatelliteManager.SATELLITE_MODEM_STATE_CONNECTED);
+ clearInvocations(mMockDatagramController);
+ }
+
+ private void moveSatelliteToDisablingState() {
+ mTestSatelliteSessionController.onSatelliteEnablementStarted(false);
+ processAllMessages();
+
+ // SatelliteSessionController should move to DISABLING state
+ assertSuccessfulModemStateChangedCallback(mTestSatelliteModemStateCallback,
+ SatelliteManager.SATELLITE_MODEM_STATE_DISABLING_SATELLITE);
+ assertEquals(
+ STATE_DISABLING_SATELLITE, mTestSatelliteSessionController.getCurrentStateName());
+ }
+
private static class TestSatelliteModemInterface extends SatelliteModemInterface {
private final AtomicInteger mListeningEnabledCount = new AtomicInteger(0);
private final AtomicInteger mListeningDisabledCount = new AtomicInteger(0);
@@ -818,8 +1119,9 @@
private int mErrorCode = SatelliteManager.SATELLITE_RESULT_SUCCESS;
TestSatelliteModemInterface(@NonNull Context context,
- SatelliteController satelliteController, @NonNull Looper looper) {
- super(context, satelliteController, looper);
+ SatelliteController satelliteController, @NonNull Looper looper,
+ @NonNull FeatureFlags featureFlags) {
+ super(context, satelliteController, looper, featureFlags);
mExponentialBackoff.stop();
}
@@ -862,9 +1164,10 @@
}
private static class TestSatelliteSessionController extends SatelliteSessionController {
- TestSatelliteSessionController(Context context, Looper looper, boolean isSatelliteSupported,
+ TestSatelliteSessionController(Context context, Looper looper, FeatureFlags featureFlags,
+ boolean isSatelliteSupported,
SatelliteModemInterface satelliteModemInterface) {
- super(context, looper, isSatelliteSupported, satelliteModemInterface);
+ super(context, looper, featureFlags, isSatelliteSupported, satelliteModemInterface);
}
String getCurrentStateName() {
@@ -878,17 +1181,26 @@
boolean isNbIotInactivityTimerStarted() {
return hasMessages(EVENT_NB_IOT_INACTIVITY_TIMER_TIMED_OUT);
}
+
+ boolean isEventDeferred(int event) {
+ return hasDeferredMessages(event);
+ }
}
private static class TestSatelliteModemStateCallback extends ISatelliteModemStateCallback.Stub {
private final AtomicInteger mModemState = new AtomicInteger(
SatelliteManager.SATELLITE_MODEM_STATE_OFF);
private final Semaphore mSemaphore = new Semaphore(0);
+ private final Object mLock = new Object();
+ private final List<Integer> mModemStates = new ArrayList<>();
@Override
public void onSatelliteModemStateChanged(int state) {
logd("onSatelliteModemStateChanged: state=" + state);
mModemState.set(state);
+ synchronized (mLock) {
+ mModemStates.add(state);
+ }
try {
mSemaphore.release();
} catch (Exception ex) {
@@ -912,6 +1224,28 @@
public int getModemState() {
return mModemState.get();
}
+
+ public int getModemState(int index) {
+ synchronized (mLock) {
+ return mModemStates.get(index);
+ }
+ }
+
+ public void clearModemStates() {
+ synchronized (mLock) {
+ mModemStates.clear();
+ }
+ }
+
+ public int getNumberOfModemStates() {
+ synchronized (mLock) {
+ return mModemStates.size();
+ }
+ }
+
+ public void clearSemaphorePermits() {
+ mSemaphore.drainPermits();
+ }
}
private static void assertSuccessfulModemStateChangedCallback(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/security/CellularNetworkSecuritySafetySourceTest.java b/tests/telephonytests/src/com/android/internal/telephony/security/CellularNetworkSecuritySafetySourceTest.java
index 76118c4..e409b8d 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/security/CellularNetworkSecuritySafetySourceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/security/CellularNetworkSecuritySafetySourceTest.java
@@ -36,6 +36,7 @@
import android.content.Context;
import android.content.Intent;
import android.safetycenter.SafetySourceData;
+import android.safetycenter.SafetySourceIssue;
import android.util.Singleton;
import com.android.internal.R;
@@ -50,6 +51,7 @@
import org.mockito.ArgumentCaptor;
import java.time.Instant;
+import java.util.List;
public final class CellularNetworkSecuritySafetySourceTest extends TelephonyTest {
@@ -76,13 +78,19 @@
mContextFixture.putResource(R.string.scCellularNetworkSecurityTitle, "fake");
mContextFixture.putResource(R.string.scCellularNetworkSecuritySummary, "fake");
- mContextFixture.putResource(R.string.scNullCipherIssueNonEncryptedTitle, "fake %1$s");
- mContextFixture.putResource(R.string.scNullCipherIssueNonEncryptedSummary, "fake");
+ mContextFixture.putResource(R.string.scCellularNetworkSecurityLearnMore,
+ "https://support.google.com/android?p=cellular_security");
+ mContextFixture.putResource(R.string.scNullCipherIssueNonEncryptedTitle, "fake");
+ mContextFixture.putResource(R.string.scNullCipherIssueNonEncryptedSummary, "fake %1$s");
+ mContextFixture.putResource(R.string.scNullCipherIssueNonEncryptedSummaryNotification,
+ "fake %1$s");
mContextFixture.putResource(R.string.scNullCipherIssueEncryptedTitle, "fake %1$s");
- mContextFixture.putResource(R.string.scNullCipherIssueEncryptedSummary, "fake");
+ mContextFixture.putResource(R.string.scNullCipherIssueEncryptedSummary, "fake %1$s");
mContextFixture.putResource(R.string.scIdentifierDisclosureIssueTitle, "fake");
+ mContextFixture.putResource(R.string.scIdentifierDisclosureIssueSummaryNotification,
+ "fake %1$s %2$s");
mContextFixture.putResource(
- R.string.scIdentifierDisclosureIssueSummary, "fake %1$d %2$tr %3$tr %4$s");
+ R.string.scIdentifierDisclosureIssueSummary, "fake %1$s %2$s");
mContextFixture.putResource(R.string.scNullCipherIssueActionSettings, "fake");
mContextFixture.putResource(R.string.scNullCipherIssueActionLearnMore, "fake");
@@ -172,6 +180,26 @@
}
@Test
+ public void clearNullCipherState() {
+ ArgumentCaptor<SafetySourceData> data = ArgumentCaptor.forClass(SafetySourceData.class);
+
+ mSafetySource.setNullCipherIssueEnabled(mContext, true);
+ mSafetySource.setNullCipherState(mContext, 0, NULL_CIPHER_STATE_NOTIFY_ENCRYPTED);
+ mSafetySource.clearNullCipherState(mContext, 0);
+
+ // Once for enable, once for encrypted state, and once for clearing state
+ verify(mSafetyCenterManagerWrapper, times(3)).setSafetySourceData(data.capture());
+
+ // initial check that our encrypted state update created an issue
+ assertThat(data.getAllValues().get(1).getStatus()).isNotNull();
+ assertThat(data.getAllValues().get(1).getIssues()).hasSize(1);
+
+ // assert that our last call to clear state results in no issues sent to SC
+ assertThat(data.getAllValues().get(2).getStatus()).isNotNull();
+ assertThat(data.getAllValues().get(2).getIssues()).isEmpty();
+ }
+
+ @Test
public void disableIdentifierDisclosueIssue_nullData() {
// We must first enable before disabling, since a standalone call to disable may result in
// a no-op when the default for a new notifier is to be disabled.
@@ -245,4 +273,24 @@
assertThat(data.getAllValues().get(3).getStatus()).isNotNull();
assertThat(data.getAllValues().get(3).getIssues()).hasSize(2);
}
+
+ @Test
+ public void learnMoreLinkEmpty_learnMoreIsHidden() {
+ mContextFixture.putResource(R.string.scCellularNetworkSecurityLearnMore, "");
+
+ ArgumentCaptor<SafetySourceData> data = ArgumentCaptor.forClass(SafetySourceData.class);
+
+ mSafetySource.setNullCipherIssueEnabled(mContext, true);
+ mSafetySource.setNullCipherState(mContext, 0, NULL_CIPHER_STATE_NOTIFY_NON_ENCRYPTED);
+ mSafetySource.setIdentifierDisclosureIssueEnabled(mContext, true);
+ mSafetySource.setIdentifierDisclosure(mContext, 0, 12, Instant.now(), Instant.now());
+
+ verify(mSafetyCenterManagerWrapper, times(4)).setSafetySourceData(data.capture());
+ List<SafetySourceIssue.Action> actions = data.getAllValues().get(
+ 3).getIssues().getFirst().getActions();
+
+ // we only see the action that takes you to the settings page
+ assertThat(actions).hasSize(1);
+ assertThat(actions.getFirst().getId()).isEqualTo("cellular_security_settings");
+ }
}
\ No newline at end of file
diff --git a/tests/telephonytests/src/com/android/internal/telephony/security/NullCipherNotifierTest.java b/tests/telephonytests/src/com/android/internal/telephony/security/NullCipherNotifierTest.java
index 0bb7b76..6a4d2fb 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/security/NullCipherNotifierTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/security/NullCipherNotifierTest.java
@@ -45,6 +45,7 @@
public class NullCipherNotifierTest {
private static final int SUB_ID = 3425;
+ private static final int PHONE_ID = 999;
private static final List<Integer> NON_TRANSPORT_LAYER_EVENTS =
List.of(SecurityAlgorithmUpdate.CONNECTION_EVENT_VOLTE_SIP,
SecurityAlgorithmUpdate.CONNECTION_EVENT_VOLTE_SIP_SOS,
@@ -149,9 +150,11 @@
@Test
public void onSecurityAlgorithmUpdate_enabled_unprotectedEmergency_noSafetySourceUpdate() {
NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.enable(mContext);
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
SecurityAlgorithmUpdate.CONNECTION_EVENT_AS_SIGNALLING_5G,
@@ -163,6 +166,24 @@
}
@Test
+ public void onSecurityAlgorithmUpdate_disabled_noSafetySourceUpdate() {
+ NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.disable(mContext);
+
+ notifier.onSecurityAlgorithmUpdate(
+ mContext,
+ PHONE_ID,
+ SUB_ID,
+ new SecurityAlgorithmUpdate(
+ SecurityAlgorithmUpdate.CONNECTION_EVENT_AS_SIGNALLING_5G,
+ SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2,
+ SecurityAlgorithmUpdate.SECURITY_ALGORITHM_HMAC_SHA1_96,
+ /* isUnprotectedEmergency= */ false));
+
+ verify(mSafetySource, never()).setNullCipherState(any(), anyInt(), anyInt());
+ }
+
+ @Test
public void onSecurityAlgorithmUpdate_enabled_nonTransportLayerEvent_noSafetySourceUpdate() {
NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
@@ -170,6 +191,7 @@
clearInvocations(mSafetySource);
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -185,12 +207,14 @@
@Test
public void onUpdate_enabled_transportLayerEvent_encryptionNullCipher_notifyNonEncrypted() {
NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.enable(mContext);
for (int connectionEvent : TRANSPORT_LAYER_EVENTS) {
for (int encryptionAlgorithm : NULL_CIPHERS) {
clearInvocations(mSafetySource);
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -214,12 +238,14 @@
@Test
public void onUpdate_enabled_transportLayerEvent_integrityNullCipher_notifyNonEncrypted() {
NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.enable(mContext);
for (int connectionEvent : TRANSPORT_LAYER_EVENTS) {
for (int integrityAlgorithm : NULL_CIPHERS) {
clearInvocations(mSafetySource);
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -243,12 +269,14 @@
@Test
public void onUpdate_enabled_transportLayerEvent_encryptionNonNullCipher_encrypted() {
NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.enable(mContext);
for (int connectionEvent : TRANSPORT_LAYER_EVENTS) {
for (int encryptionAlgorithm : NON_NULL_CIPHERS) {
clearInvocations(mSafetySource);
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -272,12 +300,14 @@
@Test
public void onUpdate_enabled_transportLayerEvent_integrityNonNullCipher_encrypted() {
NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.enable(mContext);
for (int connectionEvent : TRANSPORT_LAYER_EVENTS) {
for (int integrityAlgorithm : NON_NULL_CIPHERS) {
clearInvocations(mSafetySource);
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -301,11 +331,13 @@
@Test
public void onUpdate_enabled_transportLayerEvent_encryptionNonNullCipher_notifyEncrypted() {
NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.enable(mContext);
for (int connectionEvent : TRANSPORT_LAYER_EVENTS) {
for (int encryptionAlgorithm : NON_NULL_CIPHERS) {
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -316,6 +348,7 @@
clearInvocations(mSafetySource);
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -345,6 +378,7 @@
for (int integrityAlgorithm : NON_NULL_CIPHERS) {
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -355,6 +389,7 @@
clearInvocations(mSafetySource);
notifier.onSecurityAlgorithmUpdate(
mContext,
+ PHONE_ID,
SUB_ID,
new SecurityAlgorithmUpdate(
connectionEvent,
@@ -374,4 +409,88 @@
}
}
}
+
+ @Test
+ public void onSecurityAlgorithmUpdate_updateSubscriptionId_clearsOldId() {
+ NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.enable(mContext);
+
+ int connectionEvent = SecurityAlgorithmUpdate.CONNECTION_EVENT_AS_SIGNALLING_5G;
+ int encryptionAlgorithm = SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2;
+ int subId2 = 1337;
+
+ notifier.onSecurityAlgorithmUpdate(
+ mContext,
+ PHONE_ID,
+ SUB_ID,
+ getWellEncryptedUpdate());
+
+ notifier.setSubscriptionMapping(mContext, PHONE_ID, subId2);
+
+ verify(
+ mSafetySource,
+ times(1).description(
+ "Connection event: " + connectionEvent
+ + " Encryption algorithm: " + encryptionAlgorithm))
+ .setNullCipherState(
+ eq(mContext),
+ eq(SUB_ID),
+ eq(NULL_CIPHER_STATE_ENCRYPTED));
+
+ verify(mSafetySource, times(1)).clearNullCipherState(eq(mContext), eq(SUB_ID));
+ }
+
+ @Test
+ public void onSecurityAlgorithmUpdate_newSubIdOnAlgoUpdate_clearsOldId() {
+ NullCipherNotifier notifier = new NullCipherNotifier(mExecutor, mSafetySource);
+ notifier.enable(mContext);
+
+ int connectionEvent = SecurityAlgorithmUpdate.CONNECTION_EVENT_AS_SIGNALLING_5G;
+ int encryptionAlgorithm = SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2;
+ int subId2 = 1337;
+
+ notifier.onSecurityAlgorithmUpdate(
+ mContext,
+ PHONE_ID,
+ SUB_ID,
+ getWellEncryptedUpdate());
+
+ notifier.onSecurityAlgorithmUpdate(
+ mContext,
+ PHONE_ID,
+ subId2,
+ getWellEncryptedUpdate());
+
+ verify(
+ mSafetySource,
+ times(1).description(
+ "SubId: " + SUB_ID + "Connection event: " + connectionEvent
+ + " Encryption algorithm: " + encryptionAlgorithm))
+ .setNullCipherState(
+ eq(mContext),
+ eq(SUB_ID),
+ eq(NULL_CIPHER_STATE_ENCRYPTED));
+
+ // The update with subId2 should clear subId1 data since they have the same phone id
+ verify(mSafetySource, times(1)).clearNullCipherState(eq(mContext), eq(SUB_ID));
+
+ verify(
+ mSafetySource,
+ times(1).description(
+ "SubId: " + SUB_ID + "Connection event: " + connectionEvent
+ + " Encryption algorithm: " + encryptionAlgorithm))
+ .setNullCipherState(
+ eq(mContext),
+ eq(subId2),
+ eq(NULL_CIPHER_STATE_ENCRYPTED));
+
+ }
+
+ private SecurityAlgorithmUpdate getWellEncryptedUpdate() {
+ return new SecurityAlgorithmUpdate(
+ SecurityAlgorithmUpdate.CONNECTION_EVENT_AS_SIGNALLING_5G,
+ SecurityAlgorithmUpdate.SECURITY_ALGORITHM_EEA2,
+ SecurityAlgorithmUpdate.SECURITY_ALGORITHM_HMAC_SHA1_96,
+ /* isUnprotectedEmergency= */ false);
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
index 7339e42..62b9def 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionDatabaseManagerTest.java
@@ -76,8 +76,8 @@
static final String FAKE_DEFAULT_CARD_NAME = "CARD %d";
static final String FAKE_ICCID1 = "123456";
static final String FAKE_ICCID2 = "456789";
- static final String FAKE_PHONE_NUMBER1 = "6502530000";
- static final String FAKE_PHONE_NUMBER2 = "4089961010";
+ static final String FAKE_PHONE_NUMBER1 = "9995551234";
+ static final String FAKE_PHONE_NUMBER2 = "9998887777";
static final String FAKE_CARRIER_NAME1 = "A-Mobile";
static final String FAKE_CARRIER_NAME2 = "B-Mobile";
static final int FAKE_COLOR1 = 1;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
index 6e2c5bf..de43b85 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionInfoInternalTest.java
@@ -341,4 +341,69 @@
assertThat(subInfoNull.getCountryIso()).isEqualTo("");
assertThat(subInfoNull.getGroupOwner()).isEqualTo("");
}
+
+ @Test
+ public void testIsVisible() {
+ // Regular profile
+ SubscriptionInfoInternal regularSub =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setOnlyNonTerrestrialNetwork(0)
+ .setOpportunistic(0)
+ .setGroupUuid(SubscriptionDatabaseManagerTest.FAKE_UUID1)
+ .build();
+ assertThat(regularSub.isVisible()).isTrue();
+
+ // Provisioning profile
+ SubscriptionInfoInternal provSub =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_PROVISIONING)
+ .setOnlyNonTerrestrialNetwork(0)
+ .setOpportunistic(0)
+ .build();
+ assertThat(provSub.isVisible()).isFalse();
+
+ // NTN profile
+ SubscriptionInfoInternal ntnSub =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setOnlyNonTerrestrialNetwork(1)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setOpportunistic(0)
+ .build();
+ assertThat(ntnSub.isVisible()).isFalse();
+
+ // Opportunistic profile without group UUID
+ SubscriptionInfoInternal opportunisticSub =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setOnlyNonTerrestrialNetwork(0)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setOpportunistic(1)
+ .build();
+ assertThat(opportunisticSub.isVisible()).isTrue();
+
+ // Opportunistic profile with group UUID
+ SubscriptionInfoInternal opportunisticSubUuid =
+ new SubscriptionInfoInternal.Builder()
+ .setId(2)
+ .setIccId(SubscriptionDatabaseManagerTest.FAKE_ICCID1)
+ .setSimSlotIndex(0)
+ .setOnlyNonTerrestrialNetwork(0)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setOpportunistic(1)
+ .setGroupUuid(SubscriptionDatabaseManagerTest.FAKE_UUID1)
+ .build();
+ assertThat(opportunisticSubUuid.isVisible()).isFalse();
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index cc20dfd..eb06ff1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -43,13 +43,17 @@
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_PHONE_NUMBER2;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG1;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_RCS_CONFIG2;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_ENTITLEMENT_PLMNS1;
+import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SATELLITE_IS_NTN_DISABLED;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO1;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_SUBSCRIPTION_INFO2;
import static com.android.internal.telephony.subscription.SubscriptionDatabaseManagerTest.FAKE_UUID1;
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -131,11 +135,13 @@
import java.io.StringWriter;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
+import java.util.stream.Collectors;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -238,7 +244,6 @@
doReturn(false).when(mFlags).enforceTelephonyFeatureMappingForPublicApis();
doReturn(true).when(mPackageManager).hasSystemFeature(
eq(PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION));
-
logd("SubscriptionManagerServiceTest -Setup!");
}
@@ -421,21 +426,35 @@
@Test
public void testSetAdminOwned() {
mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
- mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1,
- 0, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
+ mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1, 0,
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
processAllMessages();
String groupOwner = "test";
mSubscriptionManagerServiceUT.setGroupOwner(1, groupOwner);
- SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
- .getSubscriptionInfoInternal(1);
+ SubscriptionInfoInternal subInfo =
+ mSubscriptionManagerServiceUT.getSubscriptionInfoInternal(1);
assertThat(subInfo).isNotNull();
assertThat(subInfo.getGroupOwner()).isEqualTo(groupOwner);
verify(mMockedSubscriptionManagerServiceCallback).onSubscriptionChanged(eq(1));
}
@Test
+ public void testSetGroupOwner_callerMissingpPermission_throws() {
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+ mSubscriptionManagerServiceUT.addSubInfo(FAKE_ICCID1, FAKE_CARRIER_NAME1, 0,
+ SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
+ processAllMessages();
+ String groupOwner = "test";
+ // Remove MODIFY_PHONE_STATE
+ mContextFixture.removeCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+
+ assertThrows(SecurityException.class,
+ () -> mSubscriptionManagerServiceUT.setGroupOwner(1, groupOwner));
+ }
+
+ @Test
@DisableCompatChanges({TelephonyManager.ENABLE_FEATURE_MAPPING})
public void testSetPhoneNumber() {
doReturn(false).when(mFlags).enforceTelephonyFeatureMapping();
@@ -1789,6 +1808,45 @@
}
@Test
+ public void testGetPhoneNumberSourcePriority() throws Exception {
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PHONE_NUMBERS);
+
+ String phoneNumberFromCarrier = "8675309";
+ String phoneNumberFromUicc = "1112223333";
+ String phoneNumberFromIms = "5553466";
+ String phoneNumberFromPhoneObject = "8001234567";
+
+ doReturn(phoneNumberFromPhoneObject).when(mPhone).getLine1Number();
+
+ SubscriptionInfoInternal multiNumberSubInfo =
+ new SubscriptionInfoInternal.Builder(FAKE_SUBSCRIPTION_INFO1)
+ .setNumberFromCarrier(phoneNumberFromCarrier)
+ .setNumber(phoneNumberFromUicc)
+ .setNumberFromIms(phoneNumberFromIms)
+ .build();
+ int subId = insertSubscription(multiNumberSubInfo);
+
+ assertThat(mSubscriptionManagerServiceUT.getPhoneNumberFromFirstAvailableSource(
+ subId, CALLING_PACKAGE, CALLING_FEATURE)).isEqualTo(phoneNumberFromCarrier);
+
+ multiNumberSubInfo =
+ new SubscriptionInfoInternal.Builder(multiNumberSubInfo)
+ .setNumberFromCarrier("")
+ .setNumber(phoneNumberFromUicc)
+ .setNumberFromIms(phoneNumberFromIms)
+ .build();
+ subId = insertSubscription(multiNumberSubInfo);
+
+ assertThat(mSubscriptionManagerServiceUT.getPhoneNumberFromFirstAvailableSource(
+ subId, CALLING_PACKAGE, CALLING_FEATURE)).isEqualTo(phoneNumberFromPhoneObject);
+
+ doReturn("").when(mPhone).getLine1Number();
+
+ assertThat(mSubscriptionManagerServiceUT.getPhoneNumberFromFirstAvailableSource(
+ subId, CALLING_PACKAGE, CALLING_FEATURE)).isEqualTo(phoneNumberFromIms);
+ }
+
+ @Test
public void testSetUiccApplicationsEnabled() {
insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -2484,6 +2542,39 @@
}
@Test
+ public void testGetPhoneNumberFromDefaultSubscription() {
+ doReturn(true).when(mFlags).saferGetPhoneNumber();
+
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+ int subId = insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+
+ mSubscriptionManagerServiceUT.setDefaultVoiceSubId(subId);
+
+ assertThat(
+ mSubscriptionManagerServiceUT.getPhoneNumberFromFirstAvailableSource(
+ subId, CALLING_PACKAGE, CALLING_FEATURE)).isEqualTo(FAKE_PHONE_NUMBER1);
+ assertThat(
+ mSubscriptionManagerServiceUT.getPhoneNumber(
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_UICC,
+ CALLING_PACKAGE,
+ CALLING_FEATURE)).isEqualTo(FAKE_PHONE_NUMBER1);
+ assertThat(
+ mSubscriptionManagerServiceUT.getPhoneNumber(
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER,
+ CALLING_PACKAGE,
+ CALLING_FEATURE)).isEqualTo(FAKE_PHONE_NUMBER1);
+ assertThat(
+ mSubscriptionManagerServiceUT.getPhoneNumber(
+ SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+ SubscriptionManager.PHONE_NUMBER_SOURCE_IMS,
+ CALLING_PACKAGE,
+ CALLING_FEATURE)).isEqualTo(FAKE_PHONE_NUMBER1);
+ }
+
+ @Test
public void testEsimActivation() {
mContextFixture.addCallingOrSelfPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
@@ -3135,6 +3226,69 @@
}
@Test
+ public void testIsSatelliteSpnWithEmptySpn() {
+ mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier, ""); // Empty
+ System.setProperty("persist.radio.allow_mock_modem", "true");
+ doReturn(true).when(mFlags).oemEnabledSatelliteFlag();
+
+ EuiccProfileInfo profileInfo1 = new EuiccProfileInfo.Builder(FAKE_ICCID1)
+ .setIccid(FAKE_ICCID1)
+ .setNickname(FAKE_CARRIER_NAME1)
+ .setServiceProviderName(FAKE_CARRIER_NAME1)
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setCarrierIdentifier(new CarrierIdentifier(FAKE_MCC1, FAKE_MNC1,
+ FAKE_CARRIER_NAME1, null, null, null, FAKE_CARRIER_ID1, FAKE_CARRIER_ID1))
+ .setUiccAccessRule(Arrays.asList(UiccAccessRule.decodeRules(
+ FAKE_NATIVE_ACCESS_RULES1)))
+ .build();
+
+ GetEuiccProfileInfoListResult result = new GetEuiccProfileInfoListResult(
+ EuiccService.RESULT_OK, new EuiccProfileInfo[]{profileInfo1}, false);
+ doReturn(result).when(mEuiccController).blockingGetEuiccProfileInfoList(eq(1));
+ doReturn(TelephonyManager.INVALID_PORT_INDEX).when(mUiccSlot)
+ .getPortIndexFromIccId(anyString());
+ doReturn(FAKE_ICCID1).when(mUiccController).convertToCardString(eq(1));
+
+ mSubscriptionManagerServiceUT.updateEmbeddedSubscriptions(List.of(1), null);
+ processAllMessages();
+
+ SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
+ .getSubscriptionInfoInternal(1);
+ assertThat(subInfo.getOnlyNonTerrestrialNetwork())
+ .isEqualTo(FAKE_SATELLITE_IS_NTN_DISABLED);
+
+ mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
+ FAKE_CARRIER_NAME1);
+ EuiccProfileInfo profileInfo2 = new EuiccProfileInfo.Builder(FAKE_ICCID2)
+ .setIccid(FAKE_ICCID2)
+ .setNickname(FAKE_CARRIER_NAME2)
+ .setServiceProviderName("")
+ .setProfileClass(SubscriptionManager.PROFILE_CLASS_OPERATIONAL)
+ .setCarrierIdentifier(new CarrierIdentifier(FAKE_MCC2, FAKE_MNC2,
+ FAKE_CARRIER_NAME2, null, null, null, FAKE_CARRIER_ID2, FAKE_CARRIER_ID2))
+ .setUiccAccessRule(Arrays.asList(UiccAccessRule.decodeRules(
+ FAKE_NATIVE_ACCESS_RULES2)))
+ .build();
+ result = new GetEuiccProfileInfoListResult(
+ EuiccService.RESULT_OK, new EuiccProfileInfo[]{profileInfo2}, false);
+ doReturn(result).when(mEuiccController).blockingGetEuiccProfileInfoList(eq(2));
+ doReturn(TelephonyManager.INVALID_PORT_INDEX).when(mUiccSlot)
+ .getPortIndexFromIccId(anyString());
+ doReturn(FAKE_ICCID2).when(mUiccController).convertToCardString(eq(2));
+
+ mSubscriptionManagerServiceUT.updateEmbeddedSubscriptions(List.of(2), null);
+ processAllMessages();
+
+ subInfo = mSubscriptionManagerServiceUT
+ .getSubscriptionInfoInternal(2);
+ assertThat(subInfo.getOnlyNonTerrestrialNetwork())
+ .isEqualTo(FAKE_SATELLITE_IS_NTN_DISABLED);
+
+ System.setProperty("persist.radio.allow_mock_modem", "false");
+ doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
+ }
+
+ @Test
public void testIsSatelliteSpnWithNullCarrierIdentifier() {
mContextFixture.putResource(R.string.config_satellite_sim_spn_identifier,
FAKE_CARRIER_NAME1);
@@ -3208,4 +3362,60 @@
System.setProperty("persist.radio.allow_mock_modem", "false");
doReturn(false).when(mFlags).oemEnabledSatelliteFlag();
}
+
+ @Test
+ public void testGetSatelliteEntitlementPlmnList() throws Exception {
+ mContextFixture.addCallingOrSelfPermission(Manifest.permission.MODIFY_PHONE_STATE);
+
+ // When the empty list is stored, verify whether SubscriptionInfoInternal returns an
+ // empty string and SubscriptionManagerService returns an empty List.
+ insertSubscription(FAKE_SUBSCRIPTION_INFO1);
+ List<String> expectedPlmnList = new ArrayList<>();
+ int subId = 1;
+
+ SubscriptionInfoInternal subInfo = mSubscriptionManagerServiceUT
+ .getSubscriptionInfoInternal(subId);
+ assertTrue(subInfo.getSatelliteEntitlementPlmns().isEmpty());
+ assertEquals(expectedPlmnList,
+ mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+
+ // When the list is stored as [123123,12310], verify whether SubscriptionInfoInternal
+ // returns the string as "123123,12310" and SubscriptionManagerService returns the List as
+ // [123123,12310].
+ insertSubscription(FAKE_SUBSCRIPTION_INFO2);
+ String expectedPlmn = FAKE_SATELLITE_ENTITLEMENT_PLMNS1;
+ expectedPlmnList = Arrays.stream(expectedPlmn.split(",")).collect(Collectors.toList());
+ subId = 2;
+
+ subInfo = mSubscriptionManagerServiceUT.getSubscriptionInfoInternal(subId);
+ assertEquals(expectedPlmn, subInfo.getSatelliteEntitlementPlmns());
+ assertEquals(expectedPlmnList,
+ mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+
+ // When calling SubscriptionDatabaseManager#getSubscriptionInfoInternalreturns returns a
+ // null, then verify the SubscriptionManagerService returns an empty List.
+ SubscriptionDatabaseManager mockSubscriptionDatabaseManager = Mockito.mock(
+ SubscriptionDatabaseManager.class);
+ Field field = SubscriptionManagerService.class.getDeclaredField(
+ "mSubscriptionDatabaseManager");
+ field.setAccessible(true);
+ field.set(mSubscriptionManagerServiceUT, mockSubscriptionDatabaseManager);
+
+ doReturn(null).when(mockSubscriptionDatabaseManager).getSubscriptionInfoInternal(anyInt());
+ expectedPlmnList = new ArrayList<>();
+ assertEquals(expectedPlmnList,
+ mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+
+ // When calling SubscriptionDatabaseManager#getSubscriptionInfoInternalreturns returns a
+ // non null. And when calling SubscriptionInfoInternal#getSatelliteEntitlementPlmns
+ // returns a null, then verify the SubscriptionManagerService returns an empty List.
+ SubscriptionInfoInternal mockSubscriptionInfoInternal = Mockito.mock(
+ SubscriptionInfoInternal.class);
+ doReturn(mockSubscriptionInfoInternal).when(
+ mockSubscriptionDatabaseManager).getSubscriptionInfoInternal(anyInt());
+ doReturn(null).when(mockSubscriptionInfoInternal).getSatelliteEntitlementPlmns();
+
+ assertEquals(expectedPlmnList,
+ mSubscriptionManagerServiceUT.getSatelliteEntitlementPlmnList(subId));
+ }
}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
index 1a846c4..5c1993f 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccPortTest.java
@@ -20,11 +20,16 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.os.Binder;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -33,9 +38,11 @@
import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.Flags;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,9 +61,13 @@
private int mPhoneId = 0;
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Before
public void setUp() throws Exception {
super.setUp(getClass().getSimpleName());
+ mSetFlagsRule.enableFlags(Flags.FLAG_CLEANUP_OPEN_LOGICAL_CHANNEL_RECORD_ON_DISPOSE);
mUiccCard = mock(UiccCard.class);
mIccCardStatus = mock(IccCardStatus.class);
/* initially there are no application available */
@@ -144,6 +155,20 @@
verify(mUiccProfile).iccCloseLogicalChannel(eq(CHANNEL_ID), eq(false), eq(null));
}
+ @Test
+ @SmallTest
+ public void testOnOpenLogicalChannel_withPortDisposed_noRecordLeft() {
+ IccLogicalChannelRequest request = getIccLogicalChannelRequest();
+
+ mUiccPort.onLogicalChannelOpened(request);
+ mUiccPort.dispose();
+
+ UiccPort.OpenLogicalChannelRecord record = mUiccPort.getOpenLogicalChannelRecord(
+ CHANNEL_ID);
+ assertThat(record).isNull();
+ verify(mUiccProfile, never()).iccCloseLogicalChannel(anyInt(), anyBoolean(), any());
+ }
+
private IccLogicalChannelRequest getIccLogicalChannelRequest() {
IccLogicalChannelRequest request = new IccLogicalChannelRequest();
request.channel = CHANNEL_ID;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
index b073c6a..cf3f900 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/euicc/apdu/ApduSenderTest.java
@@ -37,6 +37,7 @@
import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.uicc.IccIoResult;
import com.android.internal.telephony.uicc.IccUtils;
+import androidx.test.InstrumentationRegistry;
import org.junit.After;
import org.junit.Before;
@@ -93,7 +94,8 @@
mResponseCaptor = new ResponseCaptor();
mSelectResponse = null;
- mSender = new ApduSender(mMockCi, AID, false /* supportExtendedApdu */);
+ mSender = new ApduSender(InstrumentationRegistry.getContext(), 0 /* phoneId= */,
+ mMockCi, AID, false /* supportExtendedApdu */);
mLooper = TestableLooper.get(this);
}