Merge "Pass emergency session information to modem" into 24D1-dev am: 388ab1fb8e
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/opt/telephony/+/26786723
Change-Id: I466f330370763e33f5d500224f7123007fe93715
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 8f363b6..4646649 100644
--- a/flags/Android.bp
+++ b/flags/Android.bp
@@ -21,6 +21,7 @@
aconfig_declarations {
name: "telephony_flags",
package: "com.android.internal.telephony.flags",
+ container: "system",
srcs: [
"calling.aconfig",
"data.aconfig",
diff --git a/flags/calling.aconfig b/flags/calling.aconfig
index e67ebc6..f121169 100644
--- a/flags/calling.aconfig
+++ b/flags/calling.aconfig
@@ -1,12 +1,17 @@
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"
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 6334803..fbe63e1 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -1,5 +1,7 @@
package: "com.android.internal.telephony.flags"
+container: "system"
+# OWNER=linggm TARGET=24Q3
flag {
name: "auto_data_switch_allow_roaming"
namespace: "telephony"
@@ -10,6 +12,7 @@
}
}
+# OWNER=linggm TARGET=24Q3
flag {
name: "auto_data_switch_rat_ss"
namespace: "telephony"
@@ -17,6 +20,7 @@
bug:"260928808"
}
+# OWNER=linggm TARGET=24Q2
flag {
name: "use_alarm_callback"
namespace: "telephony"
@@ -24,6 +28,7 @@
bug: "311476875"
}
+# OWNER=linggm TARGET=24Q2
flag {
name: "refine_preferred_data_profile_selection"
namespace: "telephony"
@@ -31,6 +36,7 @@
bug: "311476883"
}
+# OWNER=linggm TARGET=24Q2
flag {
name: "unthrottle_check_transport"
namespace: "telephony"
@@ -38,6 +44,7 @@
bug: "303922311"
}
+# OWNER=linggm TARGET=24Q1
flag {
name: "relax_ho_teardown"
namespace: "telephony"
@@ -45,6 +52,7 @@
bug: "270895912"
}
+# OWNER=linggm TARGET=24Q2
flag {
name: "allow_mmtel_in_non_vops"
namespace: "telephony"
@@ -52,6 +60,7 @@
bug: "241198464"
}
+# OWNER=jackyu TARGET=24Q2
flag {
name: "metered_embb_urlcc"
namespace: "telephony"
@@ -59,27 +68,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"
@@ -87,6 +103,7 @@
bug: "309896936"
}
+# OWNER=qingqi TARGET=24Q3
flag {
name: "vonr_enabled_metric"
namespace: "telephony"
@@ -94,6 +111,7 @@
bug:"288449751"
}
+# OWNER=willycwhu TARGET=24Q2
flag {
name: "ignore_existing_networks_for_internet_allowed_checking"
namespace: "telephony"
@@ -101,6 +119,7 @@
bug: "284420611"
}
+# OWNER=apsankar TARGET=24Q3
flag {
name: "data_call_session_stats_captures_cross_sim_calling"
namespace: "telephony"
@@ -108,6 +127,7 @@
bug: "313956117"
}
+# OWNER=jackyu TARGET=24Q2
flag {
name: "force_iwlan_mms"
namespace: "telephony"
@@ -115,6 +135,7 @@
bug: "316211526"
}
+# OWNER=sewook TARGET=24Q3
flag {
name: "reconnect_qualified_network"
namespace: "telephony"
@@ -122,9 +143,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 2e1dfc8..623c3b6 100644
--- a/flags/domainselection.aconfig
+++ b/flags/domainselection.aconfig
@@ -1,5 +1,7 @@
package: "com.android.internal.telephony.flags"
+container: "system"
+# OWNER=forestchoi TARGET=24Q3
flag {
name: "ap_domain_selection_enabled"
namespace: "telephony"
@@ -7,6 +9,7 @@
bug:"258112541"
}
+# OWNER=forestchoi TARGET=24Q3
flag {
name: "use_aosp_domain_selection_service"
namespace: "telephony"
@@ -14,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 d09259e..6e6bfe9 100644
--- a/flags/ims.aconfig
+++ b/flags/ims.aconfig
@@ -1,5 +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"
@@ -7,6 +9,7 @@
bug:"288002989"
}
+# OWNER=joonhunshin TARGET=24Q2
flag {
name: "ignore_already_terminated_incoming_call_before_registering_listener"
namespace: "telephony"
@@ -14,6 +17,7 @@
bug:"289461637"
}
+# OWNER=joonhunshin TARGET=24Q2
flag {
name: "clear_cached_ims_phone_number_when_device_lost_ims_registration"
namespace: "telephony"
@@ -21,6 +25,7 @@
bug:"288002989"
}
+# OWNER=sangyun TARGET=24Q2
flag {
name: "update_ims_service_by_gathering_provisioning_changes"
namespace: "telephony"
@@ -28,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"
@@ -42,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"
@@ -56,9 +67,40 @@
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
+ }
+}
diff --git a/flags/iwlan.aconfig b/flags/iwlan.aconfig
index 0dc9f8d..f16ee38 100644
--- a/flags/iwlan.aconfig
+++ b/flags/iwlan.aconfig
@@ -1,13 +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 1ba89ba..45df2d8 100644
--- a/flags/messaging.aconfig
+++ b/flags/messaging.aconfig
@@ -1,5 +1,7 @@
package: "com.android.internal.telephony.flags"
+container: "system"
+# OWNER=linggm TARGET=24Q1
flag {
name: "reject_bad_sub_id_interaction"
namespace: "telephony"
@@ -7,6 +9,7 @@
bug: "294125411"
}
+# OWNER=hwangoo TARGET=24Q2
flag {
name: "sms_domain_selection_enabled"
namespace: "telephony"
@@ -14,8 +17,10 @@
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"
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 1e714c5..a491665 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -1,5 +1,7 @@
package: "com.android.internal.telephony.flags"
+container: "system"
+# OWNER=tjstuart TARGET=24Q3
flag {
name: "do_not_override_precise_label"
namespace: "telephony"
@@ -8,6 +10,7 @@
is_fixed_read_only: true
}
+# OWNER=tnd TARGET=24Q1
flag {
name: "log_mms_sms_database_access_info"
namespace: "telephony"
@@ -15,6 +18,7 @@
bug: "275225402"
}
+# OWNER=tjstuart TARGET=24Q3
flag {
name: "stop_spamming_emergency_notification"
namespace: "telephony"
@@ -22,13 +26,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"
@@ -36,6 +43,7 @@
bug: "309655251"
}
+# OWNER=sangyun TARGET=24Q2
flag {
name: "reorganize_roaming_notification"
namespace: "telephony"
@@ -43,6 +51,7 @@
bug: "310594087"
}
+# OWNER=sangyun TARGET=24Q2
flag {
name: "dismiss_network_selection_notification_on_sim_disable"
namespace: "telephony"
@@ -50,6 +59,7 @@
bug: "310594186"
}
+# OWNER=nagendranb TARGET=24Q3
flag {
name: "enable_telephony_analytics"
namespace: "telephony"
@@ -57,20 +67,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"
@@ -81,6 +96,7 @@
}
}
+# OWNER=rambowang TARGET=24Q3
flag {
name: "add_anomaly_when_notify_config_changed_with_invalid_phone"
namespace: "telephony"
@@ -91,6 +107,7 @@
}
}
+# OWNER=rambowang TARGET=24Q3
flag {
name: "hide_preinstalled_carrier_app_at_most_once"
namespace: "telephony"
@@ -100,3 +117,14 @@
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
+ }
+}
\ No newline at end of file
diff --git a/flags/network.aconfig b/flags/network.aconfig
index ab917f0..eae58d0 100644
--- a/flags/network.aconfig
+++ b/flags/network.aconfig
@@ -1,5 +1,7 @@
package: "com.android.internal.telephony.flags"
+container: "system"
+# OWNER=nharold TARGET=24Q1
flag {
name: "enable_carrier_config_n1_control_attempt2"
namespace: "telephony"
@@ -11,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"
@@ -32,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"
@@ -46,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"
@@ -60,8 +73,10 @@
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"
diff --git a/flags/satellite.aconfig b/flags/satellite.aconfig
index 798ce40..27ab0b1 100644
--- a/flags/satellite.aconfig
+++ b/flags/satellite.aconfig
@@ -1,19 +1,25 @@
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"
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index cebedd5..60c0af1 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -1,26 +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"
@@ -28,15 +36,19 @@
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"
diff --git a/flags/telephony.aconfig b/flags/telephony.aconfig
index 9ef70b1..07f2f9e 100644
--- a/flags/telephony.aconfig
+++ b/flags/telephony.aconfig
@@ -1,5 +1,7 @@
package: "com.android.internal.telephony.flags"
+container: "system"
+# OWNER=joonhunshin TARGET=24Q3
flag {
name: "enforce_telephony_feature_mapping"
namespace: "telephony"
@@ -7,6 +9,7 @@
bug:"297989574"
}
+# OWNER=joonhunshin TARGET=24Q3
flag {
name: "enforce_telephony_feature_mapping_for_public_apis"
namespace: "telephony"
@@ -14,6 +17,7 @@
bug:"297989574"
}
+# OWNER=stevestatia TARGET=24Q3
flag {
name: "prevent_system_server_and_phone_deadlock"
namespace: "telephony"
@@ -21,6 +25,7 @@
bug: "315973270"
}
+# OWNER=joonhunshin TARGET=24Q3
flag {
name: "prevent_invocation_repeat_of_ril_call_when_device_does_not_support_voice"
namespace: "telephony"
@@ -28,6 +33,7 @@
bug: "290833783"
}
+# OWNER=jackyu TARGET=24Q3
flag {
name: "minimal_telephony_cdm_check"
namespace: "telephony"
@@ -35,9 +41,18 @@
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"
+}
diff --git a/flags/uicc.aconfig b/flags/uicc.aconfig
index c1b860f..8166853 100644
--- a/flags/uicc.aconfig
+++ b/flags/uicc.aconfig
@@ -1,31 +1,43 @@
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=24Q3
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"
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index e54c969..fb89155 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: 72
message PersistAtoms {
/* Aggregated RAT usage during the call. */
repeated VoiceCallRatUsage voice_call_rat_usage = 1;
@@ -231,6 +231,12 @@
/* 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;
}
// The canonical versions of the following enums live in:
@@ -694,3 +700,13 @@
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;
+}
diff --git a/proto/src/telephony.proto b/proto/src/telephony.proto
index b87728b..92f62cc 100644
--- a/proto/src/telephony.proto
+++ b/proto/src/telephony.proto
@@ -259,8 +259,8 @@
// Roaming type
enum RoamingType {
- // Unknown. The default value. Different from ROAMING_TYPE_UNKNOWN.
- UNKNOWN = -1;
+ // Undefined. The default value. Different from ROAMING_TYPE_UNKNOWN.
+ ROAMING_TYPE_UNDEFINED = -1;
// In home network
ROAMING_TYPE_NOT_ROAMING = 0;
@@ -346,10 +346,10 @@
optional TelephonyOperator data_operator = 2;
// Current voice network roaming type
- optional RoamingType voice_roaming_type = 3 [default = UNKNOWN];
+ optional RoamingType voice_roaming_type = 3 [default = ROAMING_TYPE_UNDEFINED];
// Current data network roaming type
- optional RoamingType data_roaming_type = 4 [default = UNKNOWN];
+ optional RoamingType data_roaming_type = 4 [default = ROAMING_TYPE_UNDEFINED];
// Current voice radio technology
optional RadioAccessTechnology voice_rat = 5 [default = UNKNOWN];
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/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index db0fb2d..eeba86b 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -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();
}
@@ -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;
@@ -5444,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/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index c088406..6858533 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -779,6 +779,7 @@
case EVENT_SET_NETWORK_MANUAL_COMPLETE:
case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
handleSetSelectNetwork((AsyncResult) msg.obj);
+ onSetNetworkSelectionModeCompleted();
return;
}
@@ -1536,6 +1537,12 @@
}
/**
+ * Called when setting network selection mode is complete.
+ */
+ protected void onSetNetworkSelectionModeCompleted() {
+ }
+
+ /**
* Query the radio for the current network selection mode.
*
* Return values:
@@ -4018,6 +4025,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;
}
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 8b3be1e..9e64f52 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -151,6 +151,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 */
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/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/data/AccessNetworksManager.java b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
index 3d3fbe9..e573db9 100644
--- a/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
+++ b/src/java/com/android/internal/telephony/data/AccessNetworksManager.java
@@ -346,9 +346,9 @@
}
@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)
+ "]");
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index bd98403..d130751 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;
@@ -552,6 +553,9 @@
/** Metrics of per data network connection. */
private final DataCallSessionStats mDataCallSessionStats;
+ /** Metrics of per data network validation. */
+ private final @NonNull 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
@@ -764,6 +768,12 @@
private @Nullable AccessNetworksManagerCallback mAccessNetworksManagerCallback;
/**
+ * PreciseDataConnectionState, the most recently notified. If it has never been notified, it is
+ * null.
+ */
+ private @Nullable PreciseDataConnectionState mPreciseDataConnectionState;
+
+ /**
* The network bandwidth.
*/
public static class NetworkBandwidth {
@@ -986,6 +996,7 @@
mDataNetworkControllerCallback);
mDataConfigManager = mDataNetworkController.getDataConfigManager();
mDataCallSessionStats = new DataCallSessionStats(mPhone);
+ mDataNetworkValidationStats = new DataNetworkValidationStats(mPhone);
mDataNetworkCallback = callback;
mDataProfile = dataProfile;
if (dataProfile.getTrafficDescriptor() != null) {
@@ -1919,6 +1930,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,
@@ -2443,8 +2457,8 @@
// 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);
}
@@ -2967,6 +2981,7 @@
mDataCallResponse = response;
if (response.getLinkStatus() != DataCallResponse.LINK_STATUS_INACTIVE) {
updateDataNetwork(response);
+ notifyPreciseDataConnectionState();
} else {
log("onDataStateChanged: PDN inactive reported by "
+ AccessNetworkConstants.transportTypeToString(mTransport)
@@ -3417,11 +3432,20 @@
/**
* Send the precise data connection state to the listener of
* {@link android.telephony.TelephonyCallback.PreciseDataConnectionStateListener}.
+ *
+ * Note that notify only when {@link DataState} or {@link
+ * PreciseDataConnectionState.NetworkValidationStatus} 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 = pdcs;
+ logv("notifyPreciseDataConnectionState=" + pdcs);
+ mPhone.notifyDataConnection(pdcs);
+ }
}
/**
@@ -3511,6 +3535,8 @@
DataService.REQUEST_REASON_HANDOVER, mLinkProperties, mPduSessionId,
mNetworkSliceInfo, mHandoverDataProfile.getTrafficDescriptor(), true,
obtainMessage(EVENT_HANDOVER_RESPONSE, retryEntry));
+
+ mDataNetworkValidationStats.onHandoverAttempted();
}
/**
@@ -3705,6 +3731,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");
}
@@ -3733,8 +3764,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}
*/
@@ -3751,8 +3781,10 @@
+ PreciseDataConnectionState.networkValidationStatusToString(
networkValidationStatus));
mNetworkValidationStatus = networkValidationStatus;
- notifyPreciseDataConnectionState();
}
+
+ mDataNetworkValidationStats.onUpdateNetworkValidationState(
+ mNetworkValidationStatus, getDataNetworkType());
}
/**
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index b4aa1f0..aa461ff 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -2156,15 +2156,32 @@
}
/**
- * tethering and enterprise capabilities are not respected as restricted requests. For a request
- * with these capabilities, any soft disallowed reasons are honored.
+ * 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));
+
+ }
}
/**
@@ -3183,7 +3200,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");
diff --git a/src/java/com/android/internal/telephony/data/DataProfileManager.java b/src/java/com/android/internal/telephony/data/DataProfileManager.java
index 0da220b..21a0cec 100644
--- a/src/java/com/android/internal/telephony/data/DataProfileManager.java
+++ b/src/java/com/android/internal/telephony/data/DataProfileManager.java
@@ -939,7 +939,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 +966,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()
@@ -981,7 +982,7 @@
}
for (int j = i + 1; j < profiles.size(); j++) {
ApnSetting b = profiles.get(j).getApnSetting();
- if (b == null) continue;
+ if (b == null || b.getEditedStatus() != Telephony.Carriers.UNEDITED) continue;
String apnNameA = a.getApnName();
String apnNameB = b.getApnName();
if (TextUtils.equals(apnNameA, apnNameB)
diff --git a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
index c4eb9ca..5c1d0e1 100644
--- a/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
+++ b/src/java/com/android/internal/telephony/data/PhoneSwitcher.java
@@ -1562,6 +1562,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;
}
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index a6bb1d6..5366ebb 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -75,6 +75,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;
@@ -802,7 +803,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.
diff --git a/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java b/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
index c7ef625..0197e36 100644
--- a/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
+++ b/src/java/com/android/internal/telephony/metrics/DataConnectionStateTracker.java
@@ -16,6 +16,8 @@
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;
@@ -27,6 +29,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;
@@ -48,6 +51,7 @@
private HashMap<Integer, PreciseDataConnectionState> mLastPreciseDataConnectionState =
new HashMap<>();
private PreciseDataConnectionStateListenerImpl mDataConnectionStateListener;
+ private int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
new SubscriptionManager.OnSubscriptionsChangedListener() {
@@ -156,8 +160,37 @@
mPhone.getVoiceCallSessionStats().onPreciseDataConnectionStateChanged(connectionState);
}
+ 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 */
+ 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 PreciseDataConnectionStateListenerImpl extends TelephonyCallback
- implements TelephonyCallback.PreciseDataConnectionStateListener {
+ implements TelephonyCallback.PreciseDataConnectionStateListener,
+ TelephonyCallback.ActiveDataSubscriptionIdListener {
private final Executor mExecutor;
private TelephonyManager mTelephonyManager = null;
@@ -185,5 +218,13 @@
PreciseDataConnectionState connectionState) {
notifyDataConnectionStateChanged(connectionState);
}
+
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ if (dataRatMetricEnabled()) {
+ logRATChanges(subId);
+ mActiveDataSubId = subId;
+ }
+ }
}
}
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 456b91b..5eb0894 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -20,6 +20,7 @@
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;
@@ -72,6 +73,7 @@
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;
@@ -138,14 +140,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 +160,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;
@@ -227,6 +228,7 @@
registerAtom(SATELLITE_OUTGOING_DATAGRAM);
registerAtom(SATELLITE_PROVISION);
registerAtom(SATELLITE_SOS_MESSAGE_RECOMMENDER);
+ registerAtom(DATA_NETWORK_VALIDATION);
Rlog.d(TAG, "registered");
} else {
Rlog.e(TAG, "could not get StatsManager, atoms not registered");
@@ -234,6 +236,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 +323,8 @@
return pullSatelliteProvision(data);
case SATELLITE_SOS_MESSAGE_RECOMMENDER:
return pullSatelliteSosMessageRecommender(data);
+ case DATA_NETWORK_VALIDATION:
+ return pullDataNetworkValidation(data);
default:
Rlog.e(TAG, String.format("unexpected atom ID %d", atomTag));
return StatsManager.PULL_SKIP;
@@ -516,7 +523,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 +552,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 +581,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 +945,19 @@
}
}
+ 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;
+ }
+ }
+
/** Registers a pulled atom ID {@code atomId}. */
private void registerAtom(int atomId) {
mStatsManager.setPullAtomCallback(atomId, /* metadata= */ null,
@@ -1392,6 +1413,18 @@
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);
+ }
+
/** 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/PersistAtomsStorage.java b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
index f3fe8fa..8553b48 100644
--- a/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
+++ b/src/java/com/android/internal/telephony/metrics/PersistAtomsStorage.java
@@ -33,6 +33,7 @@
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;
@@ -173,6 +174,9 @@
private final int mMaxNumSatelliteStats;
private final int mMaxNumSatelliteControllerStats = 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 +227,7 @@
mMaxNumGbaEventStats = 5;
mMaxOutgoingShortCodeSms = 5;
mMaxNumSatelliteStats = 5;
+ mMaxNumDataNetworkValidation = 5;
} else {
mMaxNumVoiceCallSessions = 50;
mMaxNumSms = 25;
@@ -247,6 +252,7 @@
mMaxNumGbaEventStats = 10;
mMaxOutgoingShortCodeSms = 10;
mMaxNumSatelliteStats = 15;
+ mMaxNumDataNetworkValidation = 15;
}
mAtoms = loadAtomsFromFile();
@@ -791,6 +797,25 @@
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);
+ }
+
/**
* Returns and clears the voice call sessions if last pulled longer than {@code
* minIntervalMillis} ago, otherwise returns {@code null}.
@@ -1449,6 +1474,24 @@
}
}
+ /**
+ * 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;
+ }
+ }
+
/** Saves {@link PersistAtoms} to a file in private storage immediately. */
public synchronized void flushAtoms() {
saveAtomsToFile(0);
@@ -1599,6 +1642,12 @@
atoms.satelliteSosMessageRecommender = sanitizeAtoms(
atoms.satelliteSosMessageRecommender, SatelliteSosMessageRecommender.class,
mMaxNumSatelliteStats);
+ atoms.dataNetworkValidation =
+ sanitizeAtoms(
+ atoms.dataNetworkValidation,
+ DataNetworkValidation.class,
+ mMaxNumDataNetworkValidation
+ );
// out of caution, sanitize also the timestamps
atoms.voiceCallRatUsagePullTimestampMillis =
@@ -1661,6 +1710,8 @@
sanitizeTimestamp(atoms.satelliteProvisionPullTimestampMillis);
atoms.satelliteSosMessageRecommenderPullTimestampMillis =
sanitizeTimestamp(atoms.satelliteSosMessageRecommenderPullTimestampMillis);
+ atoms.dataNetworkValidationPullTimestampMillis =
+ sanitizeTimestamp(atoms.dataNetworkValidationPullTimestampMillis);
return atoms;
} catch (NoSuchFileException e) {
Rlog.d(TAG, "PersistAtoms file not found");
@@ -2084,6 +2135,24 @@
}
/**
+ * 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;
+ }
+
+
+ /**
* 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 +2408,7 @@
atoms.satelliteOutgoingDatagramPullTimestampMillis = currentTime;
atoms.satelliteProvisionPullTimestampMillis = currentTime;
atoms.satelliteSosMessageRecommenderPullTimestampMillis = currentTime;
+ atoms.dataNetworkValidationPullTimestampMillis = currentTime;
Rlog.d(TAG, "created new PersistAtoms");
return atoms;
diff --git a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
index d400c22..91b191f 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,6 +40,7 @@
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;
@@ -61,6 +64,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);
@@ -140,6 +145,10 @@
addServiceStateAndSwitch(
prevState, now, getDataServiceSwitch(prevState.mServiceState, newState));
}
+
+ if (dataRatMetricEnabled()) {
+ writeDataRatAtom(serviceState);
+ }
}
/** Updates the fold state of the device for the current service state. */
@@ -456,6 +465,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/security/CellularNetworkSecuritySafetySource.java b/src/java/com/android/internal/telephony/security/CellularNetworkSecuritySafetySource.java
index 34f26e3..605b197 100644
--- a/src/java/com/android/internal/telephony/security/CellularNetworkSecuritySafetySource.java
+++ b/src/java/com/android/internal/telephony/security/CellularNetworkSecuritySafetySource.java
@@ -25,6 +25,8 @@
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;
@@ -62,10 +64,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 +121,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.
*/
@@ -216,7 +221,8 @@
builder = new SafetySourceIssue.Builder(
NULL_CIPHER_ISSUE_NON_ENCRYPTED_ID + "_" + subId,
context.getString(
- R.string.scNullCipherIssueNonEncryptedTitle, subInfo.getDisplayName()),
+ R.string.scNullCipherIssueNonEncryptedTitle,
+ subInfo.getDisplayName()),
context.getString(R.string.scNullCipherIssueNonEncryptedSummary),
SEVERITY_LEVEL_RECOMMENDATION,
NULL_CIPHER_ISSUE_NON_ENCRYPTED_ID);
@@ -225,7 +231,7 @@
builder = new SafetySourceIssue.Builder(
NULL_CIPHER_ISSUE_NON_ENCRYPTED_ID + "_" + subId,
context.getString(
- R.string.scNullCipherIssueEncryptedTitle, subInfo.getDisplayName()),
+ R.string.scNullCipherIssueEncryptedTitle, subInfo.getDisplayName()),
context.getString(R.string.scNullCipherIssueEncryptedSummary),
SEVERITY_LEVEL_INFORMATION,
NULL_CIPHER_ISSUE_ENCRYPTED_ID);
@@ -233,26 +239,31 @@
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_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());
+ .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,7 +275,8 @@
SubscriptionInfoInternal subInfo =
mSubscriptionManagerService.getSubscriptionInfoInternal(subId);
- return Optional.of(
+
+ SafetySourceIssue.Builder builder =
new SafetySourceIssue.Builder(
IDENTIFIER_DISCLOSURE_ISSUE_ID + "_" + subId,
context.getString(R.string.scIdentifierDisclosureIssueTitle),
@@ -276,23 +288,51 @@
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_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());
+
+ 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());
+ }
+
+ /**
+ * 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 +377,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/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index bae43b6..d96c549 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -3721,16 +3721,15 @@
enforceTelephonyFeatureWithException(callingPackage, "getPhoneNumber");
final long identity = Binder.clearCallingIdentity();
-
- SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager
- .getSubscriptionInfoInternal(subId);
-
- if (subInfo == null) {
- loge("Invalid sub id " + subId + ", callingPackage=" + callingPackage);
- return "";
- }
-
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));
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/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/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/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 614846b..ba08f8b 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -3019,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/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/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java
index fecadd6..0ef6fe7 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;
@@ -1745,6 +1746,107 @@
}
@Test
+ public void testMobileDataDisabledIsValidRestrictedRequestWithSatelliteInternetRequest() {
+ mIsNonTerrestrialNetwork = true;
+
+ //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);
+
+ // 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 not connected since Network request cannot satisfy by transport
+ verify(mMockedDataNetworkControllerCallback, never())
+ .onConnectedInternetDataNetworksChanged(any());
+
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @Test
+ public void testMobileDataDisabledIsValidRestrictedRequestWithTransportSatelliteMMSRequest()
+ throws Exception {
+ mIsNonTerrestrialNetwork = true;
+
+ // 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);
+
+ // 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 not connected
+ verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
+
+ mIsNonTerrestrialNetwork = false;
+ }
+
+ @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();
@@ -4050,6 +4152,41 @@
}
@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);
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 19502f5..3676900 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -256,12 +256,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();
@@ -2245,6 +2251,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(
@@ -2332,6 +2383,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));
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 1f9ace9..8420acf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/PhoneSwitcherTest.java
@@ -1518,6 +1518,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();
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/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..35f1bb7 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
@@ -70,8 +70,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
@@ -402,6 +402,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 +412,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);
}
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 75ef7ec..bc79a56 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/PersistAtomsStorageTest.java
@@ -62,10 +62,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;
@@ -76,6 +79,7 @@
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;
@@ -286,6 +290,12 @@
private SatelliteSosMessageRecommender mSatelliteSosMessageRecommender2;
private SatelliteSosMessageRecommender[] mSatelliteSosMessageRecommenders;
+ private DataNetworkValidation mDataNetworkValidationLte1;
+ private DataNetworkValidation mDataNetworkValidationLte2;
+ private DataNetworkValidation mDataNetworkValidationIwlan1;
+ private DataNetworkValidation mDataNetworkValidationIwlan2;
+ private DataNetworkValidation[] mDataNetworkValidations;
+
private void makeTestData() {
// MO call with SRVCC (LTE to UMTS)
mCall1Proto = new VoiceCallSession();
@@ -1070,6 +1080,10 @@
mOutgoingShortCodeSms = new OutgoingShortCodeSms[] {mOutgoingShortCodeSms1,
mOutgoingShortCodeSms2};
+
+ generateTestSatelliteData();
+
+ generateTestDataNetworkValidationsData();
}
private void generateTestSatelliteData() {
@@ -1216,6 +1230,61 @@
};
}
+ 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 {
private long mTimeMillis = START_TIME_MILLIS;
@@ -1381,6 +1450,10 @@
mSatelliteSosMessageRecommender1 = null;
mSatelliteSosMessageRecommender2 = null;
mSatelliteSosMessageRecommenders = null;
+ mDataNetworkValidationLte1 = null;
+ mDataNetworkValidationLte2 = null;
+ mDataNetworkValidationIwlan1 = null;
+ mDataNetworkValidationIwlan2 = null;
super.tearDown();
}
@@ -4513,6 +4586,77 @@
@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);
mPersistAtomsStorage = new TestablePersistAtomsStorage(mContext);
@@ -4596,6 +4740,8 @@
atoms.satelliteProvisionPullTimestampMillis = lastPullTimeMillis;
atoms.satelliteSosMessageRecommender = mSatelliteSosMessageRecommenders;
atoms.satelliteSosMessageRecommenderPullTimestampMillis = lastPullTimeMillis;
+ atoms.dataNetworkValidation = mDataNetworkValidations;
+ atoms.dataNetworkValidationPullTimestampMillis = lastPullTimeMillis;
FileOutputStream stream = new FileOutputStream(mTestFile);
stream.write(PersistAtoms.toByteArray(atoms));
stream.close();
@@ -4759,6 +4905,11 @@
return SatelliteSosMessageRecommender.parseFrom(MessageNano.toByteArray(source));
}
+ private static DataNetworkValidation copyOf(DataNetworkValidation source)
+ throws Exception {
+ return DataNetworkValidation.parseFrom(MessageNano.toByteArray(source));
+ }
+
private void assertAllPullTimestampEquals(long timestamp) {
assertEquals(
timestamp,
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..77759a0 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,6 +78,8 @@
mContextFixture.putResource(R.string.scCellularNetworkSecurityTitle, "fake");
mContextFixture.putResource(R.string.scCellularNetworkSecuritySummary, "fake");
+ mContextFixture.putResource(R.string.scCellularNetworkSecurityLearnMore,
+ "https://support.google.com/android?p=cellular_security");
mContextFixture.putResource(R.string.scNullCipherIssueNonEncryptedTitle, "fake %1$s");
mContextFixture.putResource(R.string.scNullCipherIssueNonEncryptedSummary, "fake");
mContextFixture.putResource(R.string.scNullCipherIssueEncryptedTitle, "fake %1$s");
@@ -172,6 +176,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 +269,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);
+ }
}